linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes
@ 2007-07-12 15:45 Joachim Fenkes
  2007-07-12 15:46 ` [PATCH 01/10] IB/ehca: Support for multiple event queues Joachim Fenkes
                   ` (10 more replies)
  0 siblings, 11 replies; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-12 15:45 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch

Building on top of the last patch series, this set of patches adds multi-EQ
support, fixes a few nits (including formatting), refactors the MR/MW code
and adds support for large page MRs. Another patch set will follow.

Note that patch 7 will introduce a few lines over 80 chars that will be
unindented in patch 8 - I hope that's okay with you.

The patches, in detail, are:

[01/10] adds support for multiple event queues (ie interrupt sources)
[02/10] fixes a problem with HW autodetection
[03/10] \
[04/10] |
[05/10] | These refactor and clean up the MR/MW code. We split them into
[06/10] | bite-sized chunks for easier review of the changes.
[07/10] |=20
[08/10] /=20
[09/10] fixes a lot of checkpatch.pl warnings
[10/10] adds large page MR support for eHCA2

The patches should apply cleanly, in order, against Roland's git. Please
review the changes and apply the patches if they are okay.

Regards,
  Joachim

=2D-=20
Joachim Fenkes =A0-- =A0eHCA Linux Driver Developer and Hardware Tamer
IBM Deutschland Entwicklung GmbH =A0-- =A0Dept. 3627 (I/O Firmware Dev. 2)
Schoenaicher Strasse 220 =A0-- =A071032 Boeblingen =A0-- =A0Germany
eMail: fenkes@de.ibm.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 01/10] IB/ehca: Support for multiple event queues
  2007-07-12 15:45 [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Joachim Fenkes
@ 2007-07-12 15:46 ` Joachim Fenkes
  2007-07-16 16:04   ` Roland Dreier
  2007-07-12 15:47 ` [PATCH 02/10] IB/ehca: Fix HW level autodetection Joachim Fenkes
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-12 15:46 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch

From: Hoang-Nam Nguyen <hnguyen@de.ibm.com>

The eHCA driver can now handle multiple event queues (read: interrupt
sources) instead of one. The number of available EQs is selected via the
nr_eqs module parameter.

CQs are either assigned to the EQs based on the comp_vector index or, if the
dist_eqs module parameter is supplied, using a round-robin scheme.

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |   13 +++-
 drivers/infiniband/hw/ehca/ehca_cq.c      |   16 +++-
 drivers/infiniband/hw/ehca/ehca_eq.c      |  139 ++++++++++++++++++-----------
 drivers/infiniband/hw/ehca/ehca_irq.c     |   36 +++-----
 drivers/infiniband/hw/ehca/ehca_irq.h     |    8 +-
 drivers/infiniband/hw/ehca/ehca_iverbs.h  |    9 +-
 drivers/infiniband/hw/ehca/ehca_main.c    |  118 ++++++++++++++++++++-----
 drivers/infiniband/hw/ehca/ehca_qp.c      |    2 +-
 8 files changed, 233 insertions(+), 108 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index daf823e..b2d614a 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -72,7 +72,11 @@ struct ehca_eqe_cache_entry {
 	struct ehca_cq *cq;
 };
 
+struct ehca_shca;
+
 struct ehca_eq {
+	struct ehca_shca *shca;
+	char name[17];
 	u32 length;
 	struct ipz_queue ipz_queue;
 	struct ipz_eq_handle ipz_eq_handle;
@@ -100,6 +104,7 @@ struct ehca_sport {
 	struct ehca_sma_attr saved_attr;
 };
 
+#define EHCA_MAX_NR_EQS 512
 struct ehca_shca {
 	struct ib_device ib_device;
 	struct ibmebus_dev *ibmebus_dev;
@@ -108,14 +113,16 @@ struct ehca_shca {
 	struct list_head shca_list;
 	struct ipz_adapter_handle ipz_hca_handle;
 	struct ehca_sport sport[2];
-	struct ehca_eq eq;
-	struct ehca_eq neq;
+	struct ehca_eq **eqs;
+	struct ehca_eq *aeq; /* async event for qps */
+	struct ehca_eq *neq;
 	struct ehca_mr *maxmr;
 	struct ehca_pd *pd;
 	struct h_galpas galpas;
 	struct mutex modify_mutex;
 	u64 hca_cap;
 	int max_mtu;
+	atomic_t cur_eq_idx;
 };
 
 struct ehca_pd {
@@ -290,6 +297,8 @@ struct ehca_ucontext {
 
 int ehca_init_pd_cache(void);
 void ehca_cleanup_pd_cache(void);
+int ehca_init_eq_cache(void);
+void ehca_cleanup_eq_cache(void);
 int ehca_init_cq_cache(void);
 void ehca_cleanup_cq_cache(void);
 int ehca_init_qp_cache(void);
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 01d4a14..97da51e 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -117,6 +117,8 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
 			     struct ib_ucontext *context,
 			     struct ib_udata *udata)
 {
+	extern int ehca_nr_eqs;
+	extern int ehca_dist_eqs;
 	static const u32 additional_cqe = 20;
 	struct ib_cq *cq;
 	struct ehca_cq *my_cq;
@@ -134,6 +136,12 @@ 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 (comp_vector < 0 || comp_vector >= ehca_nr_eqs) {
+		ehca_err(device, "Invalid comp_vector=%x ehca_nr_eqs=%x",
+			 comp_vector, ehca_nr_eqs);
+		return ERR_PTR(-EINVAL);
+	}
+
 	my_cq = kmem_cache_zalloc(cq_cache, GFP_KERNEL);
 	if (!my_cq) {
 		ehca_err(device, "Out of memory for ehca_cq struct device=%p",
@@ -153,7 +161,13 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
 	cq = &my_cq->ib_cq;
 
 	adapter_handle = shca->ipz_hca_handle;
-	param.eq_handle = shca->eq.ipz_eq_handle;
+	if (!ehca_dist_eqs)
+		param.eq_handle = shca->eqs[comp_vector]->ipz_eq_handle;
+	else {
+		u32 eq_idx = atomic_inc_return(&shca->cur_eq_idx) % ehca_nr_eqs;
+		param.eq_handle = shca->eqs[eq_idx]->ipz_eq_handle;
+		ehca_dbg(device, "assigned comp_vector=%x", eq_idx);
+	}
 
 	do {
 		if (!idr_pre_get(&ehca_cq_idr, GFP_KERNEL)) {
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
index 4961eb8..d443bcb 100644
--- a/drivers/infiniband/hw/ehca/ehca_eq.c
+++ b/drivers/infiniband/hw/ehca/ehca_eq.c
@@ -8,6 +8,7 @@
  *           Reinhard Ernst <rernst@de.ibm.com>
  *           Heiko J Schick <schickhj@de.ibm.com>
  *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Joachim Fenkes <fenkes@de.ibm.com>
  *
  *
  *  Copyright (c) 2005 IBM Corporation
@@ -50,40 +51,54 @@
 #include "hcp_if.h"
 #include "ipz_pt_fn.h"
 
-int ehca_create_eq(struct ehca_shca *shca,
-		   struct ehca_eq *eq,
-		   const enum ehca_eq_type type, const u32 length)
+static struct kmem_cache *eq_cache;
+
+struct ehca_eq *ehca_create_eq(struct ehca_shca *shca,
+			       const enum ehca_eq_type type, const u32 length)
 {
-	u64 ret;
+	struct ehca_eq *eq = NULL;
+	int ret;
+	u64 h_ret;
 	u32 nr_pages;
 	u32 i;
 	void *vpage;
 	struct ib_device *ib_dev = &shca->ib_device;
 
-	spin_lock_init(&eq->spinlock);
-	spin_lock_init(&eq->irq_spinlock);
-	eq->is_initialized = 0;
+	if (!length) {
+		ehca_err(ib_dev, "EQ length must not be zero.");
+		return ERR_PTR(-EINVAL);
+	}
 
 	if (type != EHCA_EQ && type != EHCA_NEQ) {
-		ehca_err(ib_dev, "Invalid EQ type %x. eq=%p", type, eq);
-		return -EINVAL;
+		ehca_err(ib_dev, "Invalid EQ type %x", type);
+		return ERR_PTR(-EINVAL);
 	}
-	if (!length) {
-		ehca_err(ib_dev, "EQ length must not be zero. eq=%p", eq);
-		return -EINVAL;
+
+	eq = kmem_cache_zalloc(eq_cache, GFP_KERNEL);
+	if (!eq) {
+		ehca_err(ib_dev, "Out of memory for ehca_eq struct device=%p",
+			 ib_dev);
+		return ERR_PTR(-ENOMEM);
 	}
 
-	ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle,
-				       &eq->pf,
-				       type,
-				       length,
-				       &eq->ipz_eq_handle,
-				       &eq->length,
-				       &nr_pages, &eq->ist);
+	spin_lock_init(&eq->spinlock);
+	spin_lock_init(&eq->irq_spinlock);
+	eq->is_initialized = 0;
+	eq->shca = shca;
 
-	if (ret != H_SUCCESS) {
-		ehca_err(ib_dev, "Can't allocate EQ/NEQ. eq=%p", eq);
-		return -EINVAL;
+	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 (h_ret != H_SUCCESS) {
+		ehca_err(ib_dev, "Can't allocate EQ/NEQ. eq=%p h_ret=%lx",
+			 eq, h_ret);
+		ret = -EINVAL;
+		goto create_eq_exit0;
 	}
 
 	ret = ipz_queue_ctor(&eq->ipz_queue, nr_pages,
@@ -97,51 +112,51 @@ int ehca_create_eq(struct ehca_shca *shca,
 		u64 rpage;
 
 		if (!(vpage = ipz_qpageit_get_inc(&eq->ipz_queue))) {
-			ret = H_RESOURCE;
+			ret = -ENOMEM;
 			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) {
+				ret = -ENOMEM;
 				goto create_eq_exit2;
+			}
 		} else {
-			if (ret != H_PAGE_REGISTERED || !vpage)
+			if (h_ret != H_PAGE_REGISTERED || !vpage) {
+				ret = -ENOMEM;
 				goto create_eq_exit2;
+			}
 		}
 	}
 
 	ipz_qeit_reset(&eq->ipz_queue);
 
 	/* register interrupt handlers and initialize work queues */
-	if (type == EHCA_EQ) {
-		ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_eq,
-					  IRQF_DISABLED, "ehca_eq",
-					  (void *)shca);
-		if (ret < 0)
-			ehca_err(ib_dev, "Can't map interrupt handler.");
-
-		tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);
-	} else if (type == EHCA_NEQ) {
-		ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_neq,
-					  IRQF_DISABLED, "ehca_neq",
-					  (void *)shca);
-		if (ret < 0)
-			ehca_err(ib_dev, "Can't map interrupt handler.");
-
-		tasklet_init(&eq->interrupt_task, ehca_tasklet_neq, (long)shca);
-	}
+	if (type == EHCA_EQ)
+		snprintf(eq->name, sizeof(eq->name), "ehca_eq_%x", eq->ist);
+	else
+		snprintf(eq->name, sizeof(eq->name), "ehca_neq");
+
+	ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt,
+				  IRQF_DISABLED, eq->name, (void *)eq);
+	if (ret < 0)
+		ehca_err(ib_dev, "Can't map interrupt handler.");
+
+	tasklet_init(&eq->interrupt_task,
+		     (type == EHCA_EQ) ? ehca_tasklet_eq : ehca_tasklet_neq,
+		     (long)eq);
 
 	eq->is_initialized = 1;
 
-	return 0;
+	return eq;
 
 create_eq_exit2:
 	ipz_queue_dtor(&eq->ipz_queue);
@@ -149,10 +164,13 @@ create_eq_exit2:
 create_eq_exit1:
 	hipz_h_destroy_eq(shca->ipz_hca_handle, eq);
 
-	return -EINVAL;
+create_eq_exit0:
+	kmem_cache_free(eq_cache, eq);
+
+	return ERR_PTR(ret);
 }
 
-void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq)
+void *ehca_poll_eq(struct ehca_eq *eq)
 {
 	unsigned long flags;
 	void *eqe;
@@ -164,13 +182,14 @@ void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq)
 	return eqe;
 }
 
-int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq)
+int ehca_destroy_eq(struct ehca_eq *eq)
 {
+	struct ehca_shca *shca = eq->shca;
 	unsigned long flags;
 	u64 h_ret;
 
 	spin_lock_irqsave(&eq->spinlock, flags);
-	ibmebus_free_irq(NULL, eq->ist, (void *)shca);
+	ibmebus_free_irq(NULL, eq->ist, (void *)eq);
 
 	h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq);
 
@@ -181,6 +200,24 @@ int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq)
 		return -EINVAL;
 	}
 	ipz_queue_dtor(&eq->ipz_queue);
+	kmem_cache_free(eq_cache, eq);
 
 	return 0;
 }
+
+int ehca_init_eq_cache(void)
+{
+	eq_cache = kmem_cache_create("ehca_cache_eq",
+				     sizeof(struct ehca_eq), 0,
+				     SLAB_HWCACHE_ALIGN,
+				     NULL, NULL);
+	if (!eq_cache)
+		return -ENOMEM;
+	return 0;
+}
+
+void ehca_cleanup_eq_cache(void)
+{
+	if (eq_cache)
+		kmem_cache_destroy(eq_cache);
+}
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 96eba38..7a4071a 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -389,32 +389,24 @@ static inline void reset_eq_pending(struct ehca_cq *cq)
 	return;
 }
 
-irqreturn_t ehca_interrupt_neq(int irq, void *dev_id)
-{
-	struct ehca_shca *shca = (struct ehca_shca*)dev_id;
-
-	tasklet_hi_schedule(&shca->neq.interrupt_task);
-
-	return IRQ_HANDLED;
-}
-
 void ehca_tasklet_neq(unsigned long data)
 {
-	struct ehca_shca *shca = (struct ehca_shca*)data;
+	struct ehca_eq *neq = (struct ehca_eq *)data;
+	struct ehca_shca *shca = neq->shca;
 	struct ehca_eqe *eqe;
 	u64 ret;
 
-	eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->neq);
+	eqe = (struct ehca_eqe *)ehca_poll_eq(neq);
 
 	while (eqe) {
 		if (!EHCA_BMASK_GET(NEQE_COMPLETION_EVENT, eqe->entry))
 			parse_ec(shca, eqe->entry);
 
-		eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->neq);
+		eqe = (struct ehca_eqe *)ehca_poll_eq(neq);
 	}
 
 	ret = hipz_h_reset_event(shca->ipz_hca_handle,
-				 shca->neq.ipz_eq_handle, 0xFFFFFFFFFFFFFFFFL);
+				 neq->ipz_eq_handle, 0xFFFFFFFFFFFFFFFFL);
 
 	if (ret != H_SUCCESS)
 		ehca_err(&shca->ib_device, "Can't clear notification events.");
@@ -422,11 +414,11 @@ void ehca_tasklet_neq(unsigned long data)
 	return;
 }
 
-irqreturn_t ehca_interrupt_eq(int irq, void *dev_id)
+irqreturn_t ehca_interrupt(int irq, void *dev_id)
 {
-	struct ehca_shca *shca = (struct ehca_shca*)dev_id;
+	struct ehca_eq *eq = (struct ehca_eq *)dev_id;
 
-	tasklet_hi_schedule(&shca->eq.interrupt_task);
+	tasklet_hi_schedule(&eq->interrupt_task);
 
 	return IRQ_HANDLED;
 }
@@ -468,9 +460,9 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
 	}
 }
 
-void ehca_process_eq(struct ehca_shca *shca, int is_irq)
+void ehca_process_eq(struct ehca_eq *eq, int is_irq)
 {
-	struct ehca_eq *eq = &shca->eq;
+	struct ehca_shca *shca = eq->shca;
 	struct ehca_eqe_cache_entry *eqe_cache = eq->eqe_cache;
 	u64 eqe_value;
 	unsigned long flags;
@@ -498,7 +490,7 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
 	do {
 		u32 token;
 		eqe_cache[eqe_cnt].eqe =
-			(struct ehca_eqe *)ehca_poll_eq(shca, eq);
+			(struct ehca_eqe *)ehca_poll_eq(eq);
 		if (!eqe_cache[eqe_cnt].eqe)
 			break;
 		eqe_value = eqe_cache[eqe_cnt].eqe->entry;
@@ -535,7 +527,7 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
 	}
 	/* check eq */
 	spin_lock(&eq->spinlock);
-	eq_empty = (!ipz_eqit_eq_peek_valid(&shca->eq.ipz_queue));
+	eq_empty = (!ipz_eqit_eq_peek_valid(&eq->ipz_queue));
 	spin_unlock(&eq->spinlock);
 	/* call completion handler for cached eqes */
 	for (i = 0; i < eqe_cnt; i++)
@@ -557,7 +549,7 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
 		goto unlock_irq_spinlock;
 	do {
 		struct ehca_eqe *eqe;
-		eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq);
+		eqe = (struct ehca_eqe *)ehca_poll_eq(eq);
 		if (!eqe)
 			break;
 		process_eqe(shca, eqe);
@@ -569,7 +561,7 @@ unlock_irq_spinlock:
 
 void ehca_tasklet_eq(unsigned long data)
 {
-	ehca_process_eq((struct ehca_shca*)data, 1);
+	ehca_process_eq((struct ehca_eq *)data, 1);
 }
 
 static inline int find_next_online_cpu(struct ehca_comp_pool* pool)
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.h b/drivers/infiniband/hw/ehca/ehca_irq.h
index 3346cb0..18d5397 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.h
+++ b/drivers/infiniband/hw/ehca/ehca_irq.h
@@ -50,12 +50,10 @@ struct ehca_shca;
 
 int ehca_error_data(struct ehca_shca *shca, void *data, u64 resource);
 
-irqreturn_t ehca_interrupt_neq(int irq, void *dev_id);
-void ehca_tasklet_neq(unsigned long data);
-
-irqreturn_t ehca_interrupt_eq(int irq, void *dev_id);
+irqreturn_t ehca_interrupt(int irq, void *dev_id);
 void ehca_tasklet_eq(unsigned long data);
-void ehca_process_eq(struct ehca_shca *shca, int is_irq);
+void ehca_tasklet_neq(unsigned long data);
+void ehca_process_eq(struct ehca_eq *eq, int is_irq);
 
 struct ehca_cpu_comp_task {
 	wait_queue_head_t wait_queue;
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index 77aeca6..bf8fbf7 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -117,13 +117,12 @@ enum ehca_eq_type {
 	EHCA_NEQ     /* Notification Event Queue */
 };
 
-int ehca_create_eq(struct ehca_shca *shca, struct ehca_eq *eq,
-		   enum ehca_eq_type type, const u32 length);
+struct ehca_eq *ehca_create_eq(struct ehca_shca *shca,
+			       const enum ehca_eq_type type, const u32 length);
 
-int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq);
-
-void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq);
+int ehca_destroy_eq(struct ehca_eq *eq);
 
+void *ehca_poll_eq(struct ehca_eq *eq);
 
 struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
 			     struct ib_ucontext *context,
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 28ba2dd..d9a37dc 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -63,6 +63,8 @@ int ehca_port_act_time = 30;
 int ehca_poll_all_eqs  = 1;
 int ehca_static_rate   = -1;
 int ehca_scaling_code  = 0;
+int ehca_nr_eqs        = 2;
+int ehca_dist_eqs      = 0;
 
 module_param_named(open_aqp1,     ehca_open_aqp1,     int, 0);
 module_param_named(debug_level,   ehca_debug_level,   int, 0);
@@ -72,7 +74,9 @@ module_param_named(use_hp_mr,     ehca_use_hp_mr,     int, 0);
 module_param_named(port_act_time, ehca_port_act_time, int, 0);
 module_param_named(poll_all_eqs,  ehca_poll_all_eqs,  int, 0);
 module_param_named(static_rate,   ehca_static_rate,   int, 0);
-module_param_named(scaling_code,   ehca_scaling_code,   int, 0);
+module_param_named(scaling_code,  ehca_scaling_code,  int, 0);
+module_param_named(nr_eqs,        ehca_nr_eqs,        int, 0);
+module_param_named(dist_eqs,      ehca_dist_eqs,      int, 0);
 
 MODULE_PARM_DESC(open_aqp1,
 		 "AQP1 on startup (0: no (default), 1: yes)");
@@ -95,6 +99,11 @@ 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(nr_eqs,
+		 "set number of event queues (default : 2)");
+MODULE_PARM_DESC(dist_eqs,
+		 "enable distributing EQs across CQs "
+		 "(0: disabled/default, 1: enabled)");
 
 DEFINE_RWLOCK(ehca_qp_idr_lock);
 DEFINE_RWLOCK(ehca_cq_idr_lock);
@@ -135,6 +144,12 @@ static int ehca_create_slab_caches(void)
 		return ret;
 	}
 
+	ret = ehca_init_eq_cache();
+	if (ret) {
+		ehca_gen_err("Cannot create EQ SLAB cache.");
+		goto create_slab_caches1;
+	}
+
 	ret = ehca_init_cq_cache();
 	if (ret) {
 		ehca_gen_err("Cannot create CQ SLAB cache.");
@@ -182,6 +197,9 @@ create_slab_caches3:
 	ehca_cleanup_cq_cache();
 
 create_slab_caches2:
+	ehca_cleanup_eq_cache();
+
+create_slab_caches1:
 	ehca_cleanup_pd_cache();
 
 	return ret;
@@ -193,6 +211,7 @@ static void ehca_destroy_slab_caches(void)
 	ehca_cleanup_av_cache();
 	ehca_cleanup_qp_cache();
 	ehca_cleanup_cq_cache();
+	ehca_cleanup_eq_cache();
 	ehca_cleanup_pd_cache();
 #ifdef CONFIG_PPC_64K_PAGES
 	if (ctblk_cache)
@@ -362,7 +381,7 @@ int ehca_init_device(struct ehca_shca *shca)
 
 	shca->ib_device.node_type           = RDMA_NODE_IB_CA;
 	shca->ib_device.phys_port_cnt       = shca->num_ports;
-	shca->ib_device.num_comp_vectors    = 1;
+	shca->ib_device.num_comp_vectors    = ehca_nr_eqs;
 	shca->ib_device.dma_device          = &shca->ibmebus_dev->ofdev.dev;
 	shca->ib_device.query_device        = ehca_query_device;
 	shca->ib_device.query_port          = ehca_query_port;
@@ -585,6 +604,15 @@ 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_nr_eqs(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	return sprintf(buf, "%d\n", ehca_nr_eqs);
+}
+
+static DEVICE_ATTR(nr_eqs, S_IRUGO, ehca_show_nr_eqs, NULL);
+
 static struct attribute *ehca_dev_attrs[] = {
 	&dev_attr_adapter_handle.attr,
 	&dev_attr_num_ports.attr,
@@ -601,6 +629,7 @@ static struct attribute *ehca_dev_attrs[] = {
 	&dev_attr_cur_mw.attr,
 	&dev_attr_max_pd.attr,
 	&dev_attr_max_ah.attr,
+	&dev_attr_nr_eqs.attr,
 	NULL
 };
 
@@ -608,13 +637,27 @@ static struct attribute_group ehca_dev_attr_grp = {
 	.attrs = ehca_dev_attrs
 };
 
+static void destroy_all_eqs(struct ehca_shca *shca)
+{
+	int ret, i;
+
+	for (i = 0; i < ehca_nr_eqs && shca->eqs[i]; i++) {
+		ret = ehca_destroy_eq(shca->eqs[i]);
+		if (ret)
+			ehca_err(&shca->ib_device, "Cannot destroy EQ "
+				 "ret=%x i=%x eq=%p", ret, i, shca->eqs[i]);
+	}
+
+	kfree(shca->eqs);
+}
+
 static int __devinit ehca_probe(struct ibmebus_dev *dev,
 				const struct of_device_id *id)
 {
 	struct ehca_shca *shca;
 	const u64 *handle;
 	struct ib_pd *ibpd;
-	int ret;
+	int ret, i;
 
 	handle = of_get_property(dev->ofdev.node, "ibm,hca-handle", NULL);
 	if (!handle) {
@@ -648,19 +691,35 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
 
 	ret = ehca_init_device(shca);
 	if (ret) {
-		ehca_gen_err("Cannot init ehca  device struct");
+		ehca_gen_err("Cannot init ehca device struct");
 		goto probe1;
 	}
 
 	/* create event queues */
-	ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, 2048);
-	if (ret) {
-		ehca_err(&shca->ib_device, "Cannot create EQ.");
+	shca->eqs = kzalloc(ehca_nr_eqs * sizeof(*shca->eqs), GFP_KERNEL);
+	if (!shca->eqs) {
+		ehca_gen_err("Cannot alloc eqs array");
 		goto probe1;
 	}
 
-	ret = ehca_create_eq(shca, &shca->neq, EHCA_NEQ, 513);
-	if (ret) {
+	for (i = 0; i < ehca_nr_eqs; i++) {
+		shca->eqs[i] = ehca_create_eq(shca, EHCA_EQ, 2048);
+		if (IS_ERR(shca->eqs[i])) {
+			ehca_err(&shca->ib_device, "Cannot create EQ.");
+			ret = PTR_ERR(shca->eqs[i]);
+			shca->eqs[i] = NULL;
+			goto probe2;
+		}
+	}
+
+	shca->aeq = ehca_create_eq(shca, EHCA_EQ, 2048);
+	if (IS_ERR(shca->aeq)) {
+		ehca_err(&shca->ib_device, "Cannot create AEQ.");
+		goto probe2;
+	}
+
+	shca->neq = ehca_create_eq(shca, EHCA_NEQ, 513);
+	if (IS_ERR(shca->neq)) {
 		ehca_err(&shca->ib_device, "Cannot create NEQ.");
 		goto probe3;
 	}
@@ -747,16 +806,20 @@ probe5:
 			 "Cannot destroy internal PD. ret=%x", ret);
 
 probe4:
-	ret = ehca_destroy_eq(shca, &shca->neq);
+	ret = ehca_destroy_eq(shca->neq);
 	if (ret)
 		ehca_err(&shca->ib_device,
 			 "Cannot destroy NEQ. ret=%x", ret);
 
 probe3:
-	ret = ehca_destroy_eq(shca, &shca->eq);
+	ret = ehca_destroy_eq(shca->aeq);
 	if (ret)
 		ehca_err(&shca->ib_device,
-			 "Cannot destroy EQ. ret=%x", ret);
+			 "Cannot destroy AEQ. ret=%x", ret);
+
+probe2:
+	if (shca->eqs)
+		destroy_all_eqs(shca);
 
 probe1:
 	ib_dealloc_device(&shca->ib_device);
@@ -767,12 +830,11 @@ probe1:
 static int __devexit ehca_remove(struct ibmebus_dev *dev)
 {
 	struct ehca_shca *shca = dev->ofdev.dev.driver_data;
-	int ret;
+	int ret, i;
 
 	sysfs_remove_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp);
 
 	if (ehca_open_aqp1 == 1) {
-		int i;
 		for (i = 0; i < shca->num_ports; i++) {
 			ret = ehca_destroy_aqp1(&shca->sport[i]);
 			if (ret)
@@ -794,11 +856,14 @@ static int __devexit ehca_remove(struct ibmebus_dev *dev)
 		ehca_err(&shca->ib_device,
 			 "Cannot destroy internal PD. ret=%x", ret);
 
-	ret = ehca_destroy_eq(shca, &shca->eq);
+	if (shca->eqs)
+		destroy_all_eqs(shca);
+
+	ret = ehca_destroy_eq(shca->aeq);
 	if (ret)
-		ehca_err(&shca->ib_device, "Cannot destroy EQ. ret=%x", ret);
+		ehca_err(&shca->ib_device, "Canot destroy AEQ. ret=%x", ret);
 
-	ret = ehca_destroy_eq(shca, &shca->neq);
+	ret = ehca_destroy_eq(shca->neq);
 	if (ret)
 		ehca_err(&shca->ib_device, "Canot destroy NEQ. ret=%x", ret);
 
@@ -829,16 +894,20 @@ static struct ibmebus_driver ehca_driver = {
 
 void ehca_poll_eqs(unsigned long data)
 {
+	extern int ehca_nr_eqs;
 	struct ehca_shca *shca;
 
 	spin_lock(&shca_list_lock);
 	list_for_each_entry(shca, &shca_list, shca_list) {
-		if (shca->eq.is_initialized) {
-			/* call deadman proc only if eq ptr does not change */
-			struct ehca_eq *eq = &shca->eq;
+		int i;
+		for (i = 0; i < ehca_nr_eqs; i++) {
+			struct ehca_eq *eq = shca->eqs[i];
 			int max = 3;
 			volatile u64 q_ofs, q_ofs2;
 			u64 flags;
+			if (!eq || !eq->is_initialized)
+				continue;
+			/* call deadman proc only if eq ptr does not change */
 			spin_lock_irqsave(&eq->spinlock, flags);
 			q_ofs = eq->ipz_queue.current_q_offset;
 			spin_unlock_irqrestore(&eq->spinlock, flags);
@@ -849,7 +918,7 @@ void ehca_poll_eqs(unsigned long data)
 				max--;
 			} while (q_ofs == q_ofs2 && max > 0);
 			if (q_ofs == q_ofs2)
-				ehca_process_eq(shca, 0);
+				ehca_process_eq(eq, 0);
 		}
 	}
 	mod_timer(&poll_eqs_timer, jiffies + HZ);
@@ -863,6 +932,13 @@ int __init ehca_module_init(void)
 	printk(KERN_INFO "eHCA Infiniband Device Driver "
 	       "(Rel.: SVNEHCA_0023)\n");
 
+	if (ehca_nr_eqs < 1 || ehca_nr_eqs > EHCA_MAX_NR_EQS) {
+		ehca_gen_err("Invalid option nr_eqs=%x. "
+			     "Specify a number in range [1-%d].",
+			     ehca_nr_eqs, EHCA_MAX_NR_EQS);
+		return -EINVAL;
+	}
+
 	if ((ret = ehca_create_comp_pool())) {
 		ehca_gen_err("Cannot create comp pool.");
 		return ret;
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index 7467125..f6f4ef6 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -545,7 +545,7 @@ struct ehca_qp *internal_create_qp(struct ib_pd *pd,
 	}
 
 	parms.token = my_qp->token;
-	parms.eq_handle = shca->eq.ipz_eq_handle;
+	parms.eq_handle = shca->aeq->ipz_eq_handle;
 	parms.pd = my_pd->fw_pd;
 	if (my_qp->send_cq)
 		parms.send_cq_handle = my_qp->send_cq->ipz_cq_handle;
-- 
1.5.2

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 02/10] IB/ehca: Fix HW level autodetection
  2007-07-12 15:45 [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Joachim Fenkes
  2007-07-12 15:46 ` [PATCH 01/10] IB/ehca: Support for multiple event queues Joachim Fenkes
@ 2007-07-12 15:47 ` Joachim Fenkes
  2007-07-12 15:48 ` [PATCH 03/10] IB/ehca: fix memory leak in error path of ehca_get_dma_mr() Joachim Fenkes
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-12 15:47 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch

Autodetection was missing a few HW revisions, causing certain eHCA1
revisions to be treated like eHCA2. Fixed.

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_main.c |   29 +++++++++++++++++------------
 1 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index d9a37dc..57c551e 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -282,22 +282,27 @@ int ehca_sense_attributes(struct ehca_shca *shca)
 
 		ehca_gen_dbg(" ... hardware version=%x:%x", hcaaver, revid);
 
-		if ((hcaaver == 1) && (revid == 0))
-			shca->hw_level = 0x11;
-		else if ((hcaaver == 1) && (revid == 1))
-			shca->hw_level = 0x12;
-		else if ((hcaaver == 1) && (revid == 2))
-			shca->hw_level = 0x13;
-		else if ((hcaaver == 2) && (revid == 0))
-			shca->hw_level = 0x21;
-		else if ((hcaaver == 2) && (revid == 0x10))
-			shca->hw_level = 0x22;
-		else {
+		if (hcaaver == 1) {
+			if (revid <= 3)
+				shca->hw_level = 0x10 | (revid + 1);
+			else
+				shca->hw_level = 0x14;
+		} else if (hcaaver == 2) {
+			if (revid == 0)
+				shca->hw_level = 0x21;
+			else if (revid == 0x10)
+				shca->hw_level = 0x22;
+			else if (revid == 0x20 || revid == 0x21)
+				shca->hw_level = 0x23;
+		}
+
+		if (!shca->hw_level) {
 			ehca_gen_warn("unknown hardware version"
 				      " - assuming default level");
 			shca->hw_level = 0x22;
 		}
-	}
+	} else
+		shca->hw_level = ehca_hw_level;
 	ehca_gen_dbg(" ... hardware level=%x", shca->hw_level);
 
 	shca->sport[0].rate = IB_RATE_30_GBPS;
-- 
1.5.2

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 03/10] IB/ehca: fix memory leak in error path of ehca_get_dma_mr()
  2007-07-12 15:45 [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Joachim Fenkes
  2007-07-12 15:46 ` [PATCH 01/10] IB/ehca: Support for multiple event queues Joachim Fenkes
  2007-07-12 15:47 ` [PATCH 02/10] IB/ehca: Fix HW level autodetection Joachim Fenkes
@ 2007-07-12 15:48 ` Joachim Fenkes
  2007-07-12 15:49 ` [PATCH 04/10] IB/ehca: use common error code mapping instead of specific ones Joachim Fenkes
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-12 15:48 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch

From: Hoang-Nam Nguyen <hnguyen@de.ibm.com>

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_mrmw.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index add79bd..98f2531 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -111,6 +111,7 @@ struct ib_mr *ehca_get_dma_mr(struct ib_pd *pd, int mr_access_flags)
 				     &e_maxmr->ib.ib_mr.lkey,
 				     &e_maxmr->ib.ib_mr.rkey);
 		if (ret) {
+			ehca_mr_delete(e_maxmr);
 			ib_mr = ERR_PTR(ret);
 			goto get_dma_mr_exit0;
 		}
-- 
1.5.2

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 04/10] IB/ehca: use common error code mapping instead of specific ones
  2007-07-12 15:45 [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Joachim Fenkes
                   ` (2 preceding siblings ...)
  2007-07-12 15:48 ` [PATCH 03/10] IB/ehca: fix memory leak in error path of ehca_get_dma_mr() Joachim Fenkes
@ 2007-07-12 15:49 ` Joachim Fenkes
  2007-07-16 17:14   ` Roland Dreier
  2007-07-12 15:51 ` [PATCH 05/10] IB/ehca: use #define for "pages per register_rpage" instead of hardcoded value Joachim Fenkes
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-12 15:49 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch

From: Hoang-Nam Nguyen <hnguyen@de.ibm.com>

Instead of one error mapping function for each potential error source in
ehca_mrmw.c, use a centralized function that handles all cases, saving a
three-figure line count.

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_mrmw.c  |  195 ++-----------------------------
 drivers/infiniband/hw/ehca/ehca_mrmw.h  |   14 ---
 drivers/infiniband/hw/ehca/ehca_tools.h |    3 +
 3 files changed, 15 insertions(+), 197 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index 98f2531..7c1656a 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -537,7 +537,7 @@ int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr)
 			 "hca_hndl=%lx mr_hndl=%lx lkey=%x",
 			 h_ret, mr, shca->ipz_hca_handle.handle,
 			 e_mr->ipz_mr_handle.handle, mr->lkey);
-		ret = ehca_mrmw_map_hrc_query_mr(h_ret);
+		ret = ehca2ib_return_code(h_ret);
 		goto query_mr_exit1;
 	}
 	mr_attr->pd               = mr->pd;
@@ -597,7 +597,7 @@ int ehca_dereg_mr(struct ib_mr *mr)
 			 "e_mr=%p hca_hndl=%lx mr_hndl=%lx mr->lkey=%x",
 			 h_ret, shca, e_mr, shca->ipz_hca_handle.handle,
 			 e_mr->ipz_mr_handle.handle, mr->lkey);
-		ret = ehca_mrmw_map_hrc_free_mr(h_ret);
+		ret = ehca2ib_return_code(h_ret);
 		goto dereg_mr_exit0;
 	}
 
@@ -637,7 +637,7 @@ struct ib_mw *ehca_alloc_mw(struct ib_pd *pd)
 		ehca_err(pd->device, "hipz_mw_allocate failed, h_ret=%lx "
 			 "shca=%p hca_hndl=%lx mw=%p",
 			 h_ret, shca, shca->ipz_hca_handle.handle, e_mw);
-		ib_mw = ERR_PTR(ehca_mrmw_map_hrc_alloc(h_ret));
+		ib_mw = ERR_PTR(ehca2ib_return_code(h_ret));
 		goto alloc_mw_exit1;
 	}
 	/* successful MW allocation */
@@ -680,7 +680,7 @@ int ehca_dealloc_mw(struct ib_mw *mw)
 			 "mw=%p rkey=%x hca_hndl=%lx mw_hndl=%lx",
 			 h_ret, shca, mw, mw->rkey, shca->ipz_hca_handle.handle,
 			 e_mw->ipz_mw_handle.handle);
-		return ehca_mrmw_map_hrc_free_mw(h_ret);
+		return ehca2ib_return_code(h_ret);
 	}
 	/* successful deallocation */
 	ehca_mw_delete(e_mw);
@@ -923,7 +923,7 @@ int ehca_dealloc_fmr(struct ib_fmr *fmr)
 			 "hca_hndl=%lx fmr_hndl=%lx fmr->lkey=%x",
 			 h_ret, e_fmr, shca->ipz_hca_handle.handle,
 			 e_fmr->ipz_mr_handle.handle, fmr->lkey);
-		ret = ehca_mrmw_map_hrc_free_mr(h_ret);
+		ret = ehca2ib_return_code(h_ret);
 		goto free_fmr_exit0;
 	}
 	/* successful deregistration */
@@ -964,7 +964,7 @@ int ehca_reg_mr(struct ehca_shca *shca,
 	if (h_ret != H_SUCCESS) {
 		ehca_err(&shca->ib_device, "hipz_alloc_mr failed, h_ret=%lx "
 			 "hca_hndl=%lx", h_ret, shca->ipz_hca_handle.handle);
-		ret = ehca_mrmw_map_hrc_alloc(h_ret);
+		ret = ehca2ib_return_code(h_ret);
 		goto ehca_reg_mr_exit0;
 	}
 
@@ -1079,7 +1079,7 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
 					 shca->ipz_hca_handle.handle,
 					 e_mr->ipz_mr_handle.handle,
 					 e_mr->ib.ib_mr.lkey);
-				ret = ehca_mrmw_map_hrc_rrpg_last(h_ret);
+				ret = ehca2ib_return_code(h_ret);
 				break;
 			} else
 				ret = 0;
@@ -1090,7 +1090,7 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
 				 e_mr->ib.ib_mr.lkey,
 				 shca->ipz_hca_handle.handle,
 				 e_mr->ipz_mr_handle.handle);
-			ret = ehca_mrmw_map_hrc_rrpg_notlast(h_ret);
+			ret = ehca2ib_return_code(h_ret);
 			break;
 		} else
 			ret = 0;
@@ -1254,7 +1254,7 @@ int ehca_rereg_mr(struct ehca_shca *shca,
 				 h_ret, e_mr, shca->ipz_hca_handle.handle,
 				 e_mr->ipz_mr_handle.handle,
 				 e_mr->ib.ib_mr.lkey);
-			ret = ehca_mrmw_map_hrc_free_mr(h_ret);
+			ret = ehca2ib_return_code(h_ret);
 			goto ehca_rereg_mr_exit0;
 		}
 		/* clean ehca_mr_t, without changing struct ib_mr and lock */
@@ -1351,7 +1351,7 @@ int ehca_unmap_one_fmr(struct ehca_shca *shca,
 				 h_ret, e_fmr, shca->ipz_hca_handle.handle,
 				 e_fmr->ipz_mr_handle.handle,
 				 e_fmr->ib.ib_fmr.lkey);
-			ret = ehca_mrmw_map_hrc_free_mr(h_ret);
+			ret = ehca2ib_return_code(h_ret);
 			goto ehca_unmap_one_fmr_exit0;
 		}
 		/* clean ehca_mr_t, without changing lock */
@@ -1420,7 +1420,7 @@ int ehca_reg_smr(struct ehca_shca *shca,
 			 shca->ipz_hca_handle.handle,
 			 e_origmr->ipz_mr_handle.handle,
 			 e_origmr->ib.ib_mr.lkey);
-		ret = ehca_mrmw_map_hrc_reg_smr(h_ret);
+		ret = ehca2ib_return_code(h_ret);
 		goto ehca_reg_smr_exit0;
 	}
 	/* successful registration */
@@ -1539,7 +1539,7 @@ int ehca_reg_maxmr(struct ehca_shca *shca,
 			 h_ret, e_origmr, shca->ipz_hca_handle.handle,
 			 e_origmr->ipz_mr_handle.handle,
 			 e_origmr->ib.ib_mr.lkey);
-		return ehca_mrmw_map_hrc_reg_smr(h_ret);
+		return ehca2ib_return_code(h_ret);
 	}
 	/* successful registration */
 	e_newmr->num_pages     = e_origmr->num_pages;
@@ -2043,177 +2043,6 @@ void ehca_mrmw_reverse_map_acl(const u32 *hipz_acl,
 /*----------------------------------------------------------------------*/
 
 /*
- * map HIPZ rc to IB retcodes for MR/MW allocations
- * Used for hipz_mr_reg_alloc and hipz_mw_alloc.
- */
-int ehca_mrmw_map_hrc_alloc(const u64 hipz_rc)
-{
-	switch (hipz_rc) {
-	case H_SUCCESS:	             /* successful completion */
-		return 0;
-	case H_NOT_ENOUGH_RESOURCES: /* insufficient resources */
-	case H_CONSTRAINED:          /* resource constraint */
-	case H_NO_MEM:
-		return -ENOMEM;
-	case H_BUSY:                 /* long busy */
-		return -EBUSY;
-	default:
-		return -EINVAL;
-	}
-} /* end ehca_mrmw_map_hrc_alloc() */
-
-/*----------------------------------------------------------------------*/
-
-/*
- * map HIPZ rc to IB retcodes for MR register rpage
- * Used for hipz_h_register_rpage_mr at registering last page
- */
-int ehca_mrmw_map_hrc_rrpg_last(const u64 hipz_rc)
-{
-	switch (hipz_rc) {
-	case H_SUCCESS:         /* registration complete */
-		return 0;
-	case H_PAGE_REGISTERED:	/* page registered */
-	case H_ADAPTER_PARM:    /* invalid adapter handle */
-	case H_RH_PARM:         /* invalid resource handle */
-/*	case H_QT_PARM:            invalid queue type */
-	case H_PARAMETER:       /*
-				 * invalid logical address,
-				 * or count zero or greater 512
-				 */
-	case H_TABLE_FULL:      /* page table full */
-	case H_HARDWARE:        /* HCA not operational */
-		return -EINVAL;
-	case H_BUSY:            /* long busy */
-		return -EBUSY;
-	default:
-		return -EINVAL;
-	}
-} /* end ehca_mrmw_map_hrc_rrpg_last() */
-
-/*----------------------------------------------------------------------*/
-
-/*
- * map HIPZ rc to IB retcodes for MR register rpage
- * Used for hipz_h_register_rpage_mr at registering one page, but not last page
- */
-int ehca_mrmw_map_hrc_rrpg_notlast(const u64 hipz_rc)
-{
-	switch (hipz_rc) {
-	case H_PAGE_REGISTERED:	/* page registered */
-		return 0;
-	case H_SUCCESS:         /* registration complete */
-	case H_ADAPTER_PARM:    /* invalid adapter handle */
-	case H_RH_PARM:         /* invalid resource handle */
-/*	case H_QT_PARM:            invalid queue type */
-	case H_PARAMETER:       /*
-				 * invalid logical address,
-				 * or count zero or greater 512
-				 */
-	case H_TABLE_FULL:      /* page table full */
-	case H_HARDWARE:        /* HCA not operational */
-		return -EINVAL;
-	case H_BUSY:            /* long busy */
-		return -EBUSY;
-	default:
-		return -EINVAL;
-	}
-} /* end ehca_mrmw_map_hrc_rrpg_notlast() */
-
-/*----------------------------------------------------------------------*/
-
-/* map HIPZ rc to IB retcodes for MR query. Used for hipz_mr_query. */
-int ehca_mrmw_map_hrc_query_mr(const u64 hipz_rc)
-{
-	switch (hipz_rc) {
-	case H_SUCCESS:	             /* successful completion */
-		return 0;
-	case H_ADAPTER_PARM:         /* invalid adapter handle */
-	case H_RH_PARM:              /* invalid resource handle */
-		return -EINVAL;
-	case H_BUSY:                 /* long busy */
-		return -EBUSY;
-	default:
-		return -EINVAL;
-	}
-} /* end ehca_mrmw_map_hrc_query_mr() */
-
-/*----------------------------------------------------------------------*/
-/*----------------------------------------------------------------------*/
-
-/*
- * map HIPZ rc to IB retcodes for freeing MR resource
- * Used for hipz_h_free_resource_mr
- */
-int ehca_mrmw_map_hrc_free_mr(const u64 hipz_rc)
-{
-	switch (hipz_rc) {
-	case H_SUCCESS:      /* resource freed */
-		return 0;
-	case H_ADAPTER_PARM: /* invalid adapter handle */
-	case H_RH_PARM:      /* invalid resource handle */
-	case H_R_STATE:      /* invalid resource state */
-	case H_HARDWARE:     /* HCA not operational */
-		return -EINVAL;
-	case H_RESOURCE:     /* Resource in use */
-	case H_BUSY:         /* long busy */
-		return -EBUSY;
-	default:
-		return -EINVAL;
-	}
-} /* end ehca_mrmw_map_hrc_free_mr() */
-
-/*----------------------------------------------------------------------*/
-
-/*
- * map HIPZ rc to IB retcodes for freeing MW resource
- * Used for hipz_h_free_resource_mw
- */
-int ehca_mrmw_map_hrc_free_mw(const u64 hipz_rc)
-{
-	switch (hipz_rc) {
-	case H_SUCCESS:	     /* resource freed */
-		return 0;
-	case H_ADAPTER_PARM: /* invalid adapter handle */
-	case H_RH_PARM:      /* invalid resource handle */
-	case H_R_STATE:      /* invalid resource state */
-	case H_HARDWARE:     /* HCA not operational */
-		return -EINVAL;
-	case H_RESOURCE:     /* Resource in use */
-	case H_BUSY:         /* long busy */
-		return -EBUSY;
-	default:
-		return -EINVAL;
-	}
-} /* end ehca_mrmw_map_hrc_free_mw() */
-
-/*----------------------------------------------------------------------*/
-
-/*
- * map HIPZ rc to IB retcodes for SMR registrations
- * Used for hipz_h_register_smr.
- */
-int ehca_mrmw_map_hrc_reg_smr(const u64 hipz_rc)
-{
-	switch (hipz_rc) {
-	case H_SUCCESS:	             /* successful completion */
-		return 0;
-	case H_ADAPTER_PARM:         /* invalid adapter handle */
-	case H_RH_PARM:              /* invalid resource handle */
-	case H_MEM_PARM:             /* invalid MR virtual address */
-	case H_MEM_ACCESS_PARM:      /* invalid access controls */
-	case H_NOT_ENOUGH_RESOURCES: /* insufficient resources */
-		return -EINVAL;
-	case H_BUSY:                 /* long busy */
-		return -EBUSY;
-	default:
-		return -EINVAL;
-	}
-} /* end ehca_mrmw_map_hrc_reg_smr() */
-
-/*----------------------------------------------------------------------*/
-
-/*
  * MR destructor and constructor
  * used in Reregister MR verb, sets all fields in ehca_mr_t to 0,
  * except struct ib_mr and spinlock
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.h b/drivers/infiniband/hw/ehca/ehca_mrmw.h
index d936e40..fb69ede 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.h
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.h
@@ -121,20 +121,6 @@ void ehca_mrmw_set_pgsize_hipz_acl(u32 *hipz_acl);
 void ehca_mrmw_reverse_map_acl(const u32 *hipz_acl,
 			       int *ib_acl);
 
-int ehca_mrmw_map_hrc_alloc(const u64 hipz_rc);
-
-int ehca_mrmw_map_hrc_rrpg_last(const u64 hipz_rc);
-
-int ehca_mrmw_map_hrc_rrpg_notlast(const u64 hipz_rc);
-
-int ehca_mrmw_map_hrc_query_mr(const u64 hipz_rc);
-
-int ehca_mrmw_map_hrc_free_mr(const u64 hipz_rc);
-
-int ehca_mrmw_map_hrc_free_mw(const u64 hipz_rc);
-
-int ehca_mrmw_map_hrc_reg_smr(const u64 hipz_rc);
-
 void ehca_mr_deletenew(struct ehca_mr *mr);
 
 #endif  /*_EHCA_MRMW_H_*/
diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h
index 03b185f..fd8238b 100644
--- a/drivers/infiniband/hw/ehca/ehca_tools.h
+++ b/drivers/infiniband/hw/ehca/ehca_tools.h
@@ -161,8 +161,11 @@ static inline int ehca2ib_return_code(u64 ehca_rc)
 	switch (ehca_rc) {
 	case H_SUCCESS:
 		return 0;
+	case H_RESOURCE:             /* Resource in use */
 	case H_BUSY:
 		return -EBUSY;
+	case H_NOT_ENOUGH_RESOURCES: /* insufficient resources */
+	case H_CONSTRAINED:          /* resource constraint */
 	case H_NO_MEM:
 		return -ENOMEM;
 	default:
-- 
1.5.2

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 05/10] IB/ehca: use #define for "pages per register_rpage" instead of hardcoded value
  2007-07-12 15:45 [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Joachim Fenkes
                   ` (3 preceding siblings ...)
  2007-07-12 15:49 ` [PATCH 04/10] IB/ehca: use common error code mapping instead of specific ones Joachim Fenkes
@ 2007-07-12 15:51 ` Joachim Fenkes
  2007-07-12 15:51 ` [PATCH 06/10] IB/ehca: use macro to calculate number of chunks in a mem block Joachim Fenkes
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-12 15:51 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch

From: Hoang-Nam Nguyen <hnguyen@de.ibm.com>

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_mrmw.c |   19 +++++++++++--------
 1 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index 7c1656a..1fe4f72 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -48,6 +48,9 @@
 #include "hcp_if.h"
 #include "hipz_hw.h"
 
+/* max number of rpages (per hcall register_rpages) */
+#define MAX_RPAGES 512
+
 static struct kmem_cache *mr_cache;
 static struct kmem_cache *mw_cache;
 
@@ -1027,14 +1030,14 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
 	}
 
 	/* max 512 pages per shot */
-	for (i = 0; i < ((pginfo->num_4k + 512 - 1) / 512); i++) {
+	for (i = 0; i < ((pginfo->num_4k + MAX_RPAGES - 1) / MAX_RPAGES); i++) {
 
-		if (i == ((pginfo->num_4k + 512 - 1) / 512) - 1) {
-			rnum = pginfo->num_4k % 512; /* last shot */
+		if (i == ((pginfo->num_4k + MAX_RPAGES - 1) / MAX_RPAGES) - 1) {
+			rnum = pginfo->num_4k % MAX_RPAGES; /* last shot */
 			if (rnum == 0)
-				rnum = 512;      /* last shot is full */
+				rnum = MAX_RPAGES;      /* last shot is full */
 		} else
-			rnum = 512;
+			rnum = MAX_RPAGES;
 
 		if (rnum > 1) {
 			ret = ehca_set_pagebuf(e_mr, pginfo, rnum, kpage);
@@ -1066,7 +1069,7 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
 						 0, /* pagesize 4k */
 						 0, rpage, rnum);
 
-		if (i == ((pginfo->num_4k + 512 - 1) / 512) - 1) {
+		if (i == ((pginfo->num_4k + MAX_RPAGES - 1) / MAX_RPAGES) - 1) {
 			/*
 			 * check for 'registration complete'==H_SUCCESS
 			 * and for 'page registered'==H_PAGE_REGISTERED
@@ -1215,7 +1218,7 @@ int ehca_rereg_mr(struct ehca_shca *shca,
 	int rereg_3_hcall = 0; /* 1: use 3 hipz calls for reregistration */
 
 	/* first determine reregistration hCall(s) */
-	if ((pginfo->num_4k > 512) || (e_mr->num_4k > 512) ||
+	if ((pginfo->num_4k > MAX_RPAGES) || (e_mr->num_4k > MAX_RPAGES) ||
 	    (pginfo->num_4k > e_mr->num_4k)) {
 		ehca_dbg(&shca->ib_device, "Rereg3 case, pginfo->num_4k=%lx "
 			 "e_mr->num_4k=%x", pginfo->num_4k, e_mr->num_4k);
@@ -1306,7 +1309,7 @@ int ehca_unmap_one_fmr(struct ehca_shca *shca,
 	struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0};
 
 	/* first check if reregistration hCall can be used for unmap */
-	if (e_fmr->fmr_max_pages > 512) {
+	if (e_fmr->fmr_max_pages > MAX_RPAGES) {
 		rereg_1_hcall = 0;
 		rereg_3_hcall = 1;
 	}
-- 
1.5.2

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 06/10] IB/ehca: use macro to calculate number of chunks in a mem block
  2007-07-12 15:45 [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Joachim Fenkes
                   ` (4 preceding siblings ...)
  2007-07-12 15:51 ` [PATCH 05/10] IB/ehca: use #define for "pages per register_rpage" instead of hardcoded value Joachim Fenkes
@ 2007-07-12 15:51 ` Joachim Fenkes
  2007-07-12 15:52 ` [PATCH 07/10] IB/ehca: MR/MW structure refactoring Joachim Fenkes
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-12 15:51 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch

From: Hoang-Nam Nguyen <hnguyen@de.ibm.com>

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_mrmw.c |   47 ++++++++++++++++---------------
 1 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index 1fe4f72..58e8b33 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -48,6 +48,8 @@
 #include "hcp_if.h"
 #include "hipz_hw.h"
 
+#define NUM_CHUNKS(length, chunk_size) \
+	(((length) + (chunk_size - 1)) / (chunk_size))
 /* max number of rpages (per hcall register_rpages) */
 #define MAX_RPAGES 512
 
@@ -195,10 +197,10 @@ struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd,
 	}
 
 	/* determine number of MR pages */
-	num_pages_mr = ((((u64)iova_start % PAGE_SIZE) + size +
-			 PAGE_SIZE - 1) / PAGE_SIZE);
-	num_pages_4k = ((((u64)iova_start % EHCA_PAGESIZE) + size +
-			 EHCA_PAGESIZE - 1) / EHCA_PAGESIZE);
+	num_pages_mr = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size,
+				  PAGE_SIZE);
+	num_pages_4k = NUM_CHUNKS(((u64)iova_start % EHCA_PAGESIZE) + size,
+				  EHCA_PAGESIZE);
 
 	/* register MR on HCA */
 	if (ehca_mr_is_maxmr(size, iova_start)) {
@@ -305,10 +307,9 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt
 	}
 
 	/* determine number of MR pages */
-	num_pages_mr = (((virt % PAGE_SIZE) + length + PAGE_SIZE - 1) /
-			PAGE_SIZE);
-	num_pages_4k = (((virt % EHCA_PAGESIZE) + length + EHCA_PAGESIZE - 1) /
-			EHCA_PAGESIZE);
+	num_pages_mr = NUM_CHUNKS((virt % PAGE_SIZE) + length, PAGE_SIZE);
+	num_pages_4k = NUM_CHUNKS((virt % EHCA_PAGESIZE) + length,
+				  EHCA_PAGESIZE);
 
 	/* register MR on HCA */
 	pginfo.type       = EHCA_MR_PGI_USER;
@@ -462,10 +463,10 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
 			ret = -EINVAL;
 			goto rereg_phys_mr_exit1;
 		}
-		num_pages_mr = ((((u64)new_start % PAGE_SIZE) + new_size +
-				 PAGE_SIZE - 1) / PAGE_SIZE);
-		num_pages_4k = ((((u64)new_start % EHCA_PAGESIZE) + new_size +
-				 EHCA_PAGESIZE - 1) / EHCA_PAGESIZE);
+		num_pages_mr = NUM_CHUNKS(((u64)new_start % PAGE_SIZE) +
+					  new_size, PAGE_SIZE);
+		num_pages_4k = NUM_CHUNKS(((u64)new_start % EHCA_PAGESIZE) +
+					  new_size, EHCA_PAGESIZE);
 		pginfo.type           = EHCA_MR_PGI_PHYS;
 		pginfo.num_pages      = num_pages_mr;
 		pginfo.num_4k         = num_pages_4k;
@@ -1030,9 +1031,9 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
 	}
 
 	/* max 512 pages per shot */
-	for (i = 0; i < ((pginfo->num_4k + MAX_RPAGES - 1) / MAX_RPAGES); i++) {
+	for (i = 0; i < NUM_CHUNKS(pginfo->num_4k, MAX_RPAGES); i++) {
 
-		if (i == ((pginfo->num_4k + MAX_RPAGES - 1) / MAX_RPAGES) - 1) {
+		if (i == NUM_CHUNKS(pginfo->num_4k, MAX_RPAGES) - 1) {
 			rnum = pginfo->num_4k % MAX_RPAGES; /* last shot */
 			if (rnum == 0)
 				rnum = MAX_RPAGES;      /* last shot is full */
@@ -1069,7 +1070,7 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
 						 0, /* pagesize 4k */
 						 0, rpage, rnum);
 
-		if (i == ((pginfo->num_4k + MAX_RPAGES - 1) / MAX_RPAGES) - 1) {
+		if (i == NUM_CHUNKS(pginfo->num_4k, MAX_RPAGES) - 1) {
 			/*
 			 * check for 'registration complete'==H_SUCCESS
 			 * and for 'page registered'==H_PAGE_REGISTERED
@@ -1475,10 +1476,10 @@ int ehca_reg_internal_maxmr(
 	iova_start = (u64*)KERNELBASE;
 	ib_pbuf.addr = 0;
 	ib_pbuf.size = size_maxmr;
-	num_pages_mr = ((((u64)iova_start % PAGE_SIZE) + size_maxmr +
-			 PAGE_SIZE - 1) / PAGE_SIZE);
-	num_pages_4k = ((((u64)iova_start % EHCA_PAGESIZE) + size_maxmr +
-			 EHCA_PAGESIZE - 1) / EHCA_PAGESIZE);
+	num_pages_mr = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size_maxmr,
+				  PAGE_SIZE);
+	num_pages_4k = NUM_CHUNKS(((u64)iova_start % EHCA_PAGESIZE)
+				  + size_maxmr, EHCA_PAGESIZE);
 
 	pginfo.type           = EHCA_MR_PGI_PHYS;
 	pginfo.num_pages      = num_pages_mr;
@@ -1700,8 +1701,8 @@ int ehca_set_pagebuf(struct ehca_mr *e_mr,
 		/* loop over desired phys_buf_array entries */
 		while (i < number) {
 			pbuf   = pginfo->phys_buf_array + pginfo->next_buf;
-			num4k  = ((pbuf->addr % EHCA_PAGESIZE) + pbuf->size +
-				  EHCA_PAGESIZE - 1) / EHCA_PAGESIZE;
+			num4k  = NUM_CHUNKS((pbuf->addr % EHCA_PAGESIZE)
+					    + pbuf->size, EHCA_PAGESIZE);
 			offs4k = (pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE;
 			while (pginfo->next_4k < offs4k + num4k) {
 				/* sanity check */
@@ -1873,8 +1874,8 @@ int ehca_set_pagebuf_1(struct ehca_mr *e_mr,
 			goto ehca_set_pagebuf_1_exit0;
 		}
 		tmp_pbuf = pginfo->phys_buf_array + pginfo->next_buf;
-		num4k  = ((tmp_pbuf->addr % EHCA_PAGESIZE) + tmp_pbuf->size +
-			  EHCA_PAGESIZE - 1) / EHCA_PAGESIZE;
+		num4k  = NUM_CHUNKS((tmp_pbuf->addr % EHCA_PAGESIZE) +
+				    tmp_pbuf->size, EHCA_PAGESIZE);
 		offs4k = (tmp_pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE;
 		*rpage = phys_to_abs((tmp_pbuf->addr & EHCA_PAGEMASK) +
 				     (pginfo->next_4k * EHCA_PAGESIZE));
-- 
1.5.2

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 07/10] IB/ehca: MR/MW structure refactoring
  2007-07-12 15:45 [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Joachim Fenkes
                   ` (5 preceding siblings ...)
  2007-07-12 15:51 ` [PATCH 06/10] IB/ehca: use macro to calculate number of chunks in a mem block Joachim Fenkes
@ 2007-07-12 15:52 ` Joachim Fenkes
  2007-07-12 15:53 ` [PATCH 08/10] IB/ehca: Restructure ehca_set_pagebuf() Joachim Fenkes
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-12 15:52 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch

From: Hoang-Nam Nguyen <hnguyen@de.ibm.com>

- Rename struct ehca_mr fields to clearly distinguish between kernel and HW
  page size
- Sort struct ehca_mr_pginfo into a common part and a union containing
  specific fields for physical, user and fast MR

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |   50 ++--
 drivers/infiniband/hw/ehca/ehca_mrmw.c    |  511 +++++++++++++++--------------
 2 files changed, 284 insertions(+), 277 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index b2d614a..92103df 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -211,8 +211,8 @@ struct ehca_mr {
 	spinlock_t mrlock;
 
 	enum ehca_mr_flag flags;
-	u32 num_pages;		/* number of MR pages */
-	u32 num_4k;		/* number of 4k "page" portions to form MR */
+	u32 num_kpages;		/* number of kernel pages */
+	u32 num_hwpages;	/* number of hw pages to form MR */
 	int acl;		/* ACL (stored here for usage in reregister) */
 	u64 *start;		/* virtual start address (stored here for */
 	                        /* usage in reregister) */
@@ -224,9 +224,6 @@ struct ehca_mr {
 	/* fw specific data */
 	struct ipz_mrmw_handle ipz_mr_handle;	/* MR handle for h-calls */
 	struct h_galpas galpas;
-	/* data for userspace bridge */
-	u32 nr_of_pages;
-	void *pagearray;
 };
 
 struct ehca_mw {
@@ -248,26 +245,29 @@ enum ehca_mr_pgi_type {
 
 struct ehca_mr_pginfo {
 	enum ehca_mr_pgi_type type;
-	u64 num_pages;
-	u64 page_cnt;
-	u64 num_4k;       /* number of 4k "page" portions */
-	u64 page_4k_cnt;  /* counter for 4k "page" portions */
-	u64 next_4k;      /* next 4k "page" portion in buffer/chunk/listelem */
-
-	/* type EHCA_MR_PGI_PHYS section */
-	int num_phys_buf;
-	struct ib_phys_buf *phys_buf_array;
-	u64 next_buf;
-
-	/* type EHCA_MR_PGI_USER section */
-	struct ib_umem *region;
-	struct ib_umem_chunk *next_chunk;
-	u64 next_nmap;
-
-	/* type EHCA_MR_PGI_FMR section */
-	u64 *page_list;
-	u64 next_listelem;
-	/* next_4k also used within EHCA_MR_PGI_FMR */
+	u64 num_kpages;
+	u64 kpage_cnt;
+	u64 num_hwpages;     /* number of hw pages */
+	u64 hwpage_cnt;      /* counter for hw pages */
+	u64 next_hwpage;     /* next hw page in buffer/chunk/listelem */
+
+	union {
+		struct { /* type EHCA_MR_PGI_PHYS section */
+			int num_phys_buf;
+			struct ib_phys_buf *phys_buf_array;
+			u64 next_buf;
+		} phy;
+		struct { /* type EHCA_MR_PGI_USER section */
+			struct ib_umem *region;
+			struct ib_umem_chunk *next_chunk;
+			u64 next_nmap;
+		} usr;
+		struct { /* type EHCA_MR_PGI_FMR section */
+			u64 fmr_pgsize;
+			u64 *page_list;
+			u64 next_listelem;
+		} fmr;
+	} u;
 };
 
 /* output parameters for MR/FMR hipz calls */
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index 58e8b33..53b334b 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -150,9 +150,6 @@ struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd,
 	struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd);
 
 	u64 size;
-	struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0};
-	u32 num_pages_mr;
-	u32 num_pages_4k; /* 4k portion "pages" */
 
 	if ((num_phys_buf <= 0) || !phys_buf_array) {
 		ehca_err(pd->device, "bad input values: num_phys_buf=%x "
@@ -196,12 +193,6 @@ struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd,
 		goto reg_phys_mr_exit0;
 	}
 
-	/* determine number of MR pages */
-	num_pages_mr = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size,
-				  PAGE_SIZE);
-	num_pages_4k = NUM_CHUNKS(((u64)iova_start % EHCA_PAGESIZE) + size,
-				  EHCA_PAGESIZE);
-
 	/* register MR on HCA */
 	if (ehca_mr_is_maxmr(size, iova_start)) {
 		e_mr->flags |= EHCA_MR_FLAG_MAXMR;
@@ -213,13 +204,22 @@ struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd,
 			goto reg_phys_mr_exit1;
 		}
 	} else {
-		pginfo.type           = EHCA_MR_PGI_PHYS;
-		pginfo.num_pages      = num_pages_mr;
-		pginfo.num_4k         = num_pages_4k;
-		pginfo.num_phys_buf   = num_phys_buf;
-		pginfo.phys_buf_array = phys_buf_array;
-		pginfo.next_4k        = (((u64)iova_start & ~PAGE_MASK) /
-					 EHCA_PAGESIZE);
+		struct ehca_mr_pginfo pginfo;
+		u32 num_kpages;
+		u32 num_hwpages;
+
+		num_kpages = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size,
+					PAGE_SIZE);
+		num_hwpages = NUM_CHUNKS(((u64)iova_start % EHCA_PAGESIZE) +
+					 size, EHCA_PAGESIZE);
+		memset(&pginfo, 0, sizeof(pginfo));
+		pginfo.type = EHCA_MR_PGI_PHYS;
+		pginfo.num_kpages = num_kpages;
+		pginfo.num_hwpages = num_hwpages;
+		pginfo.u.phy.num_phys_buf = num_phys_buf;
+		pginfo.u.phy.phys_buf_array = phys_buf_array;
+		pginfo.next_hwpage = (((u64)iova_start & ~PAGE_MASK) /
+				      EHCA_PAGESIZE);
 
 		ret = ehca_reg_mr(shca, e_mr, iova_start, size, mr_access_flags,
 				  e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
@@ -254,10 +254,10 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt
 	struct ehca_shca *shca =
 		container_of(pd->device, struct ehca_shca, ib_device);
 	struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd);
-	struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0};
+	struct ehca_mr_pginfo pginfo;
 	int ret;
-	u32 num_pages_mr;
-	u32 num_pages_4k; /* 4k portion "pages" */
+	u32 num_kpages;
+	u32 num_hwpages;
 
 	if (!pd) {
 		ehca_gen_err("bad pd=%p", pd);
@@ -307,19 +307,20 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt
 	}
 
 	/* determine number of MR pages */
-	num_pages_mr = NUM_CHUNKS((virt % PAGE_SIZE) + length, PAGE_SIZE);
-	num_pages_4k = NUM_CHUNKS((virt % EHCA_PAGESIZE) + length,
-				  EHCA_PAGESIZE);
+	num_kpages = NUM_CHUNKS((virt % PAGE_SIZE) + length, PAGE_SIZE);
+	num_hwpages = NUM_CHUNKS((virt % EHCA_PAGESIZE) + length,
+				 EHCA_PAGESIZE);
 
 	/* register MR on HCA */
-	pginfo.type       = EHCA_MR_PGI_USER;
-	pginfo.num_pages  = num_pages_mr;
-	pginfo.num_4k     = num_pages_4k;
-	pginfo.region     = e_mr->umem;
-	pginfo.next_4k	  = e_mr->umem->offset / EHCA_PAGESIZE;
-	pginfo.next_chunk = list_prepare_entry(pginfo.next_chunk,
-					       (&e_mr->umem->chunk_list),
-					       list);
+	memset(&pginfo, 0, sizeof(pginfo));
+	pginfo.type = EHCA_MR_PGI_USER;
+	pginfo.num_kpages = num_kpages;
+	pginfo.num_hwpages = num_hwpages;
+	pginfo.u.usr.region = e_mr->umem;
+	pginfo.next_hwpage = e_mr->umem->offset / EHCA_PAGESIZE;
+	pginfo.u.usr.next_chunk = list_prepare_entry(pginfo.u.usr.next_chunk,
+						     (&e_mr->umem->chunk_list),
+						     list);
 
 	ret = ehca_reg_mr(shca, e_mr, (u64*) virt, length, mr_access_flags, e_pd,
 			  &pginfo, &e_mr->ib.ib_mr.lkey, &e_mr->ib.ib_mr.rkey);
@@ -365,9 +366,9 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
 	struct ehca_pd *new_pd;
 	u32 tmp_lkey, tmp_rkey;
 	unsigned long sl_flags;
-	u32 num_pages_mr = 0;
-	u32 num_pages_4k = 0; /* 4k portion "pages" */
-	struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0};
+	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 &&
@@ -463,17 +464,18 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
 			ret = -EINVAL;
 			goto rereg_phys_mr_exit1;
 		}
-		num_pages_mr = NUM_CHUNKS(((u64)new_start % PAGE_SIZE) +
-					  new_size, PAGE_SIZE);
-		num_pages_4k = NUM_CHUNKS(((u64)new_start % EHCA_PAGESIZE) +
-					  new_size, EHCA_PAGESIZE);
-		pginfo.type           = EHCA_MR_PGI_PHYS;
-		pginfo.num_pages      = num_pages_mr;
-		pginfo.num_4k         = num_pages_4k;
-		pginfo.num_phys_buf   = num_phys_buf;
-		pginfo.phys_buf_array = phys_buf_array;
-		pginfo.next_4k        = (((u64)iova_start & ~PAGE_MASK) /
-					 EHCA_PAGESIZE);
+		num_kpages = NUM_CHUNKS(((u64)new_start % PAGE_SIZE) +
+					new_size, PAGE_SIZE);
+		num_hwpages = NUM_CHUNKS(((u64)new_start % EHCA_PAGESIZE) +
+					 new_size, EHCA_PAGESIZE);
+		memset(&pginfo, 0, sizeof(pginfo));
+		pginfo.type = EHCA_MR_PGI_PHYS;
+		pginfo.num_kpages = num_kpages;
+		pginfo.num_hwpages = num_hwpages;
+		pginfo.u.phy.num_phys_buf = num_phys_buf;
+		pginfo.u.phy.phys_buf_array = phys_buf_array;
+		pginfo.next_hwpage = (((u64)iova_start & ~PAGE_MASK) /
+				      EHCA_PAGESIZE);
 	}
 	if (mr_rereg_mask & IB_MR_REREG_ACCESS)
 		new_acl = mr_access_flags;
@@ -544,11 +546,11 @@ int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr)
 		ret = ehca2ib_return_code(h_ret);
 		goto query_mr_exit1;
 	}
-	mr_attr->pd               = mr->pd;
+	mr_attr->pd = mr->pd;
 	mr_attr->device_virt_addr = hipzout.vaddr;
-	mr_attr->size             = hipzout.len;
-	mr_attr->lkey             = hipzout.lkey;
-	mr_attr->rkey             = hipzout.rkey;
+	mr_attr->size = hipzout.len;
+	mr_attr->lkey = hipzout.lkey;
+	mr_attr->rkey = hipzout.rkey;
 	ehca_mrmw_reverse_map_acl(&hipzout.acl, &mr_attr->mr_access_flags);
 
 query_mr_exit1:
@@ -704,7 +706,7 @@ struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd,
 	struct ehca_mr *e_fmr;
 	int ret;
 	u32 tmp_lkey, tmp_rkey;
-	struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0};
+	struct ehca_mr_pginfo pginfo;
 
 	/* check other parameters */
 	if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) &&
@@ -750,6 +752,7 @@ struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd,
 	e_fmr->flags |= EHCA_MR_FLAG_FMR;
 
 	/* register MR on HCA */
+	memset(&pginfo, 0, sizeof(pginfo));
 	ret = ehca_reg_mr(shca, e_fmr, NULL,
 			  fmr_attr->max_pages * (1 << fmr_attr->page_shift),
 			  mr_access_flags, e_pd, &pginfo,
@@ -788,7 +791,7 @@ int ehca_map_phys_fmr(struct ib_fmr *fmr,
 		container_of(fmr->device, struct ehca_shca, ib_device);
 	struct ehca_mr *e_fmr = container_of(fmr, struct ehca_mr, ib.ib_fmr);
 	struct ehca_pd *e_pd = container_of(fmr->pd, struct ehca_pd, ib_pd);
-	struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0};
+	struct ehca_mr_pginfo pginfo;
 	u32 tmp_lkey, tmp_rkey;
 
 	if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) {
@@ -814,12 +817,13 @@ int ehca_map_phys_fmr(struct ib_fmr *fmr,
 			  fmr, e_fmr->fmr_map_cnt, e_fmr->fmr_max_maps);
 	}
 
-	pginfo.type      = EHCA_MR_PGI_FMR;
-	pginfo.num_pages = list_len;
-	pginfo.num_4k    = list_len * (e_fmr->fmr_page_size / EHCA_PAGESIZE);
-	pginfo.page_list = page_list;
-	pginfo.next_4k   = ((iova & (e_fmr->fmr_page_size-1)) /
-			    EHCA_PAGESIZE);
+	memset(&pginfo, 0, sizeof(pginfo));
+	pginfo.type = EHCA_MR_PGI_FMR;
+	pginfo.num_kpages = list_len;
+	pginfo.num_hwpages = list_len * (e_fmr->fmr_page_size / EHCA_PAGESIZE);
+	pginfo.u.fmr.page_list = page_list;
+	pginfo.next_hwpage = ((iova & (e_fmr->fmr_page_size-1)) /
+			      EHCA_PAGESIZE);
 
 	ret = ehca_rereg_mr(shca, e_fmr, (u64*)iova,
 			    list_len * e_fmr->fmr_page_size,
@@ -979,11 +983,11 @@ int ehca_reg_mr(struct ehca_shca *shca,
 		goto ehca_reg_mr_exit1;
 
 	/* successful registration */
-	e_mr->num_pages = pginfo->num_pages;
-	e_mr->num_4k    = pginfo->num_4k;
-	e_mr->start     = iova_start;
-	e_mr->size      = size;
-	e_mr->acl       = acl;
+	e_mr->num_kpages = pginfo->num_kpages;
+	e_mr->num_hwpages = pginfo->num_hwpages;
+	e_mr->start = iova_start;
+	e_mr->size = size;
+	e_mr->acl = acl;
 	*lkey = hipzout.lkey;
 	*rkey = hipzout.rkey;
 	return 0;
@@ -993,10 +997,10 @@ ehca_reg_mr_exit1:
 	if (h_ret != H_SUCCESS) {
 		ehca_err(&shca->ib_device, "h_ret=%lx shca=%p e_mr=%p "
 			 "iova_start=%p size=%lx acl=%x e_pd=%p lkey=%x "
-			 "pginfo=%p num_pages=%lx num_4k=%lx ret=%x",
+			 "pginfo=%p num_kpages=%lx num_hwpages=%lx ret=%x",
 			 h_ret, shca, e_mr, iova_start, size, acl, e_pd,
-			 hipzout.lkey, pginfo, pginfo->num_pages,
-			 pginfo->num_4k, ret);
+			 hipzout.lkey, pginfo, pginfo->num_kpages,
+			 pginfo->num_hwpages, ret);
 		ehca_err(&shca->ib_device, "internal error in ehca_reg_mr, "
 			 "not recoverable");
 	}
@@ -1004,9 +1008,9 @@ ehca_reg_mr_exit0:
 	if (ret)
 		ehca_err(&shca->ib_device, "ret=%x shca=%p e_mr=%p "
 			 "iova_start=%p size=%lx acl=%x e_pd=%p pginfo=%p "
-			 "num_pages=%lx num_4k=%lx",
+			 "num_kpages=%lx num_hwpages=%lx",
 			 ret, shca, e_mr, iova_start, size, acl, e_pd, pginfo,
-			 pginfo->num_pages, pginfo->num_4k);
+			 pginfo->num_kpages, pginfo->num_hwpages);
 	return ret;
 } /* end ehca_reg_mr() */
 
@@ -1031,10 +1035,10 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
 	}
 
 	/* max 512 pages per shot */
-	for (i = 0; i < NUM_CHUNKS(pginfo->num_4k, MAX_RPAGES); i++) {
+	for (i = 0; i < NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES); i++) {
 
-		if (i == NUM_CHUNKS(pginfo->num_4k, MAX_RPAGES) - 1) {
-			rnum = pginfo->num_4k % MAX_RPAGES; /* last shot */
+		if (i == NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES) - 1) {
+			rnum = pginfo->num_hwpages % MAX_RPAGES; /* last shot */
 			if (rnum == 0)
 				rnum = MAX_RPAGES;      /* last shot is full */
 		} else
@@ -1070,7 +1074,7 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
 						 0, /* pagesize 4k */
 						 0, rpage, rnum);
 
-		if (i == NUM_CHUNKS(pginfo->num_4k, MAX_RPAGES) - 1) {
+		if (i == NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES) - 1) {
 			/*
 			 * check for 'registration complete'==H_SUCCESS
 			 * and for 'page registered'==H_PAGE_REGISTERED
@@ -1106,8 +1110,8 @@ ehca_reg_mr_rpages_exit1:
 ehca_reg_mr_rpages_exit0:
 	if (ret)
 		ehca_err(&shca->ib_device, "ret=%x shca=%p e_mr=%p pginfo=%p "
-			 "num_pages=%lx num_4k=%lx", ret, shca, e_mr, pginfo,
-			 pginfo->num_pages, pginfo->num_4k);
+			 "num_kpages=%lx num_hwpages=%lx", ret, shca, e_mr,
+			 pginfo, pginfo->num_kpages, pginfo->num_hwpages);
 	return ret;
 } /* end ehca_reg_mr_rpages() */
 
@@ -1142,12 +1146,12 @@ inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca,
 	}
 
 	pginfo_save = *pginfo;
-	ret = ehca_set_pagebuf(e_mr, pginfo, pginfo->num_4k, kpage);
+	ret = ehca_set_pagebuf(e_mr, pginfo, pginfo->num_hwpages, kpage);
 	if (ret) {
 		ehca_err(&shca->ib_device, "set pagebuf failed, e_mr=%p "
-			 "pginfo=%p type=%x num_pages=%lx num_4k=%lx kpage=%p",
-			 e_mr, pginfo, pginfo->type, pginfo->num_pages,
-			 pginfo->num_4k,kpage);
+			 "pginfo=%p type=%x num_kpages=%lx num_hwpages=%lx "
+			 "kpage=%p", e_mr, pginfo, pginfo->type,
+			 pginfo->num_kpages, pginfo->num_hwpages, kpage);
 		goto ehca_rereg_mr_rereg1_exit1;
 	}
 	rpage = virt_to_abs(kpage);
@@ -1181,11 +1185,11 @@ inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca,
 		 * successful reregistration
 		 * note: start and start_out are identical for eServer HCAs
 		 */
-		e_mr->num_pages = pginfo->num_pages;
-		e_mr->num_4k    = pginfo->num_4k;
-		e_mr->start     = iova_start;
-		e_mr->size      = size;
-		e_mr->acl       = acl;
+		e_mr->num_kpages = pginfo->num_kpages;
+		e_mr->num_hwpages = pginfo->num_hwpages;
+		e_mr->start = iova_start;
+		e_mr->size = size;
+		e_mr->acl = acl;
 		*lkey = hipzout.lkey;
 		*rkey = hipzout.rkey;
 	}
@@ -1195,9 +1199,9 @@ ehca_rereg_mr_rereg1_exit1:
 ehca_rereg_mr_rereg1_exit0:
 	if ( ret && (ret != -EAGAIN) )
 		ehca_err(&shca->ib_device, "ret=%x lkey=%x rkey=%x "
-			 "pginfo=%p num_pages=%lx num_4k=%lx",
-			 ret, *lkey, *rkey, pginfo, pginfo->num_pages,
-			 pginfo->num_4k);
+			 "pginfo=%p num_kpages=%lx num_hwpages=%lx",
+			 ret, *lkey, *rkey, pginfo, pginfo->num_kpages,
+			 pginfo->num_hwpages);
 	return ret;
 } /* end ehca_rereg_mr_rereg1() */
 
@@ -1219,10 +1223,12 @@ int ehca_rereg_mr(struct ehca_shca *shca,
 	int rereg_3_hcall = 0; /* 1: use 3 hipz calls for reregistration */
 
 	/* first determine reregistration hCall(s) */
-	if ((pginfo->num_4k > MAX_RPAGES) || (e_mr->num_4k > MAX_RPAGES) ||
-	    (pginfo->num_4k > e_mr->num_4k)) {
-		ehca_dbg(&shca->ib_device, "Rereg3 case, pginfo->num_4k=%lx "
-			 "e_mr->num_4k=%x", pginfo->num_4k, e_mr->num_4k);
+	if ((pginfo->num_hwpages > MAX_RPAGES) ||
+	    (e_mr->num_hwpages > MAX_RPAGES) ||
+	    (pginfo->num_hwpages > e_mr->num_hwpages)) {
+		ehca_dbg(&shca->ib_device, "Rereg3 case, "
+			 "pginfo->num_hwpages=%lx e_mr->num_hwpages=%x",
+			 pginfo->num_hwpages, e_mr->num_hwpages);
 		rereg_1_hcall = 0;
 		rereg_3_hcall = 1;
 	}
@@ -1286,9 +1292,9 @@ ehca_rereg_mr_exit0:
 	if (ret)
 		ehca_err(&shca->ib_device, "ret=%x shca=%p e_mr=%p "
 			 "iova_start=%p size=%lx acl=%x e_pd=%p pginfo=%p "
-			 "num_pages=%lx lkey=%x rkey=%x rereg_1_hcall=%x "
+			 "num_kpages=%lx lkey=%x rkey=%x rereg_1_hcall=%x "
 			 "rereg_3_hcall=%x", ret, shca, e_mr, iova_start, size,
-			 acl, e_pd, pginfo, pginfo->num_pages, *lkey, *rkey,
+			 acl, e_pd, pginfo, pginfo->num_kpages, *lkey, *rkey,
 			 rereg_1_hcall, rereg_3_hcall);
 	return ret;
 } /* end ehca_rereg_mr() */
@@ -1306,7 +1312,7 @@ int ehca_unmap_one_fmr(struct ehca_shca *shca,
 		container_of(e_fmr->ib.ib_fmr.pd, struct ehca_pd, ib_pd);
 	struct ehca_mr save_fmr;
 	u32 tmp_lkey, tmp_rkey;
-	struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0};
+	struct ehca_mr_pginfo pginfo;
 	struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0};
 
 	/* first check if reregistration hCall can be used for unmap */
@@ -1370,9 +1376,10 @@ int ehca_unmap_one_fmr(struct ehca_shca *shca,
 		e_fmr->fmr_map_cnt = save_fmr.fmr_map_cnt;
 		e_fmr->acl = save_fmr.acl;
 
-		pginfo.type      = EHCA_MR_PGI_FMR;
-		pginfo.num_pages = 0;
-		pginfo.num_4k    = 0;
+		memset(&pginfo, 0, sizeof(pginfo));
+		pginfo.type = EHCA_MR_PGI_FMR;
+		pginfo.num_kpages = 0;
+		pginfo.num_hwpages = 0;
 		ret = ehca_reg_mr(shca, e_fmr, NULL,
 				  (e_fmr->fmr_max_pages * e_fmr->fmr_page_size),
 				  e_fmr->acl, e_pd, &pginfo, &tmp_lkey,
@@ -1428,11 +1435,11 @@ int ehca_reg_smr(struct ehca_shca *shca,
 		goto ehca_reg_smr_exit0;
 	}
 	/* successful registration */
-	e_newmr->num_pages     = e_origmr->num_pages;
-	e_newmr->num_4k        = e_origmr->num_4k;
-	e_newmr->start         = iova_start;
-	e_newmr->size          = e_origmr->size;
-	e_newmr->acl           = acl;
+	e_newmr->num_kpages = e_origmr->num_kpages;
+	e_newmr->num_hwpages = e_origmr->num_hwpages;
+	e_newmr->start = iova_start;
+	e_newmr->size = e_origmr->size;
+	e_newmr->acl = acl;
 	e_newmr->ipz_mr_handle = hipzout.handle;
 	*lkey = hipzout.lkey;
 	*rkey = hipzout.rkey;
@@ -1458,10 +1465,10 @@ int ehca_reg_internal_maxmr(
 	struct ehca_mr *e_mr;
 	u64 *iova_start;
 	u64 size_maxmr;
-	struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0};
+	struct ehca_mr_pginfo pginfo;
 	struct ib_phys_buf ib_pbuf;
-	u32 num_pages_mr;
-	u32 num_pages_4k; /* 4k portion "pages" */
+	u32 num_kpages;
+	u32 num_hwpages;
 
 	e_mr = ehca_mr_new();
 	if (!e_mr) {
@@ -1476,25 +1483,26 @@ int ehca_reg_internal_maxmr(
 	iova_start = (u64*)KERNELBASE;
 	ib_pbuf.addr = 0;
 	ib_pbuf.size = size_maxmr;
-	num_pages_mr = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size_maxmr,
-				  PAGE_SIZE);
-	num_pages_4k = NUM_CHUNKS(((u64)iova_start % EHCA_PAGESIZE)
-				  + size_maxmr, EHCA_PAGESIZE);
-
-	pginfo.type           = EHCA_MR_PGI_PHYS;
-	pginfo.num_pages      = num_pages_mr;
-	pginfo.num_4k         = num_pages_4k;
-	pginfo.num_phys_buf   = 1;
-	pginfo.phys_buf_array = &ib_pbuf;
+	num_kpages = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size_maxmr,
+				PAGE_SIZE);
+	num_hwpages = NUM_CHUNKS(((u64)iova_start % EHCA_PAGESIZE) + size_maxmr,
+				 EHCA_PAGESIZE);
+
+	memset(&pginfo, 0, sizeof(pginfo));
+	pginfo.type = EHCA_MR_PGI_PHYS;
+	pginfo.num_kpages = num_kpages;
+	pginfo.num_hwpages = num_hwpages;
+	pginfo.u.phy.num_phys_buf = 1;
+	pginfo.u.phy.phys_buf_array = &ib_pbuf;
 
 	ret = ehca_reg_mr(shca, e_mr, iova_start, size_maxmr, 0, e_pd,
 			  &pginfo, &e_mr->ib.ib_mr.lkey,
 			  &e_mr->ib.ib_mr.rkey);
 	if (ret) {
 		ehca_err(&shca->ib_device, "reg of internal max MR failed, "
-			 "e_mr=%p iova_start=%p size_maxmr=%lx num_pages_mr=%x "
-			 "num_pages_4k=%x", e_mr, iova_start, size_maxmr,
-			 num_pages_mr, num_pages_4k);
+			 "e_mr=%p iova_start=%p size_maxmr=%lx num_kpages=%x "
+			 "num_hwpages=%x", e_mr, iova_start, size_maxmr,
+			 num_kpages, num_hwpages);
 		goto ehca_reg_internal_maxmr_exit1;
 	}
 
@@ -1546,11 +1554,11 @@ int ehca_reg_maxmr(struct ehca_shca *shca,
 		return ehca2ib_return_code(h_ret);
 	}
 	/* successful registration */
-	e_newmr->num_pages     = e_origmr->num_pages;
-	e_newmr->num_4k        = e_origmr->num_4k;
-	e_newmr->start         = iova_start;
-	e_newmr->size          = e_origmr->size;
-	e_newmr->acl           = acl;
+	e_newmr->num_kpages = e_origmr->num_kpages;
+	e_newmr->num_hwpages = e_origmr->num_hwpages;
+	e_newmr->start = iova_start;
+	e_newmr->size = e_origmr->size;
+	e_newmr->acl = acl;
 	e_newmr->ipz_mr_handle = hipzout.handle;
 	*lkey = hipzout.lkey;
 	*rkey = hipzout.rkey;
@@ -1693,138 +1701,139 @@ int ehca_set_pagebuf(struct ehca_mr *e_mr,
 	struct ib_umem_chunk *chunk;
 	struct ib_phys_buf *pbuf;
 	u64 *fmrlist;
-	u64 num4k, pgaddr, offs4k;
+	u64 num_hw, pgaddr, offs_hw;
 	u32 i = 0;
 	u32 j = 0;
 
 	if (pginfo->type == EHCA_MR_PGI_PHYS) {
 		/* loop over desired phys_buf_array entries */
 		while (i < number) {
-			pbuf   = pginfo->phys_buf_array + pginfo->next_buf;
-			num4k  = NUM_CHUNKS((pbuf->addr % EHCA_PAGESIZE)
-					    + pbuf->size, EHCA_PAGESIZE);
-			offs4k = (pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE;
-			while (pginfo->next_4k < offs4k + num4k) {
+			pbuf   = pginfo->u.phy.phys_buf_array
+				+ pginfo->u.phy.next_buf;
+			num_hw  = NUM_CHUNKS((pbuf->addr % EHCA_PAGESIZE) +
+					     pbuf->size, EHCA_PAGESIZE);
+			offs_hw = (pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE;
+			while (pginfo->next_hwpage < offs_hw + num_hw) {
 				/* sanity check */
-				if ((pginfo->page_cnt >= pginfo->num_pages) ||
-				    (pginfo->page_4k_cnt >= pginfo->num_4k)) {
-					ehca_gen_err("page_cnt >= num_pages, "
-						     "page_cnt=%lx "
-						     "num_pages=%lx "
-						     "page_4k_cnt=%lx "
-						     "num_4k=%lx i=%x",
-						     pginfo->page_cnt,
-						     pginfo->num_pages,
-						     pginfo->page_4k_cnt,
-						     pginfo->num_4k, i);
+				if ((pginfo->kpage_cnt >= pginfo->num_kpages) ||
+				    (pginfo->hwpage_cnt >= pginfo->num_hwpages)) {
+					ehca_gen_err("kpage_cnt >= num_kpages, "
+						     "kpage_cnt=%lx "
+						     "num_kpages=%lx "
+						     "hwpage_cnt=%lx "
+						     "num_hwpages=%lx i=%x",
+						     pginfo->kpage_cnt,
+						     pginfo->num_kpages,
+						     pginfo->hwpage_cnt,
+						     pginfo->num_hwpages, i);
 					ret = -EFAULT;
 					goto ehca_set_pagebuf_exit0;
 				}
 				*kpage = phys_to_abs(
 					(pbuf->addr & EHCA_PAGEMASK)
-					+ (pginfo->next_4k * EHCA_PAGESIZE));
+					+ (pginfo->next_hwpage * EHCA_PAGESIZE));
 				if ( !(*kpage) && pbuf->addr ) {
 					ehca_gen_err("pbuf->addr=%lx "
 						     "pbuf->size=%lx "
-						     "next_4k=%lx", pbuf->addr,
+						     "next_hwpage=%lx", pbuf->addr,
 						     pbuf->size,
-						     pginfo->next_4k);
+						     pginfo->next_hwpage);
 					ret = -EFAULT;
 					goto ehca_set_pagebuf_exit0;
 				}
-				(pginfo->page_4k_cnt)++;
-				(pginfo->next_4k)++;
-				if (pginfo->next_4k %
+				(pginfo->hwpage_cnt)++;
+				(pginfo->next_hwpage)++;
+				if (pginfo->next_hwpage %
 				    (PAGE_SIZE / EHCA_PAGESIZE) == 0)
-					(pginfo->page_cnt)++;
+					(pginfo->kpage_cnt)++;
 				kpage++;
 				i++;
 				if (i >= number) break;
 			}
-			if (pginfo->next_4k >= offs4k + num4k) {
-				(pginfo->next_buf)++;
-				pginfo->next_4k = 0;
+			if (pginfo->next_hwpage >= offs_hw + num_hw) {
+				(pginfo->u.phy.next_buf)++;
+				pginfo->next_hwpage = 0;
 			}
 		}
 	} else if (pginfo->type == EHCA_MR_PGI_USER) {
 		/* loop over desired chunk entries */
-		chunk      = pginfo->next_chunk;
-		prev_chunk = pginfo->next_chunk;
+		chunk      = pginfo->u.usr.next_chunk;
+		prev_chunk = pginfo->u.usr.next_chunk;
 		list_for_each_entry_continue(chunk,
-					     (&(pginfo->region->chunk_list)),
+					     (&(pginfo->u.usr.region->chunk_list)),
 					     list) {
-			for (i = pginfo->next_nmap; i < chunk->nmap; ) {
+			for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) {
 				pgaddr = ( page_to_pfn(chunk->page_list[i].page)
 					   << PAGE_SHIFT );
 				*kpage = phys_to_abs(pgaddr +
-						     (pginfo->next_4k *
+						     (pginfo->next_hwpage *
 						      EHCA_PAGESIZE));
 				if ( !(*kpage) ) {
 					ehca_gen_err("pgaddr=%lx "
 						     "chunk->page_list[i]=%lx "
-						     "i=%x next_4k=%lx mr=%p",
+						     "i=%x next_hwpage=%lx mr=%p",
 						     pgaddr,
 						     (u64)sg_dma_address(
 							     &chunk->
 							     page_list[i]),
-						     i, pginfo->next_4k, e_mr);
+						     i, pginfo->next_hwpage, e_mr);
 					ret = -EFAULT;
 					goto ehca_set_pagebuf_exit0;
 				}
-				(pginfo->page_4k_cnt)++;
-				(pginfo->next_4k)++;
+				(pginfo->hwpage_cnt)++;
+				(pginfo->next_hwpage)++;
 				kpage++;
-				if (pginfo->next_4k %
+				if (pginfo->next_hwpage %
 				    (PAGE_SIZE / EHCA_PAGESIZE) == 0) {
-					(pginfo->page_cnt)++;
-					(pginfo->next_nmap)++;
-					pginfo->next_4k = 0;
+					(pginfo->kpage_cnt)++;
+					(pginfo->u.usr.next_nmap)++;
+					pginfo->next_hwpage = 0;
 					i++;
 				}
 				j++;
 				if (j >= number) break;
 			}
-			if ((pginfo->next_nmap >= chunk->nmap) &&
+			if ((pginfo->u.usr.next_nmap >= chunk->nmap) &&
 			    (j >= number)) {
-				pginfo->next_nmap = 0;
+				pginfo->u.usr.next_nmap = 0;
 				prev_chunk = chunk;
 				break;
-			} else if (pginfo->next_nmap >= chunk->nmap) {
-				pginfo->next_nmap = 0;
+			} else if (pginfo->u.usr.next_nmap >= chunk->nmap) {
+				pginfo->u.usr.next_nmap = 0;
 				prev_chunk = chunk;
 			} else if (j >= number)
 				break;
 			else
 				prev_chunk = chunk;
 		}
-		pginfo->next_chunk =
+		pginfo->u.usr.next_chunk =
 			list_prepare_entry(prev_chunk,
-					   (&(pginfo->region->chunk_list)),
+					   (&(pginfo->u.usr.region->chunk_list)),
 					   list);
 	} else if (pginfo->type == EHCA_MR_PGI_FMR) {
 		/* loop over desired page_list entries */
-		fmrlist = pginfo->page_list + pginfo->next_listelem;
+		fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem;
 		for (i = 0; i < number; i++) {
 			*kpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) +
-					     pginfo->next_4k * EHCA_PAGESIZE);
+					     pginfo->next_hwpage * EHCA_PAGESIZE);
 			if ( !(*kpage) ) {
 				ehca_gen_err("*fmrlist=%lx fmrlist=%p "
-					     "next_listelem=%lx next_4k=%lx",
+					     "next_listelem=%lx next_hwpage=%lx",
 					     *fmrlist, fmrlist,
-					     pginfo->next_listelem,
-					     pginfo->next_4k);
+					     pginfo->u.fmr.next_listelem,
+					     pginfo->next_hwpage);
 				ret = -EFAULT;
 				goto ehca_set_pagebuf_exit0;
 			}
-			(pginfo->page_4k_cnt)++;
-			(pginfo->next_4k)++;
+			(pginfo->hwpage_cnt)++;
+			(pginfo->next_hwpage)++;
 			kpage++;
-			if (pginfo->next_4k %
+			if (pginfo->next_hwpage %
 			    (e_mr->fmr_page_size / EHCA_PAGESIZE) == 0) {
-				(pginfo->page_cnt)++;
-				(pginfo->next_listelem)++;
+				(pginfo->kpage_cnt)++;
+				(pginfo->u.fmr.next_listelem)++;
 				fmrlist++;
-				pginfo->next_4k = 0;
+				pginfo->next_hwpage = 0;
 			}
 		}
 	} else {
@@ -1835,16 +1844,16 @@ int ehca_set_pagebuf(struct ehca_mr *e_mr,
 
 ehca_set_pagebuf_exit0:
 	if (ret)
-		ehca_gen_err("ret=%x e_mr=%p pginfo=%p type=%x num_pages=%lx "
-			     "num_4k=%lx next_buf=%lx next_4k=%lx number=%x "
-			     "kpage=%p page_cnt=%lx page_4k_cnt=%lx i=%x "
+		ehca_gen_err("ret=%x e_mr=%p pginfo=%p type=%x num_kpages=%lx "
+			     "num_hwpages=%lx next_buf=%lx next_hwpage=%lx number=%x "
+			     "kpage=%p kpage_cnt=%lx hwpage_cnt=%lx i=%x "
 			     "next_listelem=%lx region=%p next_chunk=%p "
 			     "next_nmap=%lx", ret, e_mr, pginfo, pginfo->type,
-			     pginfo->num_pages, pginfo->num_4k,
-			     pginfo->next_buf, pginfo->next_4k, number, kpage,
-			     pginfo->page_cnt, pginfo->page_4k_cnt, i,
-			     pginfo->next_listelem, pginfo->region,
-			     pginfo->next_chunk, pginfo->next_nmap);
+			     pginfo->num_kpages, pginfo->num_hwpages,
+			     pginfo->u.phy.next_buf, pginfo->next_hwpage, number, kpage,
+			     pginfo->kpage_cnt, pginfo->hwpage_cnt, i,
+			     pginfo->u.fmr.next_listelem, pginfo->u.usr.region,
+			     pginfo->u.usr.next_chunk, pginfo->u.usr.next_nmap);
 	return ret;
 } /* end ehca_set_pagebuf() */
 
@@ -1860,101 +1869,101 @@ int ehca_set_pagebuf_1(struct ehca_mr *e_mr,
 	u64 *fmrlist;
 	struct ib_umem_chunk *chunk;
 	struct ib_umem_chunk *prev_chunk;
-	u64 pgaddr, num4k, offs4k;
+	u64 pgaddr, num_hw, offs_hw;
 
 	if (pginfo->type == EHCA_MR_PGI_PHYS) {
 		/* sanity check */
-		if ((pginfo->page_cnt >= pginfo->num_pages) ||
-		    (pginfo->page_4k_cnt >= pginfo->num_4k)) {
-			ehca_gen_err("page_cnt >= num_pages, page_cnt=%lx "
-				     "num_pages=%lx page_4k_cnt=%lx num_4k=%lx",
-				     pginfo->page_cnt, pginfo->num_pages,
-				     pginfo->page_4k_cnt, pginfo->num_4k);
+		if ((pginfo->kpage_cnt >= pginfo->num_kpages) ||
+		    (pginfo->hwpage_cnt >= pginfo->num_hwpages)) {
+			ehca_gen_err("kpage_cnt >= num_hwpages, kpage_cnt=%lx "
+				     "num_hwpages=%lx hwpage_cnt=%lx num_hwpages=%lx",
+				     pginfo->kpage_cnt, pginfo->num_kpages,
+				     pginfo->hwpage_cnt, pginfo->num_hwpages);
 			ret = -EFAULT;
 			goto ehca_set_pagebuf_1_exit0;
 		}
-		tmp_pbuf = pginfo->phys_buf_array + pginfo->next_buf;
-		num4k  = NUM_CHUNKS((tmp_pbuf->addr % EHCA_PAGESIZE) +
-				    tmp_pbuf->size, EHCA_PAGESIZE);
-		offs4k = (tmp_pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE;
+		tmp_pbuf = pginfo->u.phy.phys_buf_array + pginfo->u.phy.next_buf;
+		num_hw  = NUM_CHUNKS((tmp_pbuf->addr % EHCA_PAGESIZE) +
+				     tmp_pbuf->size, EHCA_PAGESIZE);
+		offs_hw = (tmp_pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE;
 		*rpage = phys_to_abs((tmp_pbuf->addr & EHCA_PAGEMASK) +
-				     (pginfo->next_4k * EHCA_PAGESIZE));
+				     (pginfo->next_hwpage * EHCA_PAGESIZE));
 		if ( !(*rpage) && tmp_pbuf->addr ) {
 			ehca_gen_err("tmp_pbuf->addr=%lx"
-				     " tmp_pbuf->size=%lx next_4k=%lx",
+				     " tmp_pbuf->size=%lx next_hwpage=%lx",
 				     tmp_pbuf->addr, tmp_pbuf->size,
-				     pginfo->next_4k);
+				     pginfo->next_hwpage);
 			ret = -EFAULT;
 			goto ehca_set_pagebuf_1_exit0;
 		}
-		(pginfo->page_4k_cnt)++;
-		(pginfo->next_4k)++;
-		if (pginfo->next_4k % (PAGE_SIZE / EHCA_PAGESIZE) == 0)
-			(pginfo->page_cnt)++;
-		if (pginfo->next_4k >= offs4k + num4k) {
-			(pginfo->next_buf)++;
-			pginfo->next_4k = 0;
+		(pginfo->hwpage_cnt)++;
+		(pginfo->next_hwpage)++;
+		if (pginfo->next_hwpage % (PAGE_SIZE / EHCA_PAGESIZE) == 0)
+			(pginfo->kpage_cnt)++;
+		if (pginfo->next_hwpage >= offs_hw + num_hw) {
+			(pginfo->u.phy.next_buf)++;
+			pginfo->next_hwpage = 0;
 		}
 	} else if (pginfo->type == EHCA_MR_PGI_USER) {
-		chunk      = pginfo->next_chunk;
-		prev_chunk = pginfo->next_chunk;
+		chunk = pginfo->u.usr.next_chunk;
+		prev_chunk = pginfo->u.usr.next_chunk;
 		list_for_each_entry_continue(chunk,
-					     (&(pginfo->region->chunk_list)),
+					     (&(pginfo->u.usr.region->chunk_list)),
 					     list) {
 			pgaddr = ( page_to_pfn(chunk->page_list[
-						       pginfo->next_nmap].page)
+						       pginfo->u.usr.next_nmap].page)
 				   << PAGE_SHIFT);
 			*rpage = phys_to_abs(pgaddr +
-					     (pginfo->next_4k * EHCA_PAGESIZE));
+					     (pginfo->next_hwpage * EHCA_PAGESIZE));
 			if ( !(*rpage) ) {
 				ehca_gen_err("pgaddr=%lx chunk->page_list[]=%lx"
-					     " next_nmap=%lx next_4k=%lx mr=%p",
+					     " next_nmap=%lx next_hwpage=%lx mr=%p",
 					     pgaddr, (u64)sg_dma_address(
 						     &chunk->page_list[
-							     pginfo->
+							     pginfo->u.usr.
 							     next_nmap]),
-					     pginfo->next_nmap, pginfo->next_4k,
+					     pginfo->u.usr.next_nmap, pginfo->next_hwpage,
 					     e_mr);
 				ret = -EFAULT;
 				goto ehca_set_pagebuf_1_exit0;
 			}
-			(pginfo->page_4k_cnt)++;
-			(pginfo->next_4k)++;
-			if (pginfo->next_4k %
+			(pginfo->hwpage_cnt)++;
+			(pginfo->next_hwpage)++;
+			if (pginfo->next_hwpage %
 			    (PAGE_SIZE / EHCA_PAGESIZE) == 0) {
-				(pginfo->page_cnt)++;
-				(pginfo->next_nmap)++;
-				pginfo->next_4k = 0;
+				(pginfo->kpage_cnt)++;
+				(pginfo->u.usr.next_nmap)++;
+				pginfo->next_hwpage = 0;
 			}
-			if (pginfo->next_nmap >= chunk->nmap) {
-				pginfo->next_nmap = 0;
+			if (pginfo->u.usr.next_nmap >= chunk->nmap) {
+				pginfo->u.usr.next_nmap = 0;
 				prev_chunk = chunk;
 			}
 			break;
 		}
-		pginfo->next_chunk =
+		pginfo->u.usr.next_chunk =
 			list_prepare_entry(prev_chunk,
-					   (&(pginfo->region->chunk_list)),
+					   (&(pginfo->u.usr.region->chunk_list)),
 					   list);
 	} else if (pginfo->type == EHCA_MR_PGI_FMR) {
-		fmrlist = pginfo->page_list + pginfo->next_listelem;
+		fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem;
 		*rpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) +
-				     pginfo->next_4k * EHCA_PAGESIZE);
+				     pginfo->next_hwpage * EHCA_PAGESIZE);
 		if ( !(*rpage) ) {
 			ehca_gen_err("*fmrlist=%lx fmrlist=%p "
-				     "next_listelem=%lx next_4k=%lx",
-				     *fmrlist, fmrlist, pginfo->next_listelem,
-				     pginfo->next_4k);
+				     "next_listelem=%lx next_hwpage=%lx",
+				     *fmrlist, fmrlist, pginfo->u.fmr.next_listelem,
+				     pginfo->next_hwpage);
 			ret = -EFAULT;
 			goto ehca_set_pagebuf_1_exit0;
 		}
-		(pginfo->page_4k_cnt)++;
-		(pginfo->next_4k)++;
-		if (pginfo->next_4k %
+		(pginfo->hwpage_cnt)++;
+		(pginfo->next_hwpage)++;
+		if (pginfo->next_hwpage %
 		    (e_mr->fmr_page_size / EHCA_PAGESIZE) == 0) {
-			(pginfo->page_cnt)++;
-			(pginfo->next_listelem)++;
-			pginfo->next_4k = 0;
+			(pginfo->kpage_cnt)++;
+			(pginfo->u.fmr.next_listelem)++;
+			pginfo->next_hwpage = 0;
 		}
 	} else {
 		ehca_gen_err("bad pginfo->type=%x", pginfo->type);
@@ -1964,15 +1973,15 @@ int ehca_set_pagebuf_1(struct ehca_mr *e_mr,
 
 ehca_set_pagebuf_1_exit0:
 	if (ret)
-		ehca_gen_err("ret=%x e_mr=%p pginfo=%p type=%x num_pages=%lx "
-			     "num_4k=%lx next_buf=%lx next_4k=%lx rpage=%p "
-			     "page_cnt=%lx page_4k_cnt=%lx next_listelem=%lx "
+		ehca_gen_err("ret=%x e_mr=%p pginfo=%p type=%x num_kpages=%lx "
+			     "num_hwpages=%lx next_buf=%lx next_hwpage=%lx rpage=%p "
+			     "kpage_cnt=%lx hwpage_cnt=%lx next_listelem=%lx "
 			     "region=%p next_chunk=%p next_nmap=%lx", ret, e_mr,
-			     pginfo, pginfo->type, pginfo->num_pages,
-			     pginfo->num_4k, pginfo->next_buf, pginfo->next_4k,
-			     rpage, pginfo->page_cnt, pginfo->page_4k_cnt,
-			     pginfo->next_listelem, pginfo->region,
-			     pginfo->next_chunk, pginfo->next_nmap);
+			     pginfo, pginfo->type, pginfo->num_kpages,
+			     pginfo->num_hwpages, pginfo->u.phy.next_buf, pginfo->next_hwpage,
+			     rpage, pginfo->kpage_cnt, pginfo->hwpage_cnt,
+			     pginfo->u.fmr.next_listelem, pginfo->u.usr.region,
+			     pginfo->u.usr.next_chunk, pginfo->u.usr.next_nmap);
 	return ret;
 } /* end ehca_set_pagebuf_1() */
 
@@ -2053,19 +2062,17 @@ void ehca_mrmw_reverse_map_acl(const u32 *hipz_acl,
  */
 void ehca_mr_deletenew(struct ehca_mr *mr)
 {
-	mr->flags         = 0;
-	mr->num_pages     = 0;
-	mr->num_4k        = 0;
-	mr->acl           = 0;
-	mr->start         = NULL;
+	mr->flags = 0;
+	mr->num_kpages = 0;
+	mr->num_hwpages = 0;
+	mr->acl = 0;
+	mr->start = NULL;
 	mr->fmr_page_size = 0;
 	mr->fmr_max_pages = 0;
-	mr->fmr_max_maps  = 0;
-	mr->fmr_map_cnt   = 0;
+	mr->fmr_max_maps = 0;
+	mr->fmr_map_cnt = 0;
 	memset(&mr->ipz_mr_handle, 0, sizeof(mr->ipz_mr_handle));
 	memset(&mr->galpas, 0, sizeof(mr->galpas));
-	mr->nr_of_pages   = 0;
-	mr->pagearray     = NULL;
 } /* end ehca_mr_deletenew() */
 
 int ehca_init_mrmw_cache(void)
-- 
1.5.2

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 08/10] IB/ehca: Restructure ehca_set_pagebuf()
  2007-07-12 15:45 [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Joachim Fenkes
                   ` (6 preceding siblings ...)
  2007-07-12 15:52 ` [PATCH 07/10] IB/ehca: MR/MW structure refactoring Joachim Fenkes
@ 2007-07-12 15:53 ` Joachim Fenkes
  2007-07-12 15:53 ` [PATCH 09/10] IB/ehca: Fix warnings issued by checkpatch.pl Joachim Fenkes
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-12 15:53 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch

From: Hoang-Nam Nguyen <hnguyen@de.ibm.com>

Split ehca_set_pagebuf() into three functions depending on MR type
(phys/user/fast) and remove superfluous ehca_set_pagebuf_1().

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_mrmw.c |  531 ++++++++++++--------------------
 1 files changed, 200 insertions(+), 331 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index 53b334b..93c26cc 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -824,6 +824,7 @@ int ehca_map_phys_fmr(struct ib_fmr *fmr,
 	pginfo.u.fmr.page_list = page_list;
 	pginfo.next_hwpage = ((iova & (e_fmr->fmr_page_size-1)) /
 			      EHCA_PAGESIZE);
+	pginfo.u.fmr.fmr_pgsize = e_fmr->fmr_page_size;
 
 	ret = ehca_rereg_mr(shca, e_fmr, (u64*)iova,
 			    list_len * e_fmr->fmr_page_size,
@@ -1044,15 +1045,15 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
 		} else
 			rnum = MAX_RPAGES;
 
-		if (rnum > 1) {
-			ret = ehca_set_pagebuf(e_mr, pginfo, rnum, kpage);
-			if (ret) {
-				ehca_err(&shca->ib_device, "ehca_set_pagebuf "
+		ret = ehca_set_pagebuf(pginfo, rnum, kpage);
+		if (ret) {
+			ehca_err(&shca->ib_device, "ehca_set_pagebuf "
 					 "bad rc, ret=%x rnum=%x kpage=%p",
 					 ret, rnum, kpage);
-				ret = -EFAULT;
-				goto ehca_reg_mr_rpages_exit1;
-			}
+			goto ehca_reg_mr_rpages_exit1;
+		}
+
+		if (rnum > 1) {
 			rpage = virt_to_abs(kpage);
 			if (!rpage) {
 				ehca_err(&shca->ib_device, "kpage=%p i=%x",
@@ -1060,15 +1061,8 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
 				ret = -EFAULT;
 				goto ehca_reg_mr_rpages_exit1;
 			}
-		} else {  /* rnum==1 */
-			ret = ehca_set_pagebuf_1(e_mr, pginfo, &rpage);
-			if (ret) {
-				ehca_err(&shca->ib_device, "ehca_set_pagebuf_1 "
-					 "bad rc, ret=%x i=%x", ret, i);
-				ret = -EFAULT;
-				goto ehca_reg_mr_rpages_exit1;
-			}
-		}
+		} else
+			rpage = *kpage;
 
 		h_ret = hipz_h_register_rpage_mr(shca->ipz_hca_handle, e_mr,
 						 0, /* pagesize 4k */
@@ -1146,7 +1140,7 @@ inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca,
 	}
 
 	pginfo_save = *pginfo;
-	ret = ehca_set_pagebuf(e_mr, pginfo, pginfo->num_hwpages, kpage);
+	ret = ehca_set_pagebuf(pginfo, pginfo->num_hwpages, kpage);
 	if (ret) {
 		ehca_err(&shca->ib_device, "set pagebuf failed, e_mr=%p "
 			 "pginfo=%p type=%x num_kpages=%lx num_hwpages=%lx "
@@ -1306,98 +1300,86 @@ int ehca_unmap_one_fmr(struct ehca_shca *shca,
 {
 	int ret = 0;
 	u64 h_ret;
-	int rereg_1_hcall = 1; /* 1: use hipz_mr_reregister directly */
-	int rereg_3_hcall = 0; /* 1: use 3 hipz calls for unmapping */
 	struct ehca_pd *e_pd =
 		container_of(e_fmr->ib.ib_fmr.pd, struct ehca_pd, ib_pd);
 	struct ehca_mr save_fmr;
 	u32 tmp_lkey, tmp_rkey;
 	struct ehca_mr_pginfo pginfo;
 	struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0};
+	struct ehca_mr save_mr;
 
-	/* first check if reregistration hCall can be used for unmap */
-	if (e_fmr->fmr_max_pages > MAX_RPAGES) {
-		rereg_1_hcall = 0;
-		rereg_3_hcall = 1;
-	}
-
-	if (rereg_1_hcall) {
+	if (e_fmr->fmr_max_pages <= MAX_RPAGES) {
 		/*
 		 * note: after using rereg hcall with len=0,
 		 * rereg hcall must be used again for registering pages
 		 */
 		h_ret = hipz_h_reregister_pmr(shca->ipz_hca_handle, e_fmr, 0,
 					      0, 0, e_pd->fw_pd, 0, &hipzout);
-		if (h_ret != H_SUCCESS) {
-			/*
-			 * should not happen, because length checked above,
-			 * FMRs are not shared and no MW bound to FMRs
-			 */
-			ehca_err(&shca->ib_device, "hipz_reregister_pmr failed "
-				 "(Rereg1), h_ret=%lx e_fmr=%p hca_hndl=%lx "
-				 "mr_hndl=%lx lkey=%x lkey_out=%x",
-				 h_ret, e_fmr, shca->ipz_hca_handle.handle,
-				 e_fmr->ipz_mr_handle.handle,
-				 e_fmr->ib.ib_fmr.lkey, hipzout.lkey);
-			rereg_3_hcall = 1;
-		} else {
+		if (h_ret == H_SUCCESS) {
 			/* successful reregistration */
 			e_fmr->start = NULL;
 			e_fmr->size = 0;
 			tmp_lkey = hipzout.lkey;
 			tmp_rkey = hipzout.rkey;
+			return 0;
 		}
+		/*
+		 * should not happen, because length checked above,
+		 * FMRs are not shared and no MW bound to FMRs
+		 */
+		ehca_err(&shca->ib_device, "hipz_reregister_pmr failed "
+			 "(Rereg1), h_ret=%lx e_fmr=%p hca_hndl=%lx "
+			 "mr_hndl=%lx lkey=%x lkey_out=%x",
+			 h_ret, e_fmr, shca->ipz_hca_handle.handle,
+			 e_fmr->ipz_mr_handle.handle,
+			 e_fmr->ib.ib_fmr.lkey, hipzout.lkey);
+		/* try free and rereg */
 	}
 
-	if (rereg_3_hcall) {
-		struct ehca_mr save_mr;
-
-		/* first free old FMR */
-		h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr);
-		if (h_ret != H_SUCCESS) {
-			ehca_err(&shca->ib_device, "hipz_free_mr failed, "
-				 "h_ret=%lx e_fmr=%p hca_hndl=%lx mr_hndl=%lx "
-				 "lkey=%x",
-				 h_ret, e_fmr, shca->ipz_hca_handle.handle,
-				 e_fmr->ipz_mr_handle.handle,
-				 e_fmr->ib.ib_fmr.lkey);
-			ret = ehca2ib_return_code(h_ret);
-			goto ehca_unmap_one_fmr_exit0;
-		}
-		/* clean ehca_mr_t, without changing lock */
-		save_fmr = *e_fmr;
-		ehca_mr_deletenew(e_fmr);
+	/* first free old FMR */
+	h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr);
+	if (h_ret != H_SUCCESS) {
+		ehca_err(&shca->ib_device, "hipz_free_mr failed, "
+			 "h_ret=%lx e_fmr=%p hca_hndl=%lx mr_hndl=%lx "
+			 "lkey=%x",
+			 h_ret, e_fmr, shca->ipz_hca_handle.handle,
+			 e_fmr->ipz_mr_handle.handle,
+			 e_fmr->ib.ib_fmr.lkey);
+		ret = ehca2ib_return_code(h_ret);
+		goto ehca_unmap_one_fmr_exit0;
+	}
+	/* clean ehca_mr_t, without changing lock */
+	save_fmr = *e_fmr;
+	ehca_mr_deletenew(e_fmr);
 
-		/* set some MR values */
-		e_fmr->flags = save_fmr.flags;
-		e_fmr->fmr_page_size = save_fmr.fmr_page_size;
-		e_fmr->fmr_max_pages = save_fmr.fmr_max_pages;
-		e_fmr->fmr_max_maps = save_fmr.fmr_max_maps;
-		e_fmr->fmr_map_cnt = save_fmr.fmr_map_cnt;
-		e_fmr->acl = save_fmr.acl;
+	/* set some MR values */
+	e_fmr->flags = save_fmr.flags;
+	e_fmr->fmr_page_size = save_fmr.fmr_page_size;
+	e_fmr->fmr_max_pages = save_fmr.fmr_max_pages;
+	e_fmr->fmr_max_maps = save_fmr.fmr_max_maps;
+	e_fmr->fmr_map_cnt = save_fmr.fmr_map_cnt;
+	e_fmr->acl = save_fmr.acl;
 
-		memset(&pginfo, 0, sizeof(pginfo));
-		pginfo.type = EHCA_MR_PGI_FMR;
-		pginfo.num_kpages = 0;
-		pginfo.num_hwpages = 0;
-		ret = ehca_reg_mr(shca, e_fmr, NULL,
-				  (e_fmr->fmr_max_pages * e_fmr->fmr_page_size),
-				  e_fmr->acl, e_pd, &pginfo, &tmp_lkey,
-				  &tmp_rkey);
-		if (ret) {
-			u32 offset = (u64)(&e_fmr->flags) - (u64)e_fmr;
-			memcpy(&e_fmr->flags, &(save_mr.flags),
-			       sizeof(struct ehca_mr) - offset);
-			goto ehca_unmap_one_fmr_exit0;
-		}
+	memset(&pginfo, 0, sizeof(pginfo));
+	pginfo.type = EHCA_MR_PGI_FMR;
+	pginfo.num_kpages = 0;
+	pginfo.num_hwpages = 0;
+	ret = ehca_reg_mr(shca, e_fmr, NULL,
+			  (e_fmr->fmr_max_pages * e_fmr->fmr_page_size),
+			  e_fmr->acl, e_pd, &pginfo, &tmp_lkey,
+			  &tmp_rkey);
+	if (ret) {
+		u32 offset = (u64)(&e_fmr->flags) - (u64)e_fmr;
+		memcpy(&e_fmr->flags, &(save_mr.flags),
+		       sizeof(struct ehca_mr) - offset);
+		goto ehca_unmap_one_fmr_exit0;
 	}
 
 ehca_unmap_one_fmr_exit0:
 	if (ret)
 		ehca_err(&shca->ib_device, "ret=%x tmp_lkey=%x tmp_rkey=%x "
-			 "fmr_max_pages=%x rereg_1_hcall=%x rereg_3_hcall=%x",
-			 ret, tmp_lkey, tmp_rkey, e_fmr->fmr_max_pages,
-			 rereg_1_hcall, rereg_3_hcall);
+			 "fmr_max_pages=%x",
+			 ret, tmp_lkey, tmp_rkey, e_fmr->fmr_max_pages);
 	return ret;
 } /* end ehca_unmap_one_fmr() */
 
@@ -1690,300 +1672,187 @@ int ehca_fmr_check_page_list(struct ehca_mr *e_fmr,
 
 /*----------------------------------------------------------------------*/
 
-/* setup page buffer from page info */
-int ehca_set_pagebuf(struct ehca_mr *e_mr,
-		     struct ehca_mr_pginfo *pginfo,
-		     u32 number,
-		     u64 *kpage)
+/* PAGE_SIZE >= pginfo->hwpage_size */
+static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
+				  u32 number,
+				  u64 *kpage)
 {
 	int ret = 0;
 	struct ib_umem_chunk *prev_chunk;
 	struct ib_umem_chunk *chunk;
-	struct ib_phys_buf *pbuf;
-	u64 *fmrlist;
-	u64 num_hw, pgaddr, offs_hw;
+	u64 pgaddr;
 	u32 i = 0;
 	u32 j = 0;
 
-	if (pginfo->type == EHCA_MR_PGI_PHYS) {
-		/* loop over desired phys_buf_array entries */
-		while (i < number) {
-			pbuf   = pginfo->u.phy.phys_buf_array
-				+ pginfo->u.phy.next_buf;
-			num_hw  = NUM_CHUNKS((pbuf->addr % EHCA_PAGESIZE) +
-					     pbuf->size, EHCA_PAGESIZE);
-			offs_hw = (pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE;
-			while (pginfo->next_hwpage < offs_hw + num_hw) {
-				/* sanity check */
-				if ((pginfo->kpage_cnt >= pginfo->num_kpages) ||
-				    (pginfo->hwpage_cnt >= pginfo->num_hwpages)) {
-					ehca_gen_err("kpage_cnt >= num_kpages, "
-						     "kpage_cnt=%lx "
-						     "num_kpages=%lx "
-						     "hwpage_cnt=%lx "
-						     "num_hwpages=%lx i=%x",
-						     pginfo->kpage_cnt,
-						     pginfo->num_kpages,
-						     pginfo->hwpage_cnt,
-						     pginfo->num_hwpages, i);
-					ret = -EFAULT;
-					goto ehca_set_pagebuf_exit0;
-				}
-				*kpage = phys_to_abs(
-					(pbuf->addr & EHCA_PAGEMASK)
-					+ (pginfo->next_hwpage * EHCA_PAGESIZE));
-				if ( !(*kpage) && pbuf->addr ) {
-					ehca_gen_err("pbuf->addr=%lx "
-						     "pbuf->size=%lx "
-						     "next_hwpage=%lx", pbuf->addr,
-						     pbuf->size,
-						     pginfo->next_hwpage);
-					ret = -EFAULT;
-					goto ehca_set_pagebuf_exit0;
-				}
-				(pginfo->hwpage_cnt)++;
-				(pginfo->next_hwpage)++;
-				if (pginfo->next_hwpage %
-				    (PAGE_SIZE / EHCA_PAGESIZE) == 0)
-					(pginfo->kpage_cnt)++;
-				kpage++;
-				i++;
-				if (i >= number) break;
-			}
-			if (pginfo->next_hwpage >= offs_hw + num_hw) {
-				(pginfo->u.phy.next_buf)++;
-				pginfo->next_hwpage = 0;
-			}
-		}
-	} else if (pginfo->type == EHCA_MR_PGI_USER) {
-		/* loop over desired chunk entries */
-		chunk      = pginfo->u.usr.next_chunk;
-		prev_chunk = pginfo->u.usr.next_chunk;
-		list_for_each_entry_continue(chunk,
-					     (&(pginfo->u.usr.region->chunk_list)),
-					     list) {
-			for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) {
-				pgaddr = ( page_to_pfn(chunk->page_list[i].page)
-					   << PAGE_SHIFT );
-				*kpage = phys_to_abs(pgaddr +
-						     (pginfo->next_hwpage *
-						      EHCA_PAGESIZE));
-				if ( !(*kpage) ) {
-					ehca_gen_err("pgaddr=%lx "
-						     "chunk->page_list[i]=%lx "
-						     "i=%x next_hwpage=%lx mr=%p",
-						     pgaddr,
-						     (u64)sg_dma_address(
-							     &chunk->
-							     page_list[i]),
-						     i, pginfo->next_hwpage, e_mr);
-					ret = -EFAULT;
-					goto ehca_set_pagebuf_exit0;
-				}
-				(pginfo->hwpage_cnt)++;
-				(pginfo->next_hwpage)++;
-				kpage++;
-				if (pginfo->next_hwpage %
-				    (PAGE_SIZE / EHCA_PAGESIZE) == 0) {
-					(pginfo->kpage_cnt)++;
-					(pginfo->u.usr.next_nmap)++;
-					pginfo->next_hwpage = 0;
-					i++;
-				}
-				j++;
-				if (j >= number) break;
-			}
-			if ((pginfo->u.usr.next_nmap >= chunk->nmap) &&
-			    (j >= number)) {
-				pginfo->u.usr.next_nmap = 0;
-				prev_chunk = chunk;
-				break;
-			} else if (pginfo->u.usr.next_nmap >= chunk->nmap) {
-				pginfo->u.usr.next_nmap = 0;
-				prev_chunk = chunk;
-			} else if (j >= number)
-				break;
-			else
-				prev_chunk = chunk;
-		}
-		pginfo->u.usr.next_chunk =
-			list_prepare_entry(prev_chunk,
-					   (&(pginfo->u.usr.region->chunk_list)),
-					   list);
-	} else if (pginfo->type == EHCA_MR_PGI_FMR) {
-		/* loop over desired page_list entries */
-		fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem;
-		for (i = 0; i < number; i++) {
-			*kpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) +
-					     pginfo->next_hwpage * EHCA_PAGESIZE);
+	/* loop over desired chunk entries */
+	chunk      = pginfo->u.usr.next_chunk;
+	prev_chunk = pginfo->u.usr.next_chunk;
+	list_for_each_entry_continue(
+		chunk, (&(pginfo->u.usr.region->chunk_list)), list) {
+		for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) {
+			pgaddr = page_to_pfn(chunk->page_list[i].page)
+				<< PAGE_SHIFT ;
+			*kpage = phys_to_abs(pgaddr +
+					     (pginfo->next_hwpage *
+					      EHCA_PAGESIZE));
 			if ( !(*kpage) ) {
-				ehca_gen_err("*fmrlist=%lx fmrlist=%p "
-					     "next_listelem=%lx next_hwpage=%lx",
-					     *fmrlist, fmrlist,
-					     pginfo->u.fmr.next_listelem,
-					     pginfo->next_hwpage);
-				ret = -EFAULT;
-				goto ehca_set_pagebuf_exit0;
+				ehca_gen_err("pgaddr=%lx "
+					     "chunk->page_list[i]=%lx "
+					     "i=%x next_hwpage=%lx",
+					     pgaddr, (u64)sg_dma_address(
+						     &chunk->page_list[i]),
+					     i, pginfo->next_hwpage);
+				return -EFAULT;
 			}
 			(pginfo->hwpage_cnt)++;
 			(pginfo->next_hwpage)++;
 			kpage++;
 			if (pginfo->next_hwpage %
-			    (e_mr->fmr_page_size / EHCA_PAGESIZE) == 0) {
+			    (PAGE_SIZE / EHCA_PAGESIZE) == 0) {
 				(pginfo->kpage_cnt)++;
-				(pginfo->u.fmr.next_listelem)++;
-				fmrlist++;
+				(pginfo->u.usr.next_nmap)++;
 				pginfo->next_hwpage = 0;
+				i++;
 			}
+			j++;
+			if (j >= number) break;
 		}
-	} else {
-		ehca_gen_err("bad pginfo->type=%x", pginfo->type);
-		ret = -EFAULT;
-		goto ehca_set_pagebuf_exit0;
+		if ((pginfo->u.usr.next_nmap >= chunk->nmap) &&
+		    (j >= number)) {
+			pginfo->u.usr.next_nmap = 0;
+			prev_chunk = chunk;
+			break;
+		} else if (pginfo->u.usr.next_nmap >= chunk->nmap) {
+			pginfo->u.usr.next_nmap = 0;
+			prev_chunk = chunk;
+		} else if (j >= number)
+			break;
+		else
+			prev_chunk = chunk;
 	}
-
-ehca_set_pagebuf_exit0:
-	if (ret)
-		ehca_gen_err("ret=%x e_mr=%p pginfo=%p type=%x num_kpages=%lx "
-			     "num_hwpages=%lx next_buf=%lx next_hwpage=%lx number=%x "
-			     "kpage=%p kpage_cnt=%lx hwpage_cnt=%lx i=%x "
-			     "next_listelem=%lx region=%p next_chunk=%p "
-			     "next_nmap=%lx", ret, e_mr, pginfo, pginfo->type,
-			     pginfo->num_kpages, pginfo->num_hwpages,
-			     pginfo->u.phy.next_buf, pginfo->next_hwpage, number, kpage,
-			     pginfo->kpage_cnt, pginfo->hwpage_cnt, i,
-			     pginfo->u.fmr.next_listelem, pginfo->u.usr.region,
-			     pginfo->u.usr.next_chunk, pginfo->u.usr.next_nmap);
+	pginfo->u.usr.next_chunk =
+		list_prepare_entry(prev_chunk,
+				   (&(pginfo->u.usr.region->chunk_list)),
+				   list);
 	return ret;
-} /* end ehca_set_pagebuf() */
-
-/*----------------------------------------------------------------------*/
+}
 
-/* setup 1 page from page info page buffer */
-int ehca_set_pagebuf_1(struct ehca_mr *e_mr,
-		       struct ehca_mr_pginfo *pginfo,
-		       u64 *rpage)
+int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
+			  u32 number,
+			  u64 *kpage)
 {
 	int ret = 0;
-	struct ib_phys_buf *tmp_pbuf;
-	u64 *fmrlist;
-	struct ib_umem_chunk *chunk;
-	struct ib_umem_chunk *prev_chunk;
-	u64 pgaddr, num_hw, offs_hw;
-
-	if (pginfo->type == EHCA_MR_PGI_PHYS) {
-		/* sanity check */
-		if ((pginfo->kpage_cnt >= pginfo->num_kpages) ||
-		    (pginfo->hwpage_cnt >= pginfo->num_hwpages)) {
-			ehca_gen_err("kpage_cnt >= num_hwpages, kpage_cnt=%lx "
-				     "num_hwpages=%lx hwpage_cnt=%lx num_hwpages=%lx",
-				     pginfo->kpage_cnt, pginfo->num_kpages,
-				     pginfo->hwpage_cnt, pginfo->num_hwpages);
-			ret = -EFAULT;
-			goto ehca_set_pagebuf_1_exit0;
-		}
-		tmp_pbuf = pginfo->u.phy.phys_buf_array + pginfo->u.phy.next_buf;
-		num_hw  = NUM_CHUNKS((tmp_pbuf->addr % EHCA_PAGESIZE) +
-				     tmp_pbuf->size, EHCA_PAGESIZE);
-		offs_hw = (tmp_pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE;
-		*rpage = phys_to_abs((tmp_pbuf->addr & EHCA_PAGEMASK) +
-				     (pginfo->next_hwpage * EHCA_PAGESIZE));
-		if ( !(*rpage) && tmp_pbuf->addr ) {
-			ehca_gen_err("tmp_pbuf->addr=%lx"
-				     " tmp_pbuf->size=%lx next_hwpage=%lx",
-				     tmp_pbuf->addr, tmp_pbuf->size,
-				     pginfo->next_hwpage);
-			ret = -EFAULT;
-			goto ehca_set_pagebuf_1_exit0;
-		}
-		(pginfo->hwpage_cnt)++;
-		(pginfo->next_hwpage)++;
-		if (pginfo->next_hwpage % (PAGE_SIZE / EHCA_PAGESIZE) == 0)
-			(pginfo->kpage_cnt)++;
-		if (pginfo->next_hwpage >= offs_hw + num_hw) {
-			(pginfo->u.phy.next_buf)++;
-			pginfo->next_hwpage = 0;
-		}
-	} else if (pginfo->type == EHCA_MR_PGI_USER) {
-		chunk = pginfo->u.usr.next_chunk;
-		prev_chunk = pginfo->u.usr.next_chunk;
-		list_for_each_entry_continue(chunk,
-					     (&(pginfo->u.usr.region->chunk_list)),
-					     list) {
-			pgaddr = ( page_to_pfn(chunk->page_list[
-						       pginfo->u.usr.next_nmap].page)
-				   << PAGE_SHIFT);
-			*rpage = phys_to_abs(pgaddr +
-					     (pginfo->next_hwpage * EHCA_PAGESIZE));
-			if ( !(*rpage) ) {
-				ehca_gen_err("pgaddr=%lx chunk->page_list[]=%lx"
-					     " next_nmap=%lx next_hwpage=%lx mr=%p",
-					     pgaddr, (u64)sg_dma_address(
-						     &chunk->page_list[
-							     pginfo->u.usr.
-							     next_nmap]),
-					     pginfo->u.usr.next_nmap, pginfo->next_hwpage,
-					     e_mr);
-				ret = -EFAULT;
-				goto ehca_set_pagebuf_1_exit0;
+	struct ib_phys_buf *pbuf;
+	u64 num_hw, offs_hw;
+	u32 i = 0;
+
+	/* loop over desired phys_buf_array entries */
+	while (i < number) {
+		pbuf   = pginfo->u.phy.phys_buf_array + pginfo->u.phy.next_buf;
+		num_hw  = NUM_CHUNKS((pbuf->addr % EHCA_PAGESIZE) +
+				     pbuf->size, EHCA_PAGESIZE);
+		offs_hw = (pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE;
+		while (pginfo->next_hwpage < offs_hw + num_hw) {
+			/* sanity check */
+			if ((pginfo->kpage_cnt >= pginfo->num_kpages) ||
+			    (pginfo->hwpage_cnt >= pginfo->num_hwpages)) {
+				ehca_gen_err("kpage_cnt >= num_kpages, "
+					     "kpage_cnt=%lx num_kpages=%lx "
+					     "hwpage_cnt=%lx "
+					     "num_hwpages=%lx i=%x",
+					     pginfo->kpage_cnt,
+					     pginfo->num_kpages,
+					     pginfo->hwpage_cnt,
+					     pginfo->num_hwpages, i);
+				return -EFAULT;
+			}
+			*kpage = phys_to_abs(
+				(pbuf->addr & EHCA_PAGEMASK)
+				+ (pginfo->next_hwpage * EHCA_PAGESIZE));
+			if ( !(*kpage) && pbuf->addr ) {
+				ehca_gen_err("pbuf->addr=%lx "
+					     "pbuf->size=%lx "
+					     "next_hwpage=%lx", pbuf->addr,
+					     pbuf->size,
+					     pginfo->next_hwpage);
+				return -EFAULT;
 			}
 			(pginfo->hwpage_cnt)++;
 			(pginfo->next_hwpage)++;
 			if (pginfo->next_hwpage %
-			    (PAGE_SIZE / EHCA_PAGESIZE) == 0) {
+			    (PAGE_SIZE / EHCA_PAGESIZE) == 0)
 				(pginfo->kpage_cnt)++;
-				(pginfo->u.usr.next_nmap)++;
-				pginfo->next_hwpage = 0;
-			}
-			if (pginfo->u.usr.next_nmap >= chunk->nmap) {
-				pginfo->u.usr.next_nmap = 0;
-				prev_chunk = chunk;
-			}
-			break;
+			kpage++;
+			i++;
+			if (i >= number) break;
 		}
-		pginfo->u.usr.next_chunk =
-			list_prepare_entry(prev_chunk,
-					   (&(pginfo->u.usr.region->chunk_list)),
-					   list);
-	} else if (pginfo->type == EHCA_MR_PGI_FMR) {
-		fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem;
-		*rpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) +
+		if (pginfo->next_hwpage >= offs_hw + num_hw) {
+			(pginfo->u.phy.next_buf)++;
+			pginfo->next_hwpage = 0;
+		}
+	}
+	return ret;
+}
+
+int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
+			 u32 number,
+			 u64 *kpage)
+{
+	int ret = 0;
+	u64 *fmrlist;
+	u32 i;
+
+	/* loop over desired page_list entries */
+	fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem;
+	for (i = 0; i < number; i++) {
+		*kpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) +
 				     pginfo->next_hwpage * EHCA_PAGESIZE);
-		if ( !(*rpage) ) {
+		if ( !(*kpage) ) {
 			ehca_gen_err("*fmrlist=%lx fmrlist=%p "
 				     "next_listelem=%lx next_hwpage=%lx",
-				     *fmrlist, fmrlist, pginfo->u.fmr.next_listelem,
+				     *fmrlist, fmrlist,
+				     pginfo->u.fmr.next_listelem,
 				     pginfo->next_hwpage);
-			ret = -EFAULT;
-			goto ehca_set_pagebuf_1_exit0;
+			return -EFAULT;
 		}
 		(pginfo->hwpage_cnt)++;
 		(pginfo->next_hwpage)++;
+		kpage++;
 		if (pginfo->next_hwpage %
-		    (e_mr->fmr_page_size / EHCA_PAGESIZE) == 0) {
+		    (pginfo->u.fmr.fmr_pgsize / EHCA_PAGESIZE) == 0) {
 			(pginfo->kpage_cnt)++;
 			(pginfo->u.fmr.next_listelem)++;
+			fmrlist++;
 			pginfo->next_hwpage = 0;
 		}
-	} else {
+	}
+	return ret;
+}
+
+/* setup page buffer from page info */
+int ehca_set_pagebuf(struct ehca_mr_pginfo *pginfo,
+		     u32 number,
+		     u64 *kpage)
+{
+	int ret;
+
+	switch (pginfo->type) {
+	case EHCA_MR_PGI_PHYS:
+		ret = ehca_set_pagebuf_phys(pginfo, number, kpage);
+		break;
+	case EHCA_MR_PGI_USER:
+		ret = ehca_set_pagebuf_user1(pginfo, number, kpage);
+		break;
+	case EHCA_MR_PGI_FMR:
+		ret = ehca_set_pagebuf_fmr(pginfo, number, kpage);
+		break;
+	default:
 		ehca_gen_err("bad pginfo->type=%x", pginfo->type);
 		ret = -EFAULT;
-		goto ehca_set_pagebuf_1_exit0;
+		break;
 	}
-
-ehca_set_pagebuf_1_exit0:
-	if (ret)
-		ehca_gen_err("ret=%x e_mr=%p pginfo=%p type=%x num_kpages=%lx "
-			     "num_hwpages=%lx next_buf=%lx next_hwpage=%lx rpage=%p "
-			     "kpage_cnt=%lx hwpage_cnt=%lx next_listelem=%lx "
-			     "region=%p next_chunk=%p next_nmap=%lx", ret, e_mr,
-			     pginfo, pginfo->type, pginfo->num_kpages,
-			     pginfo->num_hwpages, pginfo->u.phy.next_buf, pginfo->next_hwpage,
-			     rpage, pginfo->kpage_cnt, pginfo->hwpage_cnt,
-			     pginfo->u.fmr.next_listelem, pginfo->u.usr.region,
-			     pginfo->u.usr.next_chunk, pginfo->u.usr.next_nmap);
 	return ret;
-} /* end ehca_set_pagebuf_1() */
+} /* end ehca_set_pagebuf() */
 
 /*----------------------------------------------------------------------*/
 
-- 
1.5.2

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 09/10] IB/ehca: Fix warnings issued by checkpatch.pl
  2007-07-12 15:45 [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Joachim Fenkes
                   ` (7 preceding siblings ...)
  2007-07-12 15:53 ` [PATCH 08/10] IB/ehca: Restructure ehca_set_pagebuf() Joachim Fenkes
@ 2007-07-12 15:53 ` Joachim Fenkes
  2007-07-12 15:54 ` [PATCH 10/10] IB/ehca: Support large page MRs Joachim Fenkes
  2007-07-12 17:15 ` [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Roland Dreier
  10 siblings, 0 replies; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-12 15:53 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch

From: Hoang-Nam Nguyen <hnguyen@de.ibm.com>

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_av.c              |    2 +-
 drivers/infiniband/hw/ehca/ehca_classes.h         |    4 +-
 drivers/infiniband/hw/ehca/ehca_classes_pSeries.h |  156 ++++++++++----------
 drivers/infiniband/hw/ehca/ehca_cq.c              |    2 +-
 drivers/infiniband/hw/ehca/ehca_eq.c              |    3 +-
 drivers/infiniband/hw/ehca/ehca_hca.c             |   28 +++-
 drivers/infiniband/hw/ehca/ehca_irq.c             |   56 ++++----
 drivers/infiniband/hw/ehca/ehca_iverbs.h          |    7 +-
 drivers/infiniband/hw/ehca/ehca_main.c            |   21 ++--
 drivers/infiniband/hw/ehca/ehca_mrmw.c            |   59 ++++----
 drivers/infiniband/hw/ehca/ehca_mrmw.h            |    7 +-
 drivers/infiniband/hw/ehca/ehca_qes.h             |   22 ++--
 drivers/infiniband/hw/ehca/ehca_qp.c              |   39 +++---
 drivers/infiniband/hw/ehca/ehca_reqs.c            |   15 ++-
 drivers/infiniband/hw/ehca/ehca_tools.h           |   28 ++--
 drivers/infiniband/hw/ehca/ehca_uverbs.c          |   10 +-
 drivers/infiniband/hw/ehca/hcp_if.c               |    8 +-
 drivers/infiniband/hw/ehca/hcp_phyp.c             |    2 +-
 drivers/infiniband/hw/ehca/hipz_fns_core.h        |    4 +-
 drivers/infiniband/hw/ehca/hipz_hw.h              |   24 ++--
 drivers/infiniband/hw/ehca/ipz_pt_fn.c            |    2 +-
 drivers/infiniband/hw/ehca/ipz_pt_fn.h            |    4 +-
 22 files changed, 261 insertions(+), 242 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c
index 3cd6bf3..e53a97a 100644
--- a/drivers/infiniband/hw/ehca/ehca_av.c
+++ b/drivers/infiniband/hw/ehca/ehca_av.c
@@ -79,7 +79,7 @@ struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
 			av->av.ipd = (ah_mult > 0) ?
 				((ehca_mult - 1) / ah_mult) : 0;
 	} else
-	        av->av.ipd = ehca_static_rate;
+		av->av.ipd = ehca_static_rate;
 
 	av->av.lnh = ah_attr->ah_flags;
 	av->av.grh.word_0 = EHCA_BMASK_SET(GRH_IPVERSION_MASK, 6);
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 92103df..1752821 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -215,7 +215,7 @@ struct ehca_mr {
 	u32 num_hwpages;	/* number of hw pages to form MR */
 	int acl;		/* ACL (stored here for usage in reregister) */
 	u64 *start;		/* virtual start address (stored here for */
-	                        /* usage in reregister) */
+				/* usage in reregister) */
 	u64 size;		/* size (stored here for usage in reregister) */
 	u32 fmr_page_size;	/* page size for FMR */
 	u32 fmr_max_pages;	/* max pages for FMR */
@@ -400,6 +400,6 @@ struct ehca_alloc_qp_parms {
 
 int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp);
 int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int qp_num);
-struct ehca_qp* ehca_cq_get_qp(struct ehca_cq *cq, int qp_num);
+struct ehca_qp *ehca_cq_get_qp(struct ehca_cq *cq, int qp_num);
 
 #endif
diff --git a/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h b/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
index fb3df5c..1798e64 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
@@ -154,83 +154,83 @@ struct hcp_modify_qp_control_block {
 	u32 reserved_70_127[58];       /* 70 */
 };
 
-#define MQPCB_MASK_QKEY                         EHCA_BMASK_IBM(0,0)
-#define MQPCB_MASK_SEND_PSN                     EHCA_BMASK_IBM(2,2)
-#define MQPCB_MASK_RECEIVE_PSN                  EHCA_BMASK_IBM(3,3)
-#define MQPCB_MASK_PRIM_PHYS_PORT               EHCA_BMASK_IBM(4,4)
-#define MQPCB_PRIM_PHYS_PORT                    EHCA_BMASK_IBM(24,31)
-#define MQPCB_MASK_ALT_PHYS_PORT                EHCA_BMASK_IBM(5,5)
-#define MQPCB_MASK_PRIM_P_KEY_IDX               EHCA_BMASK_IBM(6,6)
-#define MQPCB_PRIM_P_KEY_IDX                    EHCA_BMASK_IBM(24,31)
-#define MQPCB_MASK_ALT_P_KEY_IDX                EHCA_BMASK_IBM(7,7)
-#define MQPCB_MASK_RDMA_ATOMIC_CTRL             EHCA_BMASK_IBM(8,8)
-#define MQPCB_MASK_QP_STATE                     EHCA_BMASK_IBM(9,9)
-#define MQPCB_QP_STATE                          EHCA_BMASK_IBM(24,31)
-#define MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES      EHCA_BMASK_IBM(11,11)
-#define MQPCB_MASK_PATH_MIGRATION_STATE         EHCA_BMASK_IBM(12,12)
-#define MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP    EHCA_BMASK_IBM(13,13)
-#define MQPCB_MASK_DEST_QP_NR                   EHCA_BMASK_IBM(14,14)
-#define MQPCB_MASK_MIN_RNR_NAK_TIMER_FIELD      EHCA_BMASK_IBM(15,15)
-#define MQPCB_MASK_SERVICE_LEVEL                EHCA_BMASK_IBM(16,16)
-#define MQPCB_MASK_SEND_GRH_FLAG                EHCA_BMASK_IBM(17,17)
-#define MQPCB_MASK_RETRY_COUNT                  EHCA_BMASK_IBM(18,18)
-#define MQPCB_MASK_TIMEOUT                      EHCA_BMASK_IBM(19,19)
-#define MQPCB_MASK_PATH_MTU                     EHCA_BMASK_IBM(20,20)
-#define MQPCB_PATH_MTU                          EHCA_BMASK_IBM(24,31)
-#define MQPCB_MASK_MAX_STATIC_RATE              EHCA_BMASK_IBM(21,21)
-#define MQPCB_MAX_STATIC_RATE                   EHCA_BMASK_IBM(24,31)
-#define MQPCB_MASK_DLID                         EHCA_BMASK_IBM(22,22)
-#define MQPCB_DLID                              EHCA_BMASK_IBM(16,31)
-#define MQPCB_MASK_RNR_RETRY_COUNT              EHCA_BMASK_IBM(23,23)
-#define MQPCB_RNR_RETRY_COUNT                   EHCA_BMASK_IBM(29,31)
-#define MQPCB_MASK_SOURCE_PATH_BITS             EHCA_BMASK_IBM(24,24)
-#define MQPCB_SOURCE_PATH_BITS                  EHCA_BMASK_IBM(25,31)
-#define MQPCB_MASK_TRAFFIC_CLASS                EHCA_BMASK_IBM(25,25)
-#define MQPCB_TRAFFIC_CLASS                     EHCA_BMASK_IBM(24,31)
-#define MQPCB_MASK_HOP_LIMIT                    EHCA_BMASK_IBM(26,26)
-#define MQPCB_HOP_LIMIT                         EHCA_BMASK_IBM(24,31)
-#define MQPCB_MASK_SOURCE_GID_IDX               EHCA_BMASK_IBM(27,27)
-#define MQPCB_SOURCE_GID_IDX                    EHCA_BMASK_IBM(24,31)
-#define MQPCB_MASK_FLOW_LABEL                   EHCA_BMASK_IBM(28,28)
-#define MQPCB_FLOW_LABEL                        EHCA_BMASK_IBM(12,31)
-#define MQPCB_MASK_DEST_GID                     EHCA_BMASK_IBM(30,30)
-#define MQPCB_MASK_SERVICE_LEVEL_AL             EHCA_BMASK_IBM(31,31)
-#define MQPCB_SERVICE_LEVEL_AL                  EHCA_BMASK_IBM(28,31)
-#define MQPCB_MASK_SEND_GRH_FLAG_AL             EHCA_BMASK_IBM(32,32)
-#define MQPCB_SEND_GRH_FLAG_AL                  EHCA_BMASK_IBM(31,31)
-#define MQPCB_MASK_RETRY_COUNT_AL               EHCA_BMASK_IBM(33,33)
-#define MQPCB_RETRY_COUNT_AL                    EHCA_BMASK_IBM(29,31)
-#define MQPCB_MASK_TIMEOUT_AL                   EHCA_BMASK_IBM(34,34)
-#define MQPCB_TIMEOUT_AL                        EHCA_BMASK_IBM(27,31)
-#define MQPCB_MASK_MAX_STATIC_RATE_AL           EHCA_BMASK_IBM(35,35)
-#define MQPCB_MAX_STATIC_RATE_AL                EHCA_BMASK_IBM(24,31)
-#define MQPCB_MASK_DLID_AL                      EHCA_BMASK_IBM(36,36)
-#define MQPCB_DLID_AL                           EHCA_BMASK_IBM(16,31)
-#define MQPCB_MASK_RNR_RETRY_COUNT_AL           EHCA_BMASK_IBM(37,37)
-#define MQPCB_RNR_RETRY_COUNT_AL                EHCA_BMASK_IBM(29,31)
-#define MQPCB_MASK_SOURCE_PATH_BITS_AL          EHCA_BMASK_IBM(38,38)
-#define MQPCB_SOURCE_PATH_BITS_AL               EHCA_BMASK_IBM(25,31)
-#define MQPCB_MASK_TRAFFIC_CLASS_AL             EHCA_BMASK_IBM(39,39)
-#define MQPCB_TRAFFIC_CLASS_AL                  EHCA_BMASK_IBM(24,31)
-#define MQPCB_MASK_HOP_LIMIT_AL                 EHCA_BMASK_IBM(40,40)
-#define MQPCB_HOP_LIMIT_AL                      EHCA_BMASK_IBM(24,31)
-#define MQPCB_MASK_SOURCE_GID_IDX_AL            EHCA_BMASK_IBM(41,41)
-#define MQPCB_SOURCE_GID_IDX_AL                 EHCA_BMASK_IBM(24,31)
-#define MQPCB_MASK_FLOW_LABEL_AL                EHCA_BMASK_IBM(42,42)
-#define MQPCB_FLOW_LABEL_AL                     EHCA_BMASK_IBM(12,31)
-#define MQPCB_MASK_DEST_GID_AL                  EHCA_BMASK_IBM(44,44)
-#define MQPCB_MASK_MAX_NR_OUTST_SEND_WR         EHCA_BMASK_IBM(45,45)
-#define MQPCB_MAX_NR_OUTST_SEND_WR              EHCA_BMASK_IBM(16,31)
-#define MQPCB_MASK_MAX_NR_OUTST_RECV_WR         EHCA_BMASK_IBM(46,46)
-#define MQPCB_MAX_NR_OUTST_RECV_WR              EHCA_BMASK_IBM(16,31)
-#define MQPCB_MASK_DISABLE_ETE_CREDIT_CHECK     EHCA_BMASK_IBM(47,47)
-#define MQPCB_DISABLE_ETE_CREDIT_CHECK          EHCA_BMASK_IBM(31,31)
-#define MQPCB_QP_NUMBER                         EHCA_BMASK_IBM(8,31)
-#define MQPCB_MASK_QP_ENABLE                    EHCA_BMASK_IBM(48,48)
-#define MQPCB_QP_ENABLE                         EHCA_BMASK_IBM(31,31)
-#define MQPCB_MASK_CURR_SRQ_LIMIT               EHCA_BMASK_IBM(49,49)
-#define MQPCB_CURR_SRQ_LIMIT                    EHCA_BMASK_IBM(16,31)
-#define MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG       EHCA_BMASK_IBM(50,50)
-#define MQPCB_MASK_SHARED_RQ_HNDL               EHCA_BMASK_IBM(51,51)
+#define MQPCB_MASK_QKEY                         EHCA_BMASK_IBM( 0,  0)
+#define MQPCB_MASK_SEND_PSN                     EHCA_BMASK_IBM( 2,  2)
+#define MQPCB_MASK_RECEIVE_PSN                  EHCA_BMASK_IBM( 3,  3)
+#define MQPCB_MASK_PRIM_PHYS_PORT               EHCA_BMASK_IBM( 4,  4)
+#define MQPCB_PRIM_PHYS_PORT                    EHCA_BMASK_IBM(24, 31)
+#define MQPCB_MASK_ALT_PHYS_PORT                EHCA_BMASK_IBM( 5,  5)
+#define MQPCB_MASK_PRIM_P_KEY_IDX               EHCA_BMASK_IBM( 6,  6)
+#define MQPCB_PRIM_P_KEY_IDX                    EHCA_BMASK_IBM(24, 31)
+#define MQPCB_MASK_ALT_P_KEY_IDX                EHCA_BMASK_IBM( 7,  7)
+#define MQPCB_MASK_RDMA_ATOMIC_CTRL             EHCA_BMASK_IBM( 8,  8)
+#define MQPCB_MASK_QP_STATE                     EHCA_BMASK_IBM( 9,  9)
+#define MQPCB_QP_STATE                          EHCA_BMASK_IBM(24, 31)
+#define MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES      EHCA_BMASK_IBM(11, 11)
+#define MQPCB_MASK_PATH_MIGRATION_STATE         EHCA_BMASK_IBM(12, 12)
+#define MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP    EHCA_BMASK_IBM(13, 13)
+#define MQPCB_MASK_DEST_QP_NR                   EHCA_BMASK_IBM(14, 14)
+#define MQPCB_MASK_MIN_RNR_NAK_TIMER_FIELD      EHCA_BMASK_IBM(15, 15)
+#define MQPCB_MASK_SERVICE_LEVEL                EHCA_BMASK_IBM(16, 16)
+#define MQPCB_MASK_SEND_GRH_FLAG                EHCA_BMASK_IBM(17, 17)
+#define MQPCB_MASK_RETRY_COUNT                  EHCA_BMASK_IBM(18, 18)
+#define MQPCB_MASK_TIMEOUT                      EHCA_BMASK_IBM(19, 19)
+#define MQPCB_MASK_PATH_MTU                     EHCA_BMASK_IBM(20, 20)
+#define MQPCB_PATH_MTU                          EHCA_BMASK_IBM(24, 31)
+#define MQPCB_MASK_MAX_STATIC_RATE              EHCA_BMASK_IBM(21, 21)
+#define MQPCB_MAX_STATIC_RATE                   EHCA_BMASK_IBM(24, 31)
+#define MQPCB_MASK_DLID                         EHCA_BMASK_IBM(22, 22)
+#define MQPCB_DLID                              EHCA_BMASK_IBM(16, 31)
+#define MQPCB_MASK_RNR_RETRY_COUNT              EHCA_BMASK_IBM(23, 23)
+#define MQPCB_RNR_RETRY_COUNT                   EHCA_BMASK_IBM(29, 31)
+#define MQPCB_MASK_SOURCE_PATH_BITS             EHCA_BMASK_IBM(24, 24)
+#define MQPCB_SOURCE_PATH_BITS                  EHCA_BMASK_IBM(25, 31)
+#define MQPCB_MASK_TRAFFIC_CLASS                EHCA_BMASK_IBM(25, 25)
+#define MQPCB_TRAFFIC_CLASS                     EHCA_BMASK_IBM(24, 31)
+#define MQPCB_MASK_HOP_LIMIT                    EHCA_BMASK_IBM(26, 26)
+#define MQPCB_HOP_LIMIT                         EHCA_BMASK_IBM(24, 31)
+#define MQPCB_MASK_SOURCE_GID_IDX               EHCA_BMASK_IBM(27, 27)
+#define MQPCB_SOURCE_GID_IDX                    EHCA_BMASK_IBM(24, 31)
+#define MQPCB_MASK_FLOW_LABEL                   EHCA_BMASK_IBM(28, 28)
+#define MQPCB_FLOW_LABEL                        EHCA_BMASK_IBM(12, 31)
+#define MQPCB_MASK_DEST_GID                     EHCA_BMASK_IBM(30, 30)
+#define MQPCB_MASK_SERVICE_LEVEL_AL             EHCA_BMASK_IBM(31, 31)
+#define MQPCB_SERVICE_LEVEL_AL                  EHCA_BMASK_IBM(28, 31)
+#define MQPCB_MASK_SEND_GRH_FLAG_AL             EHCA_BMASK_IBM(32, 32)
+#define MQPCB_SEND_GRH_FLAG_AL                  EHCA_BMASK_IBM(31, 31)
+#define MQPCB_MASK_RETRY_COUNT_AL               EHCA_BMASK_IBM(33, 33)
+#define MQPCB_RETRY_COUNT_AL                    EHCA_BMASK_IBM(29, 31)
+#define MQPCB_MASK_TIMEOUT_AL                   EHCA_BMASK_IBM(34, 34)
+#define MQPCB_TIMEOUT_AL                        EHCA_BMASK_IBM(27, 31)
+#define MQPCB_MASK_MAX_STATIC_RATE_AL           EHCA_BMASK_IBM(35, 35)
+#define MQPCB_MAX_STATIC_RATE_AL                EHCA_BMASK_IBM(24, 31)
+#define MQPCB_MASK_DLID_AL                      EHCA_BMASK_IBM(36, 36)
+#define MQPCB_DLID_AL                           EHCA_BMASK_IBM(16, 31)
+#define MQPCB_MASK_RNR_RETRY_COUNT_AL           EHCA_BMASK_IBM(37, 37)
+#define MQPCB_RNR_RETRY_COUNT_AL                EHCA_BMASK_IBM(29, 31)
+#define MQPCB_MASK_SOURCE_PATH_BITS_AL          EHCA_BMASK_IBM(38, 38)
+#define MQPCB_SOURCE_PATH_BITS_AL               EHCA_BMASK_IBM(25, 31)
+#define MQPCB_MASK_TRAFFIC_CLASS_AL             EHCA_BMASK_IBM(39, 39)
+#define MQPCB_TRAFFIC_CLASS_AL                  EHCA_BMASK_IBM(24, 31)
+#define MQPCB_MASK_HOP_LIMIT_AL                 EHCA_BMASK_IBM(40, 40)
+#define MQPCB_HOP_LIMIT_AL                      EHCA_BMASK_IBM(24, 31)
+#define MQPCB_MASK_SOURCE_GID_IDX_AL            EHCA_BMASK_IBM(41, 41)
+#define MQPCB_SOURCE_GID_IDX_AL                 EHCA_BMASK_IBM(24, 31)
+#define MQPCB_MASK_FLOW_LABEL_AL                EHCA_BMASK_IBM(42, 42)
+#define MQPCB_FLOW_LABEL_AL                     EHCA_BMASK_IBM(12, 31)
+#define MQPCB_MASK_DEST_GID_AL                  EHCA_BMASK_IBM(44, 44)
+#define MQPCB_MASK_MAX_NR_OUTST_SEND_WR         EHCA_BMASK_IBM(45, 45)
+#define MQPCB_MAX_NR_OUTST_SEND_WR              EHCA_BMASK_IBM(16, 31)
+#define MQPCB_MASK_MAX_NR_OUTST_RECV_WR         EHCA_BMASK_IBM(46, 46)
+#define MQPCB_MAX_NR_OUTST_RECV_WR              EHCA_BMASK_IBM(16, 31)
+#define MQPCB_MASK_DISABLE_ETE_CREDIT_CHECK     EHCA_BMASK_IBM(47, 47)
+#define MQPCB_DISABLE_ETE_CREDIT_CHECK          EHCA_BMASK_IBM(31, 31)
+#define MQPCB_QP_NUMBER                         EHCA_BMASK_IBM( 8, 31)
+#define MQPCB_MASK_QP_ENABLE                    EHCA_BMASK_IBM(48, 48)
+#define MQPCB_QP_ENABLE                         EHCA_BMASK_IBM(31, 31)
+#define MQPCB_MASK_CURR_SRQ_LIMIT               EHCA_BMASK_IBM(49, 49)
+#define MQPCB_CURR_SRQ_LIMIT                    EHCA_BMASK_IBM(16, 31)
+#define MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG       EHCA_BMASK_IBM(50, 50)
+#define MQPCB_MASK_SHARED_RQ_HNDL               EHCA_BMASK_IBM(51, 51)
 
 #endif /* __EHCA_CLASSES_PSERIES_H__ */
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 97da51e..ba1bcb9 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -97,7 +97,7 @@ int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int real_qp_num)
 	return ret;
 }
 
-struct ehca_qp* ehca_cq_get_qp(struct ehca_cq *cq, int real_qp_num)
+struct ehca_qp *ehca_cq_get_qp(struct ehca_cq *cq, int real_qp_num)
 {
 	struct ehca_qp *ret = NULL;
 	unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1);
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
index d443bcb..78a2e5a 100644
--- a/drivers/infiniband/hw/ehca/ehca_eq.c
+++ b/drivers/infiniband/hw/ehca/ehca_eq.c
@@ -111,7 +111,8 @@ struct ehca_eq *ehca_create_eq(struct ehca_shca *shca,
 	for (i = 0; i < nr_pages; i++) {
 		u64 rpage;
 
-		if (!(vpage = ipz_qpageit_get_inc(&eq->ipz_queue))) {
+		vpage = ipz_qpageit_get_inc(&eq->ipz_queue);
+		if (!vpage) {
 			ret = -ENOMEM;
 			goto create_eq_exit2;
 		}
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index bbd3c6a..fc19ef9 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -127,6 +127,7 @@ int ehca_query_port(struct ib_device *ibdev,
 		    u8 port, struct ib_port_attr *props)
 {
 	int ret = 0;
+	u64 h_ret;
 	struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
 					      ib_device);
 	struct hipz_query_port *rblock;
@@ -137,7 +138,8 @@ int ehca_query_port(struct ib_device *ibdev,
 		return -ENOMEM;
 	}
 
-	if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
+	h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock);
+	if (h_ret != H_SUCCESS) {
 		ehca_err(&shca->ib_device, "Can't query port properties");
 		ret = -EINVAL;
 		goto query_port1;
@@ -197,6 +199,7 @@ int ehca_query_sma_attr(struct ehca_shca *shca,
 			u8 port, struct ehca_sma_attr *attr)
 {
 	int ret = 0;
+	u64 h_ret;
 	struct hipz_query_port *rblock;
 
 	rblock = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
@@ -205,7 +208,8 @@ int ehca_query_sma_attr(struct ehca_shca *shca,
 		return -ENOMEM;
 	}
 
-	if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
+	h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock);
+	if (h_ret != H_SUCCESS) {
 		ehca_err(&shca->ib_device, "Can't query port properties");
 		ret = -EINVAL;
 		goto query_sma_attr1;
@@ -230,9 +234,11 @@ query_sma_attr1:
 int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
 {
 	int ret = 0;
-	struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, ib_device);
+	u64 h_ret;
+	struct ehca_shca *shca;
 	struct hipz_query_port *rblock;
 
+	shca = container_of(ibdev, struct ehca_shca, ib_device);
 	if (index > 16) {
 		ehca_err(&shca->ib_device, "Invalid index: %x.", index);
 		return -EINVAL;
@@ -244,7 +250,8 @@ int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
 		return -ENOMEM;
 	}
 
-	if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
+	h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock);
+	if (h_ret != H_SUCCESS) {
 		ehca_err(&shca->ib_device, "Can't query port properties");
 		ret = -EINVAL;
 		goto query_pkey1;
@@ -262,6 +269,7 @@ int ehca_query_gid(struct ib_device *ibdev, u8 port,
 		   int index, union ib_gid *gid)
 {
 	int ret = 0;
+	u64 h_ret;
 	struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
 					      ib_device);
 	struct hipz_query_port *rblock;
@@ -277,7 +285,8 @@ int ehca_query_gid(struct ib_device *ibdev, u8 port,
 		return -ENOMEM;
 	}
 
-	if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
+	h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock);
+	if (h_ret != H_SUCCESS) {
 		ehca_err(&shca->ib_device, "Can't query port properties");
 		ret = -EINVAL;
 		goto query_gid1;
@@ -302,11 +311,12 @@ int ehca_modify_port(struct ib_device *ibdev,
 		     struct ib_port_modify *props)
 {
 	int ret = 0;
-	struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, ib_device);
+	struct ehca_shca *shca;
 	struct hipz_query_port *rblock;
 	u32 cap;
 	u64 hret;
 
+	shca = container_of(ibdev, struct ehca_shca, ib_device);
 	if ((props->set_port_cap_mask | props->clr_port_cap_mask)
 	    & ~allowed_port_caps) {
 		ehca_err(&shca->ib_device, "Non-changeable bits set in masks  "
@@ -325,7 +335,8 @@ int ehca_modify_port(struct ib_device *ibdev,
 		goto modify_port1;
 	}
 
-	if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
+	hret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock);
+	if (hret != H_SUCCESS) {
 		ehca_err(&shca->ib_device, "Can't query port properties");
 		ret = -EINVAL;
 		goto modify_port2;
@@ -337,7 +348,8 @@ int ehca_modify_port(struct ib_device *ibdev,
 	hret = hipz_h_modify_port(shca->ipz_hca_handle, port,
 				  cap, props->init_type, port_modify_mask);
 	if (hret != H_SUCCESS) {
-		ehca_err(&shca->ib_device, "Modify port failed  hret=%lx", hret);
+		ehca_err(&shca->ib_device, "Modify port failed  hret=%lx",
+			 hret);
 		ret = -EINVAL;
 	}
 
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 7a4071a..1f043d0 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -49,26 +49,26 @@
 #include "hipz_fns.h"
 #include "ipz_pt_fn.h"
 
-#define EQE_COMPLETION_EVENT   EHCA_BMASK_IBM(1,1)
-#define EQE_CQ_QP_NUMBER       EHCA_BMASK_IBM(8,31)
-#define EQE_EE_IDENTIFIER      EHCA_BMASK_IBM(2,7)
-#define EQE_CQ_NUMBER          EHCA_BMASK_IBM(8,31)
-#define EQE_QP_NUMBER          EHCA_BMASK_IBM(8,31)
-#define EQE_QP_TOKEN           EHCA_BMASK_IBM(32,63)
-#define EQE_CQ_TOKEN           EHCA_BMASK_IBM(32,63)
-
-#define NEQE_COMPLETION_EVENT  EHCA_BMASK_IBM(1,1)
-#define NEQE_EVENT_CODE        EHCA_BMASK_IBM(2,7)
-#define NEQE_PORT_NUMBER       EHCA_BMASK_IBM(8,15)
-#define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16,16)
-#define NEQE_DISRUPTIVE        EHCA_BMASK_IBM(16,16)
-
-#define ERROR_DATA_LENGTH      EHCA_BMASK_IBM(52,63)
-#define ERROR_DATA_TYPE        EHCA_BMASK_IBM(0,7)
+#define EQE_COMPLETION_EVENT   EHCA_BMASK_IBM( 1,  1)
+#define EQE_CQ_QP_NUMBER       EHCA_BMASK_IBM( 8, 31)
+#define EQE_EE_IDENTIFIER      EHCA_BMASK_IBM( 2,  7)
+#define EQE_CQ_NUMBER          EHCA_BMASK_IBM( 8, 31)
+#define EQE_QP_NUMBER          EHCA_BMASK_IBM( 8, 31)
+#define EQE_QP_TOKEN           EHCA_BMASK_IBM(32, 63)
+#define EQE_CQ_TOKEN           EHCA_BMASK_IBM(32, 63)
+
+#define NEQE_COMPLETION_EVENT  EHCA_BMASK_IBM( 1,  1)
+#define NEQE_EVENT_CODE        EHCA_BMASK_IBM( 2,  7)
+#define NEQE_PORT_NUMBER       EHCA_BMASK_IBM( 8, 15)
+#define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16, 16)
+#define NEQE_DISRUPTIVE        EHCA_BMASK_IBM(16, 16)
+
+#define ERROR_DATA_LENGTH      EHCA_BMASK_IBM(52, 63)
+#define ERROR_DATA_TYPE        EHCA_BMASK_IBM( 0,  7)
 
 static void queue_comp_task(struct ehca_cq *__cq);
 
-static struct ehca_comp_pool* pool;
+static struct ehca_comp_pool *pool;
 #ifdef CONFIG_HOTPLUG_CPU
 static struct notifier_block comp_pool_callback_nb;
 #endif
@@ -85,8 +85,8 @@ static inline void comp_event_callback(struct ehca_cq *cq)
 	return;
 }
 
-static void print_error_data(struct ehca_shca * shca, void* data,
-			     u64* rblock, int length)
+static void print_error_data(struct ehca_shca *shca, void *data,
+			     u64 *rblock, int length)
 {
 	u64 type = EHCA_BMASK_GET(ERROR_DATA_TYPE, rblock[2]);
 	u64 resource = rblock[1];
@@ -94,7 +94,7 @@ static void print_error_data(struct ehca_shca * shca, void* data,
 	switch (type) {
 	case 0x1: /* Queue Pair */
 	{
-		struct ehca_qp *qp = (struct ehca_qp*)data;
+		struct ehca_qp *qp = (struct ehca_qp *)data;
 
 		/* only print error data if AER is set */
 		if (rblock[6] == 0)
@@ -107,7 +107,7 @@ static void print_error_data(struct ehca_shca * shca, void* data,
 	}
 	case 0x4: /* Completion Queue */
 	{
-		struct ehca_cq *cq = (struct ehca_cq*)data;
+		struct ehca_cq *cq = (struct ehca_cq *)data;
 
 		ehca_err(&shca->ib_device,
 			 "CQ 0x%x (resource=%lx) has errors.",
@@ -564,7 +564,7 @@ void ehca_tasklet_eq(unsigned long data)
 	ehca_process_eq((struct ehca_eq *)data, 1);
 }
 
-static inline int find_next_online_cpu(struct ehca_comp_pool* pool)
+static inline int find_next_online_cpu(struct ehca_comp_pool *pool)
 {
 	int cpu;
 	unsigned long flags;
@@ -628,7 +628,7 @@ static void queue_comp_task(struct ehca_cq *__cq)
 	__queue_comp_task(__cq, cct);
 }
 
-static void run_comp_task(struct ehca_cpu_comp_task* cct)
+static void run_comp_task(struct ehca_cpu_comp_task *cct)
 {
 	struct ehca_cq *cq;
 	unsigned long flags;
@@ -658,12 +658,12 @@ static void run_comp_task(struct ehca_cpu_comp_task* cct)
 
 static int comp_task(void *__cct)
 {
-	struct ehca_cpu_comp_task* cct = __cct;
+	struct ehca_cpu_comp_task *cct = __cct;
 	int cql_empty;
 	DECLARE_WAITQUEUE(wait, current);
 
 	set_current_state(TASK_INTERRUPTIBLE);
-	while(!kthread_should_stop()) {
+	while (!kthread_should_stop()) {
 		add_wait_queue(&cct->wait_queue, &wait);
 
 		spin_lock_irq(&cct->task_lock);
@@ -737,7 +737,7 @@ static void take_over_work(struct ehca_comp_pool *pool,
 
 	list_splice_init(&cct->cq_list, &list);
 
-	while(!list_empty(&list)) {
+	while (!list_empty(&list)) {
 		cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
 
 		list_del(&cq->entry);
@@ -760,7 +760,7 @@ static int comp_pool_callback(struct notifier_block *nfb,
 	case CPU_UP_PREPARE:
 	case CPU_UP_PREPARE_FROZEN:
 		ehca_gen_dbg("CPU: %x (CPU_PREPARE)", cpu);
-		if(!create_comp_task(pool, cpu)) {
+		if (!create_comp_task(pool, cpu)) {
 			ehca_gen_err("Can't create comp_task for cpu: %x", cpu);
 			return NOTIFY_BAD;
 		}
@@ -830,7 +830,7 @@ int ehca_create_comp_pool(void)
 
 #ifdef CONFIG_HOTPLUG_CPU
 	comp_pool_callback_nb.notifier_call = comp_pool_callback;
-	comp_pool_callback_nb.priority =0;
+	comp_pool_callback_nb.priority = 0;
 	register_cpu_notifier(&comp_pool_callback_nb);
 #endif
 
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index bf8fbf7..99881e3 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -81,8 +81,9 @@ struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd,
 			       int num_phys_buf,
 			       int mr_access_flags, u64 *iova_start);
 
-struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt,
-			       int mr_access_flags, struct ib_udata *udata);
+struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+			       u64 virt, int mr_access_flags,
+			       struct ib_udata *udata);
 
 int ehca_rereg_phys_mr(struct ib_mr *mr,
 		       int mr_rereg_mask,
@@ -191,7 +192,7 @@ void ehca_poll_eqs(unsigned long data);
 void *ehca_alloc_fw_ctrlblock(gfp_t flags);
 void ehca_free_fw_ctrlblock(void *ptr);
 #else
-#define ehca_alloc_fw_ctrlblock(flags) ((void *) get_zeroed_page(flags))
+#define ehca_alloc_fw_ctrlblock(flags) ((void *)get_zeroed_page(flags))
 #define ehca_free_fw_ctrlblock(ptr) free_page((unsigned long)(ptr))
 #endif
 
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 57c551e..ecf4ef4 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -116,7 +116,7 @@ static DEFINE_SPINLOCK(shca_list_lock);
 static struct timer_list poll_eqs_timer;
 
 #ifdef CONFIG_PPC_64K_PAGES
-static struct kmem_cache *ctblk_cache = NULL;
+static struct kmem_cache *ctblk_cache;
 
 void *ehca_alloc_fw_ctrlblock(gfp_t flags)
 {
@@ -219,8 +219,8 @@ static void ehca_destroy_slab_caches(void)
 #endif
 }
 
-#define EHCA_HCAAVER  EHCA_BMASK_IBM(32,39)
-#define EHCA_REVID    EHCA_BMASK_IBM(40,63)
+#define EHCA_HCAAVER  EHCA_BMASK_IBM(32, 39)
+#define EHCA_REVID    EHCA_BMASK_IBM(40, 63)
 
 static struct cap_descr {
 	u64 mask;
@@ -314,7 +314,7 @@ int ehca_sense_attributes(struct ehca_shca *shca)
 		if (EHCA_BMASK_GET(hca_cap_descr[i].mask, shca->hca_cap))
 			ehca_gen_dbg("   %s", hca_cap_descr[i].descr);
 
-	port = (struct hipz_query_port *) rblock;
+	port = (struct hipz_query_port *)rblock;
 	h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port);
 	if (h_ret != H_SUCCESS) {
 		ehca_gen_err("Cannot query port properties. h_ret=%lx",
@@ -463,7 +463,7 @@ static int ehca_create_aqp1(struct ehca_shca *shca, u32 port)
 		return -EPERM;
 	}
 
-	ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void*)(-1), 10, 0);
+	ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void *)(-1), 10, 0);
 	if (IS_ERR(ibcq)) {
 		ehca_err(&shca->ib_device, "Cannot create AQP1 CQ.");
 		return PTR_ERR(ibcq);
@@ -730,7 +730,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
 	}
 
 	/* create internal protection domain */
-	ibpd = ehca_alloc_pd(&shca->ib_device, (void*)(-1), NULL);
+	ibpd = ehca_alloc_pd(&shca->ib_device, (void *)(-1), NULL);
 	if (IS_ERR(ibpd)) {
 		ehca_err(&shca->ib_device, "Cannot create internal PD.");
 		ret = PTR_ERR(ibpd);
@@ -944,18 +944,21 @@ int __init ehca_module_init(void)
 		return -EINVAL;
 	}
 
-	if ((ret = ehca_create_comp_pool())) {
+	ret = ehca_create_comp_pool();
+	if (ret) {
 		ehca_gen_err("Cannot create comp pool.");
 		return ret;
 	}
 
-	if ((ret = ehca_create_slab_caches())) {
+	ret = ehca_create_slab_caches();
+	if (ret) {
 		ehca_gen_err("Cannot create SLAB caches");
 		ret = -ENOMEM;
 		goto module_init1;
 	}
 
-	if ((ret = ibmebus_register_driver(&ehca_driver))) {
+	ret = ibmebus_register_driver(&ehca_driver);
+	if (ret) {
 		ehca_gen_err("Cannot register eHCA device driver");
 		ret = -EINVAL;
 		goto module_init2;
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index 93c26cc..6262c54 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -61,9 +61,9 @@ static struct ehca_mr *ehca_mr_new(void)
 	struct ehca_mr *me;
 
 	me = kmem_cache_zalloc(mr_cache, GFP_KERNEL);
-	if (me) {
+	if (me)
 		spin_lock_init(&me->mrlock);
-	} else
+	else
 		ehca_gen_err("alloc failed");
 
 	return me;
@@ -79,9 +79,9 @@ static struct ehca_mw *ehca_mw_new(void)
 	struct ehca_mw *me;
 
 	me = kmem_cache_zalloc(mw_cache, GFP_KERNEL);
-	if (me) {
+	if (me)
 		spin_lock_init(&me->mwlock);
-	} else
+	else
 		ehca_gen_err("alloc failed");
 
 	return me;
@@ -111,7 +111,7 @@ struct ib_mr *ehca_get_dma_mr(struct ib_pd *pd, int mr_access_flags)
 			goto get_dma_mr_exit0;
 		}
 
-		ret = ehca_reg_maxmr(shca, e_maxmr, (u64*)KERNELBASE,
+		ret = ehca_reg_maxmr(shca, e_maxmr, (u64 *)KERNELBASE,
 				     mr_access_flags, e_pd,
 				     &e_maxmr->ib.ib_mr.lkey,
 				     &e_maxmr->ib.ib_mr.rkey);
@@ -246,8 +246,9 @@ reg_phys_mr_exit0:
 
 /*----------------------------------------------------------------------*/
 
-struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt,
-			       int mr_access_flags, struct ib_udata *udata)
+struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+			       u64 virt, int mr_access_flags,
+			       struct ib_udata *udata)
 {
 	struct ib_mr *ib_mr;
 	struct ehca_mr *e_mr;
@@ -295,7 +296,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt
 	e_mr->umem = ib_umem_get(pd->uobject->context, start, length,
 				 mr_access_flags);
 	if (IS_ERR(e_mr->umem)) {
-		ib_mr = (void *) e_mr->umem;
+		ib_mr = (void *)e_mr->umem;
 		goto reg_user_mr_exit1;
 	}
 
@@ -322,8 +323,9 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt
 						     (&e_mr->umem->chunk_list),
 						     list);
 
-	ret = ehca_reg_mr(shca, e_mr, (u64*) virt, length, mr_access_flags, e_pd,
-			  &pginfo, &e_mr->ib.ib_mr.lkey, &e_mr->ib.ib_mr.rkey);
+	ret = ehca_reg_mr(shca, e_mr, (u64 *)virt, length, mr_access_flags,
+			  e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
+			  &e_mr->ib.ib_mr.rkey);
 	if (ret) {
 		ib_mr = ERR_PTR(ret);
 		goto reg_user_mr_exit2;
@@ -420,7 +422,7 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
 			goto rereg_phys_mr_exit0;
 		}
 		if (!phys_buf_array || num_phys_buf <= 0) {
-			ehca_err(mr->device, "bad input values: mr_rereg_mask=%x"
+			ehca_err(mr->device, "bad input values mr_rereg_mask=%x"
 				 " phys_buf_array=%p num_phys_buf=%x",
 				 mr_rereg_mask, phys_buf_array, num_phys_buf);
 			ret = -EINVAL;
@@ -444,10 +446,10 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
 
 	/* set requested values dependent on rereg request */
 	spin_lock_irqsave(&e_mr->mrlock, sl_flags);
-	new_start = e_mr->start;  /* new == old address */
-	new_size  = e_mr->size;	  /* new == old length */
-	new_acl   = e_mr->acl;	  /* new == old access control */
-	new_pd    = container_of(mr->pd,struct ehca_pd,ib_pd); /*new == old PD*/
+	new_start = e_mr->start;
+	new_size = e_mr->size;
+	new_acl = e_mr->acl;
+	new_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
 
 	if (mr_rereg_mask & IB_MR_REREG_TRANS) {
 		new_start = iova_start;	/* change address */
@@ -517,7 +519,7 @@ int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr)
 	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 = {{0},0,0,0,0,0};
+	struct ehca_mr_hipzout_parms hipzout;
 
 	if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
 	    (my_pd->ownpid != cur_pid)) {
@@ -629,7 +631,7 @@ struct ib_mw *ehca_alloc_mw(struct ib_pd *pd)
 	struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd);
 	struct ehca_shca *shca =
 		container_of(pd->device, struct ehca_shca, ib_device);
-	struct ehca_mw_hipzout_parms hipzout = {{0},0};
+	struct ehca_mw_hipzout_parms hipzout;
 
 	e_mw = ehca_mw_new();
 	if (!e_mw) {
@@ -826,7 +828,7 @@ int ehca_map_phys_fmr(struct ib_fmr *fmr,
 			      EHCA_PAGESIZE);
 	pginfo.u.fmr.fmr_pgsize = e_fmr->fmr_page_size;
 
-	ret = ehca_rereg_mr(shca, e_fmr, (u64*)iova,
+	ret = ehca_rereg_mr(shca, e_fmr, (u64 *)iova,
 			    list_len * e_fmr->fmr_page_size,
 			    e_fmr->acl, e_pd, &pginfo, &tmp_lkey, &tmp_rkey);
 	if (ret)
@@ -841,8 +843,7 @@ int ehca_map_phys_fmr(struct ib_fmr *fmr,
 map_phys_fmr_exit0:
 	if (ret)
 		ehca_err(fmr->device, "ret=%x fmr=%p page_list=%p list_len=%x "
-			 "iova=%lx",
-			 ret, fmr, page_list, list_len, iova);
+			 "iova=%lx", ret, fmr, page_list, list_len, iova);
 	return ret;
 } /* end ehca_map_phys_fmr() */
 
@@ -960,12 +961,12 @@ int ehca_reg_mr(struct ehca_shca *shca,
 	int ret;
 	u64 h_ret;
 	u32 hipz_acl;
-	struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0};
+	struct ehca_mr_hipzout_parms hipzout;
 
 	ehca_mrmw_map_acl(acl, &hipz_acl);
 	ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl);
 	if (ehca_use_hp_mr == 1)
-	        hipz_acl |= 0x00000001;
+		hipz_acl |= 0x00000001;
 
 	h_ret = hipz_h_alloc_resource_mr(shca->ipz_hca_handle, e_mr,
 					 (u64)iova_start, size, hipz_acl,
@@ -1127,7 +1128,7 @@ inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca,
 	u64 *kpage;
 	u64 rpage;
 	struct ehca_mr_pginfo pginfo_save;
-	struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0};
+	struct ehca_mr_hipzout_parms hipzout;
 
 	ehca_mrmw_map_acl(acl, &hipz_acl);
 	ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl);
@@ -1167,7 +1168,7 @@ inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca,
 			  "(Rereg1), h_ret=%lx e_mr=%p", h_ret, e_mr);
 		*pginfo = pginfo_save;
 		ret = -EAGAIN;
-	} else if ((u64*)hipzout.vaddr != iova_start) {
+	} else if ((u64 *)hipzout.vaddr != iova_start) {
 		ehca_err(&shca->ib_device, "PHYP changed iova_start in "
 			 "rereg_pmr, iova_start=%p iova_start_out=%lx e_mr=%p "
 			 "mr_handle=%lx lkey=%x lkey_out=%x", iova_start,
@@ -1305,7 +1306,7 @@ int ehca_unmap_one_fmr(struct ehca_shca *shca,
 	struct ehca_mr save_fmr;
 	u32 tmp_lkey, tmp_rkey;
 	struct ehca_mr_pginfo pginfo;
-	struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0};
+	struct ehca_mr_hipzout_parms hipzout;
 	struct ehca_mr save_mr;
 
 	if (e_fmr->fmr_max_pages <= MAX_RPAGES) {
@@ -1397,7 +1398,7 @@ int ehca_reg_smr(struct ehca_shca *shca,
 	int ret = 0;
 	u64 h_ret;
 	u32 hipz_acl;
-	struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0};
+	struct ehca_mr_hipzout_parms hipzout;
 
 	ehca_mrmw_map_acl(acl, &hipz_acl);
 	ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl);
@@ -1462,7 +1463,7 @@ int ehca_reg_internal_maxmr(
 
 	/* register internal max-MR on HCA */
 	size_maxmr = (u64)high_memory - PAGE_OFFSET;
-	iova_start = (u64*)KERNELBASE;
+	iova_start = (u64 *)KERNELBASE;
 	ib_pbuf.addr = 0;
 	ib_pbuf.size = size_maxmr;
 	num_kpages = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size_maxmr,
@@ -1519,7 +1520,7 @@ int ehca_reg_maxmr(struct ehca_shca *shca,
 	u64 h_ret;
 	struct ehca_mr *e_origmr = shca->maxmr;
 	u32 hipz_acl;
-	struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0};
+	struct ehca_mr_hipzout_parms hipzout;
 
 	ehca_mrmw_map_acl(acl, &hipz_acl);
 	ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl);
@@ -1865,7 +1866,7 @@ int ehca_mr_is_maxmr(u64 size,
 {
 	/* a MR is treated as max-MR only if it fits following: */
 	if ((size == ((u64)high_memory - PAGE_OFFSET)) &&
-	    (iova_start == (void*)KERNELBASE)) {
+	    (iova_start == (void *)KERNELBASE)) {
 		ehca_gen_dbg("this is a max-MR");
 		return 1;
 	} else
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.h b/drivers/infiniband/hw/ehca/ehca_mrmw.h
index fb69ede..24f13fe 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.h
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.h
@@ -101,15 +101,10 @@ int ehca_fmr_check_page_list(struct ehca_mr *e_fmr,
 			     u64 *page_list,
 			     int list_len);
 
-int ehca_set_pagebuf(struct ehca_mr *e_mr,
-		     struct ehca_mr_pginfo *pginfo,
+int ehca_set_pagebuf(struct ehca_mr_pginfo *pginfo,
 		     u32 number,
 		     u64 *kpage);
 
-int ehca_set_pagebuf_1(struct ehca_mr *e_mr,
-		       struct ehca_mr_pginfo *pginfo,
-		       u64 *rpage);
-
 int ehca_mr_is_maxmr(u64 size,
 		     u64 *iova_start);
 
diff --git a/drivers/infiniband/hw/ehca/ehca_qes.h b/drivers/infiniband/hw/ehca/ehca_qes.h
index 8707d29..8188030 100644
--- a/drivers/infiniband/hw/ehca/ehca_qes.h
+++ b/drivers/infiniband/hw/ehca/ehca_qes.h
@@ -53,13 +53,13 @@ struct ehca_vsgentry {
 	u32 length;
 };
 
-#define GRH_FLAG_MASK        EHCA_BMASK_IBM(7,7)
-#define GRH_IPVERSION_MASK   EHCA_BMASK_IBM(0,3)
-#define GRH_TCLASS_MASK      EHCA_BMASK_IBM(4,12)
-#define GRH_FLOWLABEL_MASK   EHCA_BMASK_IBM(13,31)
-#define GRH_PAYLEN_MASK      EHCA_BMASK_IBM(32,47)
-#define GRH_NEXTHEADER_MASK  EHCA_BMASK_IBM(48,55)
-#define GRH_HOPLIMIT_MASK    EHCA_BMASK_IBM(56,63)
+#define GRH_FLAG_MASK        EHCA_BMASK_IBM( 7,  7)
+#define GRH_IPVERSION_MASK   EHCA_BMASK_IBM( 0,  3)
+#define GRH_TCLASS_MASK      EHCA_BMASK_IBM( 4, 12)
+#define GRH_FLOWLABEL_MASK   EHCA_BMASK_IBM(13, 31)
+#define GRH_PAYLEN_MASK      EHCA_BMASK_IBM(32, 47)
+#define GRH_NEXTHEADER_MASK  EHCA_BMASK_IBM(48, 55)
+#define GRH_HOPLIMIT_MASK    EHCA_BMASK_IBM(56, 63)
 
 /*
  * Unreliable Datagram Address Vector Format
@@ -206,10 +206,10 @@ struct ehca_wqe {
 
 };
 
-#define WC_SEND_RECEIVE EHCA_BMASK_IBM(0,0)
-#define WC_IMM_DATA     EHCA_BMASK_IBM(1,1)
-#define WC_GRH_PRESENT  EHCA_BMASK_IBM(2,2)
-#define WC_SE_BIT       EHCA_BMASK_IBM(3,3)
+#define WC_SEND_RECEIVE EHCA_BMASK_IBM(0, 0)
+#define WC_IMM_DATA     EHCA_BMASK_IBM(1, 1)
+#define WC_GRH_PRESENT  EHCA_BMASK_IBM(2, 2)
+#define WC_SE_BIT       EHCA_BMASK_IBM(3, 3)
 #define WC_STATUS_ERROR_BIT 0x80000000
 #define WC_STATUS_REMOTE_ERROR_FLAGS 0x0000F800
 #define WC_STATUS_PURGE_BIT 0x10
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index f6f4ef6..3bd13e1 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -602,10 +602,10 @@ struct ehca_qp *internal_create_qp(struct ib_pd *pd,
 			/* UD circumvention */
 			parms.act_nr_send_sges -= 2;
 			parms.act_nr_recv_sges -= 2;
-			swqe_size = offsetof(struct ehca_wqe,
-					     u.ud_av.sg_list[parms.act_nr_send_sges]);
-			rwqe_size = offsetof(struct ehca_wqe,
-					     u.ud_av.sg_list[parms.act_nr_recv_sges]);
+			swqe_size = offsetof(struct ehca_wqe, u.ud_av.sg_list[
+						     parms.act_nr_send_sges]);
+			rwqe_size = offsetof(struct ehca_wqe, u.ud_av.sg_list[
+						     parms.act_nr_recv_sges]);
 		}
 
 		if (IB_QPT_GSI == qp_type || IB_QPT_SMI == qp_type) {
@@ -690,8 +690,8 @@ struct ehca_qp *internal_create_qp(struct ib_pd *pd,
 	if (my_qp->send_cq) {
 		ret = ehca_cq_assign_qp(my_qp->send_cq, my_qp);
 		if (ret) {
-			ehca_err(pd->device, "Couldn't assign qp to send_cq ret=%x",
-				 ret);
+			ehca_err(pd->device,
+				 "Couldn't assign qp to send_cq ret=%x", ret);
 			goto create_qp_exit4;
 		}
 	}
@@ -749,7 +749,7 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
 	struct ehca_qp *ret;
 
 	ret = internal_create_qp(pd, qp_init_attr, NULL, udata, 0);
-	return IS_ERR(ret) ? (struct ib_qp *) ret : &ret->ib_qp;
+	return IS_ERR(ret) ? (struct ib_qp *)ret : &ret->ib_qp;
 }
 
 int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
@@ -780,7 +780,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
 
 	my_qp = internal_create_qp(pd, &qp_init_attr, srq_init_attr, udata, 1);
 	if (IS_ERR(my_qp))
-		return (struct ib_srq *) my_qp;
+		return (struct ib_srq *)my_qp;
 
 	/* copy back return values */
 	srq_init_attr->attr.max_wr = qp_init_attr.cap.max_recv_wr;
@@ -875,7 +875,7 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
 			 my_qp, qp_num, h_ret);
 		return ehca2ib_return_code(h_ret);
 	}
-	bad_send_wqe_p = (void*)((u64)bad_send_wqe_p & (~(1L<<63)));
+	bad_send_wqe_p = (void *)((u64)bad_send_wqe_p & (~(1L << 63)));
 	ehca_dbg(&shca->ib_device, "qp_num=%x bad_send_wqe_p=%p",
 		 qp_num, bad_send_wqe_p);
 	/* convert wqe pointer to vadr */
@@ -890,7 +890,7 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
 	}
 
 	/* loop sets wqe's purge bit */
-	wqe = (struct ehca_wqe*)ipz_qeit_calc(squeue, q_ofs);
+	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)
@@ -898,7 +898,7 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
 		wqe->nr_of_data_seg = 0; /* suppress data access */
 		wqe->wqef = WQEF_PURGE; /* WQE to be purged */
 		q_ofs = ipz_queue_advance_offset(squeue, q_ofs);
-		wqe = (struct ehca_wqe*)ipz_qeit_calc(squeue, q_ofs);
+		wqe = (struct ehca_wqe *)ipz_qeit_calc(squeue, q_ofs);
 		*bad_wqe_cnt = (*bad_wqe_cnt)+1;
 	}
 	/*
@@ -1003,7 +1003,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
 		goto modify_qp_exit1;
 	}
 
-	ehca_dbg(ibqp->device,"ehca_qp=%p qp_num=%x current qp_state=%x "
+	ehca_dbg(ibqp->device, "ehca_qp=%p qp_num=%x current qp_state=%x "
 		 "new qp_state=%x attribute_mask=%x",
 		 my_qp, ibqp->qp_num, qp_cur_state, attr->qp_state, attr_mask);
 
@@ -1019,7 +1019,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
 		goto modify_qp_exit1;
 	}
 
-	if ((mqpcb->qp_state = ib2ehca_qp_state(qp_new_state)))
+	mqpcb->qp_state = ib2ehca_qp_state(qp_new_state);
+	if (mqpcb->qp_state)
 		update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);
 	else {
 		ret = -EINVAL;
@@ -1077,7 +1078,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
 			spin_lock_irqsave(&my_qp->spinlock_s, flags);
 			squeue_locked = 1;
 			/* mark next free wqe */
-			wqe = (struct ehca_wqe*)
+			wqe = (struct ehca_wqe *)
 				ipz_qeit_get(&my_qp->ipz_squeue);
 			wqe->optype = wqe->wqef = 0xff;
 			ehca_dbg(ibqp->device, "qp_num=%x next_free_wqe=%p",
@@ -1312,7 +1313,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
 	if (h_ret != H_SUCCESS) {
 		ret = ehca2ib_return_code(h_ret);
 		ehca_err(ibqp->device, "hipz_h_modify_qp() failed rc=%lx "
-			 "ehca_qp=%p qp_num=%x",h_ret, my_qp, ibqp->qp_num);
+			 "ehca_qp=%p qp_num=%x", h_ret, my_qp, ibqp->qp_num);
 		goto modify_qp_exit2;
 	}
 
@@ -1411,7 +1412,7 @@ int ehca_query_qp(struct ib_qp *qp,
 	}
 
 	if (qp_attr_mask & QP_ATTR_QUERY_NOT_SUPPORTED) {
-		ehca_err(qp->device,"Invalid attribute mask "
+		ehca_err(qp->device, "Invalid attribute mask "
 			 "ehca_qp=%p qp_num=%x qp_attr_mask=%x ",
 			 my_qp, qp->qp_num, qp_attr_mask);
 		return -EINVAL;
@@ -1419,7 +1420,7 @@ int ehca_query_qp(struct ib_qp *qp,
 
 	qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!qpcb) {
-		ehca_err(qp->device,"Out of memory for qpcb "
+		ehca_err(qp->device, "Out of memory for qpcb "
 			 "ehca_qp=%p qp_num=%x", my_qp, qp->qp_num);
 		return -ENOMEM;
 	}
@@ -1431,7 +1432,7 @@ int ehca_query_qp(struct ib_qp *qp,
 
 	if (h_ret != H_SUCCESS) {
 		ret = ehca2ib_return_code(h_ret);
-		ehca_err(qp->device,"hipz_h_query_qp() failed "
+		ehca_err(qp->device, "hipz_h_query_qp() failed "
 			 "ehca_qp=%p qp_num=%x h_ret=%lx",
 			 my_qp, qp->qp_num, h_ret);
 		goto query_qp_exit1;
@@ -1442,7 +1443,7 @@ int ehca_query_qp(struct ib_qp *qp,
 
 	if (qp_attr->cur_qp_state == -EINVAL) {
 		ret = -EINVAL;
-		ehca_err(qp->device,"Got invalid ehca_qp_state=%x "
+		ehca_err(qp->device, "Got invalid ehca_qp_state=%x "
 			 "ehca_qp=%p qp_num=%x",
 			 qpcb->qp_state, my_qp, qp->qp_num);
 		goto query_qp_exit1;
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
index 61da65e..94eed70 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -79,7 +79,8 @@ static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
 	}
 
 	if (ehca_debug_level) {
-		ehca_gen_dbg("RECEIVE WQE written into ipz_rqueue=%p", ipz_rqueue);
+		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");
 	}
 
@@ -99,7 +100,7 @@ static void trace_send_wr_ud(const struct ib_send_wr *send_wr)
 		struct ib_mad_hdr *mad_hdr = send_wr->wr.ud.mad_hdr;
 		struct ib_sge *sge = send_wr->sg_list;
 		ehca_gen_dbg("send_wr#%x wr_id=%lx num_sge=%x "
-			     "send_flags=%x opcode=%x",idx, send_wr->wr_id,
+			     "send_flags=%x opcode=%x", idx, send_wr->wr_id,
 			     send_wr->num_sge, send_wr->send_flags,
 			     send_wr->opcode);
 		if (mad_hdr) {
@@ -116,7 +117,7 @@ static void trace_send_wr_ud(const struct ib_send_wr *send_wr)
 				     mad_hdr->attr_mod);
 		}
 		for (j = 0; j < send_wr->num_sge; j++) {
-			u8 *data = (u8 *) abs_to_virt(sge->addr);
+			u8 *data = (u8 *)abs_to_virt(sge->addr);
 			ehca_gen_dbg("send_wr#%x sge#%x addr=%p length=%x "
 				     "lkey=%x",
 				     idx, j, data, sge->length, sge->lkey);
@@ -534,9 +535,11 @@ poll_cq_one_read_cqe:
 
 	cqe_count++;
 	if (unlikely(cqe->status & WC_STATUS_PURGE_BIT)) {
-		struct ehca_qp *qp=ehca_cq_get_qp(my_cq, cqe->local_qp_number);
+		struct ehca_qp *qp;
 		int purgeflag;
 		unsigned long flags;
+
+		qp = ehca_cq_get_qp(my_cq, cqe->local_qp_number);
 		if (!qp) {
 			ehca_err(cq->device, "cq_num=%x qp_num=%x "
 				 "could not find qp -> ignore cqe",
@@ -551,8 +554,8 @@ poll_cq_one_read_cqe:
 		spin_unlock_irqrestore(&qp->spinlock_s, flags);
 
 		if (purgeflag) {
-			ehca_dbg(cq->device, "Got CQE with purged bit qp_num=%x "
-				 "src_qp=%x",
+			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)
 				ehca_dmp(cqe, 64, "qp_num=%x src_qp=%x",
diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h
index fd8238b..678b813 100644
--- a/drivers/infiniband/hw/ehca/ehca_tools.h
+++ b/drivers/infiniband/hw/ehca/ehca_tools.h
@@ -93,14 +93,14 @@ extern int ehca_debug_level;
 #define ehca_gen_dbg(format, arg...) \
 	do { \
 		if (unlikely(ehca_debug_level)) \
-			printk(KERN_DEBUG "PU%04x EHCA_DBG:%s " format "\n",\
+			printk(KERN_DEBUG "PU%04x EHCA_DBG:%s " format "\n", \
 			       get_paca()->paca_index, __FUNCTION__, ## arg); \
 	} while (0)
 
 #define ehca_gen_warn(format, arg...) \
 	do { \
 		if (unlikely(ehca_debug_level)) \
-			printk(KERN_INFO "PU%04x EHCA_WARN:%s " format "\n",\
+			printk(KERN_INFO "PU%04x EHCA_WARN:%s " format "\n", \
 			       get_paca()->paca_index, __FUNCTION__, ## arg); \
 	} while (0)
 
@@ -114,12 +114,12 @@ extern int ehca_debug_level;
  * <format string> adr=X ofs=Y <8 bytes hex> <8 bytes hex>
  */
 #define ehca_dmp(adr, len, format, args...) \
-	do {				       \
-		unsigned int x;			      \
+	do { \
+		unsigned int x; \
 		unsigned int l = (unsigned int)(len); \
-		unsigned char *deb = (unsigned char*)(adr);	\
+		unsigned char *deb = (unsigned char *)(adr); \
 		for (x = 0; x < l; x += 16) { \
-			printk("EHCA_DMP:%s " format \
+			printk(KERN_INFO "EHCA_DMP:%s " format \
 			       " adr=%p ofs=%04x %016lx %016lx\n", \
 			       __FUNCTION__, ##args, deb, x, \
 			       *((u64 *)&deb[0]), *((u64 *)&deb[8])); \
@@ -128,16 +128,16 @@ extern int ehca_debug_level;
 	} while (0)
 
 /* define a bitmask, little endian version */
-#define EHCA_BMASK(pos,length) (((pos)<<16)+(length))
+#define EHCA_BMASK(pos, length) (((pos) << 16) + (length))
 
 /* define a bitmask, the ibm way... */
-#define EHCA_BMASK_IBM(from,to) (((63-to)<<16)+((to)-(from)+1))
+#define EHCA_BMASK_IBM(from, to) (((63 - to) << 16) + ((to) - (from) + 1))
 
 /* internal function, don't use */
-#define EHCA_BMASK_SHIFTPOS(mask) (((mask)>>16)&0xffff)
+#define EHCA_BMASK_SHIFTPOS(mask) (((mask) >> 16) & 0xffff)
 
 /* internal function, don't use */
-#define EHCA_BMASK_MASK(mask) (0xffffffffffffffffULL >> ((64-(mask))&0xffff))
+#define EHCA_BMASK_MASK(mask) (~0ULL >> ((64 - (mask)) & 0xffff))
 
 /**
  * EHCA_BMASK_SET - return value shifted and masked by mask
@@ -145,14 +145,14 @@ extern int ehca_debug_level;
  * variable&=~EHCA_BMASK_SET(MY_MASK,-1) clears the bits from the mask
  * in variable
  */
-#define EHCA_BMASK_SET(mask,value) \
-	((EHCA_BMASK_MASK(mask) & ((u64)(value)))<<EHCA_BMASK_SHIFTPOS(mask))
+#define EHCA_BMASK_SET(mask, value) \
+	((EHCA_BMASK_MASK(mask) & ((u64)(value))) << EHCA_BMASK_SHIFTPOS(mask))
 
 /**
  * EHCA_BMASK_GET - extract a parameter from value by mask
  */
-#define EHCA_BMASK_GET(mask,value) \
-	(EHCA_BMASK_MASK(mask)& (((u64)(value))>>EHCA_BMASK_SHIFTPOS(mask)))
+#define EHCA_BMASK_GET(mask, value) \
+	(EHCA_BMASK_MASK(mask) & (((u64)(value)) >> EHCA_BMASK_SHIFTPOS(mask)))
 
 
 /* Converts ehca to ib return code */
diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c b/drivers/infiniband/hw/ehca/ehca_uverbs.c
index 3031b3b..05c4157 100644
--- a/drivers/infiniband/hw/ehca/ehca_uverbs.c
+++ b/drivers/infiniband/hw/ehca/ehca_uverbs.c
@@ -70,7 +70,7 @@ int ehca_dealloc_ucontext(struct ib_ucontext *context)
 
 static void ehca_mm_open(struct vm_area_struct *vma)
 {
-	u32 *count = (u32*)vma->vm_private_data;
+	u32 *count = (u32 *)vma->vm_private_data;
 	if (!count) {
 		ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx",
 			     vma->vm_start, vma->vm_end);
@@ -86,7 +86,7 @@ static void ehca_mm_open(struct vm_area_struct *vma)
 
 static void ehca_mm_close(struct vm_area_struct *vma)
 {
-	u32 *count = (u32*)vma->vm_private_data;
+	u32 *count = (u32 *)vma->vm_private_data;
 	if (!count) {
 		ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx",
 			     vma->vm_start, vma->vm_end);
@@ -215,7 +215,8 @@ static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp,
 	case 2: /* qp rqueue_addr */
 		ehca_dbg(qp->ib_qp.device, "qp_num=%x rqueue",
 			 qp->ib_qp.qp_num);
-		ret = ehca_mmap_queue(vma, &qp->ipz_rqueue, &qp->mm_count_rqueue);
+		ret = ehca_mmap_queue(vma, &qp->ipz_rqueue,
+				      &qp->mm_count_rqueue);
 		if (unlikely(ret)) {
 			ehca_err(qp->ib_qp.device,
 				 "ehca_mmap_queue(rq) failed rc=%x qp_num=%x",
@@ -227,7 +228,8 @@ static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp,
 	case 3: /* qp squeue_addr */
 		ehca_dbg(qp->ib_qp.device, "qp_num=%x squeue",
 			 qp->ib_qp.qp_num);
-		ret = ehca_mmap_queue(vma, &qp->ipz_squeue, &qp->mm_count_squeue);
+		ret = ehca_mmap_queue(vma, &qp->ipz_squeue,
+				      &qp->mm_count_squeue);
 		if (unlikely(ret)) {
 			ehca_err(qp->ib_qp.device,
 				 "ehca_mmap_queue(sq) failed rc=%x qp_num=%x",
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
index 4776a8b..3394e05 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -501,8 +501,8 @@ u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
 		return H_PARAMETER;
 	}
 
-	return hipz_h_register_rpage(adapter_handle,pagesize,queue_type,
-				     qp_handle.handle,logical_address_of_page,
+	return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
+				     qp_handle.handle, logical_address_of_page,
 				     count);
 }
 
@@ -522,9 +522,9 @@ u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
 				qp_handle.handle,	   /* r6 */
 				0, 0, 0, 0, 0, 0);
 	if (log_addr_next_sq_wqe2processed)
-		*log_addr_next_sq_wqe2processed = (void*)outs[0];
+		*log_addr_next_sq_wqe2processed = (void *)outs[0];
 	if (log_addr_next_rq_wqe2processed)
-		*log_addr_next_rq_wqe2processed = (void*)outs[1];
+		*log_addr_next_rq_wqe2processed = (void *)outs[1];
 
 	return ret;
 }
diff --git a/drivers/infiniband/hw/ehca/hcp_phyp.c b/drivers/infiniband/hw/ehca/hcp_phyp.c
index 0b1a477..069c69e 100644
--- a/drivers/infiniband/hw/ehca/hcp_phyp.c
+++ b/drivers/infiniband/hw/ehca/hcp_phyp.c
@@ -50,7 +50,7 @@ int hcall_map_page(u64 physaddr, u64 *mapaddr)
 
 int hcall_unmap_page(u64 mapaddr)
 {
-	iounmap((volatile void __iomem*)mapaddr);
+	iounmap((volatile void __iomem *)mapaddr);
 	return 0;
 }
 
diff --git a/drivers/infiniband/hw/ehca/hipz_fns_core.h b/drivers/infiniband/hw/ehca/hipz_fns_core.h
index 20898a1..868735f 100644
--- a/drivers/infiniband/hw/ehca/hipz_fns_core.h
+++ b/drivers/infiniband/hw/ehca/hipz_fns_core.h
@@ -53,10 +53,10 @@
 #define hipz_galpa_load_cq(gal, offset) \
 	hipz_galpa_load(gal, CQTEMM_OFFSET(offset))
 
-#define hipz_galpa_store_qp(gal,offset, value) \
+#define hipz_galpa_store_qp(gal, offset, value) \
 	hipz_galpa_store(gal, QPTEMM_OFFSET(offset), value)
 #define hipz_galpa_load_qp(gal, offset) \
-	hipz_galpa_load(gal,QPTEMM_OFFSET(offset))
+	hipz_galpa_load(gal, QPTEMM_OFFSET(offset))
 
 static inline void hipz_update_sqa(struct ehca_qp *qp, u16 nr_wqes)
 {
diff --git a/drivers/infiniband/hw/ehca/hipz_hw.h b/drivers/infiniband/hw/ehca/hipz_hw.h
index dad6dea..d9739e5 100644
--- a/drivers/infiniband/hw/ehca/hipz_hw.h
+++ b/drivers/infiniband/hw/ehca/hipz_hw.h
@@ -161,11 +161,11 @@ struct hipz_qptemm {
 /* 0x1000      */
 };
 
-#define QPX_SQADDER EHCA_BMASK_IBM(48,63)
-#define QPX_RQADDER EHCA_BMASK_IBM(48,63)
-#define QPX_AAELOG_RESET_SRQ_LIMIT EHCA_BMASK_IBM(3,3)
+#define QPX_SQADDER EHCA_BMASK_IBM(48, 63)
+#define QPX_RQADDER EHCA_BMASK_IBM(48, 63)
+#define QPX_AAELOG_RESET_SRQ_LIMIT EHCA_BMASK_IBM(3, 3)
 
-#define QPTEMM_OFFSET(x) offsetof(struct hipz_qptemm,x)
+#define QPTEMM_OFFSET(x) offsetof(struct hipz_qptemm, x)
 
 /* MRMWPT Entry Memory Map */
 struct hipz_mrmwmm {
@@ -187,7 +187,7 @@ struct hipz_mrmwmm {
 
 };
 
-#define MRMWMM_OFFSET(x) offsetof(struct hipz_mrmwmm,x)
+#define MRMWMM_OFFSET(x) offsetof(struct hipz_mrmwmm, x)
 
 struct hipz_qpedmm {
 	/* 0x00 */
@@ -238,7 +238,7 @@ struct hipz_qpedmm {
 	u64 qpedx_rrva3;
 };
 
-#define QPEDMM_OFFSET(x) offsetof(struct hipz_qpedmm,x)
+#define QPEDMM_OFFSET(x) offsetof(struct hipz_qpedmm, x)
 
 /* CQ Table Entry Memory Map */
 struct hipz_cqtemm {
@@ -263,12 +263,12 @@ struct hipz_cqtemm {
 /* 0x1000 */
 };
 
-#define CQX_FEC_CQE_CNT           EHCA_BMASK_IBM(32,63)
-#define CQX_FECADDER              EHCA_BMASK_IBM(32,63)
-#define CQX_N0_GENERATE_SOLICITED_COMP_EVENT EHCA_BMASK_IBM(0,0)
-#define CQX_N1_GENERATE_COMP_EVENT EHCA_BMASK_IBM(0,0)
+#define CQX_FEC_CQE_CNT           EHCA_BMASK_IBM(32, 63)
+#define CQX_FECADDER              EHCA_BMASK_IBM(32, 63)
+#define CQX_N0_GENERATE_SOLICITED_COMP_EVENT EHCA_BMASK_IBM(0, 0)
+#define CQX_N1_GENERATE_COMP_EVENT EHCA_BMASK_IBM(0, 0)
 
-#define CQTEMM_OFFSET(x) offsetof(struct hipz_cqtemm,x)
+#define CQTEMM_OFFSET(x) offsetof(struct hipz_cqtemm, x)
 
 /* EQ Table Entry Memory Map */
 struct hipz_eqtemm {
@@ -293,7 +293,7 @@ struct hipz_eqtemm {
 
 };
 
-#define EQTEMM_OFFSET(x) offsetof(struct hipz_eqtemm,x)
+#define EQTEMM_OFFSET(x) offsetof(struct hipz_eqtemm, x)
 
 /* access control defines for MR/MW */
 #define HIPZ_ACCESSCTRL_L_WRITE  0x00800000
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.c b/drivers/infiniband/hw/ehca/ipz_pt_fn.c
index bf7a400..9606f13 100644
--- a/drivers/infiniband/hw/ehca/ipz_pt_fn.c
+++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.c
@@ -114,7 +114,7 @@ int ipz_queue_ctor(struct ipz_queue *queue,
 	 */
 	f = 0;
 	while (f < nr_of_pages) {
-		u8 *kpage = (u8*)get_zeroed_page(GFP_KERNEL);
+		u8 *kpage = (u8 *)get_zeroed_page(GFP_KERNEL);
 		int k;
 		if (!kpage)
 			goto ipz_queue_ctor_exit0; /*NOMEM*/
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.h b/drivers/infiniband/hw/ehca/ipz_pt_fn.h
index 007f088..39a4f64 100644
--- a/drivers/infiniband/hw/ehca/ipz_pt_fn.h
+++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.h
@@ -240,7 +240,7 @@ void *ipz_qeit_eq_get_inc(struct ipz_queue *queue);
 static inline void *ipz_eqit_eq_get_inc_valid(struct ipz_queue *queue)
 {
 	void *ret = ipz_qeit_get(queue);
-	u32 qe = *(u8 *) ret;
+	u32 qe = *(u8 *)ret;
 	if ((qe >> 7) != (queue->toggle_state & 1))
 		return NULL;
 	ipz_qeit_eq_get_inc(queue); /* this is a good one */
@@ -250,7 +250,7 @@ static inline void *ipz_eqit_eq_get_inc_valid(struct ipz_queue *queue)
 static inline void *ipz_eqit_eq_peek_valid(struct ipz_queue *queue)
 {
 	void *ret = ipz_qeit_get(queue);
-	u32 qe = *(u8 *) ret;
+	u32 qe = *(u8 *)ret;
 	if ((qe >> 7) != (queue->toggle_state & 1))
 		return NULL;
 	return ret;
-- 
1.5.2

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 10/10] IB/ehca: Support large page MRs
  2007-07-12 15:45 [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Joachim Fenkes
                   ` (8 preceding siblings ...)
  2007-07-12 15:53 ` [PATCH 09/10] IB/ehca: Fix warnings issued by checkpatch.pl Joachim Fenkes
@ 2007-07-12 15:54 ` Joachim Fenkes
  2007-07-16 17:37   ` Roland Dreier
  2007-07-12 17:15 ` [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Roland Dreier
  10 siblings, 1 reply; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-12 15:54 UTC (permalink / raw)
  To: LinuxPPC-Dev, LKML, OF-General, Roland Dreier
  Cc: Stefan Roscher, Christoph Raisch

From: Hoang-Nam Nguyen <hnguyen@de.ibm.com>

Add support for MR pages larger than 4K on eHCA2. This reduces firmware
memory consumption. If enabled via the mr_largepage module parameter, the MR
page size will be determined based on the MR length and the hardware
capabilities - if the MR is >= 16M, 16M pages are used, for example.

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |   10 +
 drivers/infiniband/hw/ehca/ehca_main.c    |   17 ++-
 drivers/infiniband/hw/ehca/ehca_mrmw.c    |  371 ++++++++++++++++++++++++-----
 drivers/infiniband/hw/ehca/ehca_mrmw.h    |    2 +-
 drivers/infiniband/hw/ehca/hcp_if.c       |   20 ++-
 5 files changed, 357 insertions(+), 63 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 1752821..2a39cfa 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -105,6 +105,12 @@ struct ehca_sport {
 };
 
 #define EHCA_MAX_NR_EQS 512
+
+#define HCA_CAP_MR_PGSIZE_4K  1
+#define HCA_CAP_MR_PGSIZE_64K 2
+#define HCA_CAP_MR_PGSIZE_1M  4
+#define HCA_CAP_MR_PGSIZE_16M 8
+
 struct ehca_shca {
 	struct ib_device ib_device;
 	struct ibmebus_dev *ibmebus_dev;
@@ -121,6 +127,8 @@ struct ehca_shca {
 	struct h_galpas galpas;
 	struct mutex modify_mutex;
 	u64 hca_cap;
+	/* MR pgsize: bit 0-3 means 4K, 64K, 1M, 16M respectively */
+	u32 hca_cap_mr_pgsize;
 	int max_mtu;
 	atomic_t cur_eq_idx;
 };
@@ -213,6 +221,7 @@ struct ehca_mr {
 	enum ehca_mr_flag flags;
 	u32 num_kpages;		/* number of kernel pages */
 	u32 num_hwpages;	/* number of hw pages to form MR */
+	u64 hwpage_size;	/* hw page size used for this MR */
 	int acl;		/* ACL (stored here for usage in reregister) */
 	u64 *start;		/* virtual start address (stored here for */
 				/* usage in reregister) */
@@ -247,6 +256,7 @@ struct ehca_mr_pginfo {
 	enum ehca_mr_pgi_type type;
 	u64 num_kpages;
 	u64 kpage_cnt;
+	u64 hwpage_size;     /* hw page size used for this MR */
 	u64 num_hwpages;     /* number of hw pages */
 	u64 hwpage_cnt;      /* counter for hw pages */
 	u64 next_hwpage;     /* next hw page in buffer/chunk/listelem */
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index ecf4ef4..5f207f2 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -65,6 +65,7 @@ int ehca_static_rate   = -1;
 int ehca_scaling_code  = 0;
 int ehca_nr_eqs        = 2;
 int ehca_dist_eqs      = 0;
+int ehca_mr_largepage  = 0;
 
 module_param_named(open_aqp1,     ehca_open_aqp1,     int, 0);
 module_param_named(debug_level,   ehca_debug_level,   int, 0);
@@ -77,6 +78,7 @@ module_param_named(static_rate,   ehca_static_rate,   int, 0);
 module_param_named(scaling_code,  ehca_scaling_code,  int, 0);
 module_param_named(nr_eqs,        ehca_nr_eqs,        int, 0);
 module_param_named(dist_eqs,      ehca_dist_eqs,      int, 0);
+module_param_named(mr_largepage,  ehca_mr_largepage,  int, 0);
 
 MODULE_PARM_DESC(open_aqp1,
 		 "AQP1 on startup (0: no (default), 1: yes)");
@@ -104,6 +106,9 @@ MODULE_PARM_DESC(nr_eqs,
 MODULE_PARM_DESC(dist_eqs,
 		 "enable distributing EQs across CQs "
 		 "(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");
 
 DEFINE_RWLOCK(ehca_qp_idr_lock);
 DEFINE_RWLOCK(ehca_cq_idr_lock);
@@ -314,6 +319,8 @@ int ehca_sense_attributes(struct ehca_shca *shca)
 		if (EHCA_BMASK_GET(hca_cap_descr[i].mask, shca->hca_cap))
 			ehca_gen_dbg("   %s", hca_cap_descr[i].descr);
 
+	shca->hca_cap_mr_pgsize = rblock->memory_page_size_supported;
+
 	port = (struct hipz_query_port *)rblock;
 	h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port);
 	if (h_ret != H_SUCCESS) {
@@ -609,13 +616,20 @@ 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 ssize_t ehca_show_nr_eqs(struct device *dev,
 				struct device_attribute *attr,
 				char *buf)
 {
 	return sprintf(buf, "%d\n", ehca_nr_eqs);
 }
-
 static DEVICE_ATTR(nr_eqs, S_IRUGO, ehca_show_nr_eqs, NULL);
 
 static struct attribute *ehca_dev_attrs[] = {
@@ -635,6 +649,7 @@ static struct attribute *ehca_dev_attrs[] = {
 	&dev_attr_max_pd.attr,
 	&dev_attr_max_ah.attr,
 	&dev_attr_nr_eqs.attr,
+	&dev_attr_mr_largepage.attr,
 	NULL
 };
 
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index 6262c54..ba28783 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -5,6 +5,7 @@
  *
  *  Authors: Dietmar Decker <ddecker@de.ibm.com>
  *           Christoph Raisch <raisch@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
  *
  *  Copyright (c) 2005 IBM Corporation
  *
@@ -56,6 +57,37 @@
 static struct kmem_cache *mr_cache;
 static struct kmem_cache *mw_cache;
 
+enum ehca_mr_pgsize {
+	EHCA_MR_PGSIZE4K  = 0x1000L,
+	EHCA_MR_PGSIZE64K = 0x10000L,
+	EHCA_MR_PGSIZE1M  = 0x100000L,
+	EHCA_MR_PGSIZE16M = 0x1000000L
+};
+
+extern int ehca_mr_largepage;
+
+static u32 ehca_encode_hwpage_size(u32 pgsize)
+{
+	u32 idx = 0;
+	pgsize >>= 12;
+	/*
+	 * map mr page size into hw code:
+	 * 0, 1, 2, 3 for 4K, 64K, 1M, 64M
+	 */
+	while (!(pgsize & 1)) {
+		idx++;
+		pgsize >>= 4;
+	}
+	return idx;
+}
+
+static u64 ehca_get_max_hwpage_size(struct ehca_shca *shca)
+{
+	if (shca->hca_cap_mr_pgsize & HCA_CAP_MR_PGSIZE_16M)
+		return EHCA_MR_PGSIZE16M;
+	return EHCA_MR_PGSIZE4K;
+}
+
 static struct ehca_mr *ehca_mr_new(void)
 {
 	struct ehca_mr *me;
@@ -207,19 +239,23 @@ struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd,
 		struct ehca_mr_pginfo pginfo;
 		u32 num_kpages;
 		u32 num_hwpages;
+		u64 hw_pgsize;
 
 		num_kpages = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size,
 					PAGE_SIZE);
-		num_hwpages = NUM_CHUNKS(((u64)iova_start % EHCA_PAGESIZE) +
-					 size, EHCA_PAGESIZE);
+		/* for kernel space we try most possible pgsize */
+		hw_pgsize = ehca_get_max_hwpage_size(shca);
+		num_hwpages = NUM_CHUNKS(((u64)iova_start % hw_pgsize) + size,
+					 hw_pgsize);
 		memset(&pginfo, 0, sizeof(pginfo));
 		pginfo.type = EHCA_MR_PGI_PHYS;
 		pginfo.num_kpages = num_kpages;
+		pginfo.hwpage_size = hw_pgsize;
 		pginfo.num_hwpages = num_hwpages;
 		pginfo.u.phy.num_phys_buf = num_phys_buf;
 		pginfo.u.phy.phys_buf_array = phys_buf_array;
-		pginfo.next_hwpage = (((u64)iova_start & ~PAGE_MASK) /
-				      EHCA_PAGESIZE);
+		pginfo.next_hwpage =
+			((u64)iova_start & ~(hw_pgsize - 1)) / hw_pgsize;
 
 		ret = ehca_reg_mr(shca, e_mr, iova_start, size, mr_access_flags,
 				  e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
@@ -259,6 +295,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
 	int ret;
 	u32 num_kpages;
 	u32 num_hwpages;
+	u64 hwpage_size;
 
 	if (!pd) {
 		ehca_gen_err("bad pd=%p", pd);
@@ -309,16 +346,32 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
 
 	/* determine number of MR pages */
 	num_kpages = NUM_CHUNKS((virt % PAGE_SIZE) + length, PAGE_SIZE);
-	num_hwpages = NUM_CHUNKS((virt % EHCA_PAGESIZE) + length,
-				 EHCA_PAGESIZE);
+	/* select proper hw_pgsize */
+	if (ehca_mr_largepage &&
+	    (shca->hca_cap_mr_pgsize & HCA_CAP_MR_PGSIZE_16M)) {
+		if (length <= EHCA_MR_PGSIZE4K
+		    && PAGE_SIZE == EHCA_MR_PGSIZE4K)
+			hwpage_size = EHCA_MR_PGSIZE4K;
+		else if (length <= EHCA_MR_PGSIZE64K)
+			hwpage_size = EHCA_MR_PGSIZE64K;
+		else if (length <= EHCA_MR_PGSIZE1M)
+			hwpage_size = EHCA_MR_PGSIZE1M;
+		else
+			hwpage_size = EHCA_MR_PGSIZE16M;
+	} else
+		hwpage_size = EHCA_MR_PGSIZE4K;
+	ehca_dbg(pd->device, "hwpage_size=%lx", hwpage_size);
 
+reg_user_mr_fallback:
+	num_hwpages = NUM_CHUNKS((virt % hwpage_size) + length, hwpage_size);
 	/* register MR on HCA */
 	memset(&pginfo, 0, sizeof(pginfo));
 	pginfo.type = EHCA_MR_PGI_USER;
+	pginfo.hwpage_size = hwpage_size;
 	pginfo.num_kpages = num_kpages;
 	pginfo.num_hwpages = num_hwpages;
 	pginfo.u.usr.region = e_mr->umem;
-	pginfo.next_hwpage = e_mr->umem->offset / EHCA_PAGESIZE;
+	pginfo.next_hwpage = e_mr->umem->offset / hwpage_size;
 	pginfo.u.usr.next_chunk = list_prepare_entry(pginfo.u.usr.next_chunk,
 						     (&e_mr->umem->chunk_list),
 						     list);
@@ -326,6 +379,18 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
 	ret = ehca_reg_mr(shca, e_mr, (u64 *)virt, length, mr_access_flags,
 			  e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
 			  &e_mr->ib.ib_mr.rkey);
+	if (ret == -EINVAL && pginfo.hwpage_size > PAGE_SIZE) {
+		ehca_warn(pd->device, "failed to register mr "
+			  "with hwpage_size=%lx", hwpage_size);
+		ehca_info(pd->device, "try to register mr with "
+			  "kpage_size=%lx", PAGE_SIZE);
+		/*
+		 * this means kpages are not contiguous for a hw page
+		 * try kernel page size as fallback solution
+		 */
+		hwpage_size = PAGE_SIZE;
+		goto reg_user_mr_fallback;
+	}
 	if (ret) {
 		ib_mr = ERR_PTR(ret);
 		goto reg_user_mr_exit2;
@@ -452,6 +517,8 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
 	new_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
 
 	if (mr_rereg_mask & IB_MR_REREG_TRANS) {
+		u64 hw_pgsize = ehca_get_max_hwpage_size(shca);
+
 		new_start = iova_start;	/* change address */
 		/* check physical buffer list and calculate size */
 		ret = ehca_mr_chk_buf_and_calc_size(phys_buf_array,
@@ -468,16 +535,17 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
 		}
 		num_kpages = NUM_CHUNKS(((u64)new_start % PAGE_SIZE) +
 					new_size, PAGE_SIZE);
-		num_hwpages = NUM_CHUNKS(((u64)new_start % EHCA_PAGESIZE) +
-					 new_size, EHCA_PAGESIZE);
+		num_hwpages = NUM_CHUNKS(((u64)new_start % hw_pgsize) +
+					 new_size, hw_pgsize);
 		memset(&pginfo, 0, sizeof(pginfo));
 		pginfo.type = EHCA_MR_PGI_PHYS;
 		pginfo.num_kpages = num_kpages;
+		pginfo.hwpage_size = hw_pgsize;
 		pginfo.num_hwpages = num_hwpages;
 		pginfo.u.phy.num_phys_buf = num_phys_buf;
 		pginfo.u.phy.phys_buf_array = phys_buf_array;
-		pginfo.next_hwpage = (((u64)iova_start & ~PAGE_MASK) /
-				      EHCA_PAGESIZE);
+		pginfo.next_hwpage =
+			((u64)iova_start & ~(hw_pgsize - 1)) / hw_pgsize;
 	}
 	if (mr_rereg_mask & IB_MR_REREG_ACCESS)
 		new_acl = mr_access_flags;
@@ -709,6 +777,7 @@ struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd,
 	int ret;
 	u32 tmp_lkey, tmp_rkey;
 	struct ehca_mr_pginfo pginfo;
+	u64 hw_pgsize;
 
 	/* check other parameters */
 	if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) &&
@@ -738,8 +807,8 @@ struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd,
 		ib_fmr = ERR_PTR(-EINVAL);
 		goto alloc_fmr_exit0;
 	}
-	if (((1 << fmr_attr->page_shift) != EHCA_PAGESIZE) &&
-	    ((1 << fmr_attr->page_shift) != PAGE_SIZE)) {
+	hw_pgsize = ehca_get_max_hwpage_size(shca);
+	if ((1 << fmr_attr->page_shift) != hw_pgsize) {
 		ehca_err(pd->device, "unsupported fmr_attr->page_shift=%x",
 			 fmr_attr->page_shift);
 		ib_fmr = ERR_PTR(-EINVAL);
@@ -755,6 +824,10 @@ struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd,
 
 	/* register MR on HCA */
 	memset(&pginfo, 0, sizeof(pginfo));
+	/*
+	 * pginfo.num_hwpages==0, ie register_rpages() will not be called
+	 * but deferred to map_phys_fmr()
+	 */
 	ret = ehca_reg_mr(shca, e_fmr, NULL,
 			  fmr_attr->max_pages * (1 << fmr_attr->page_shift),
 			  mr_access_flags, e_pd, &pginfo,
@@ -765,6 +838,7 @@ struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd,
 	}
 
 	/* successful */
+	e_fmr->hwpage_size = hw_pgsize;
 	e_fmr->fmr_page_size = 1 << fmr_attr->page_shift;
 	e_fmr->fmr_max_pages = fmr_attr->max_pages;
 	e_fmr->fmr_max_maps = fmr_attr->max_maps;
@@ -822,10 +896,12 @@ int ehca_map_phys_fmr(struct ib_fmr *fmr,
 	memset(&pginfo, 0, sizeof(pginfo));
 	pginfo.type = EHCA_MR_PGI_FMR;
 	pginfo.num_kpages = list_len;
-	pginfo.num_hwpages = list_len * (e_fmr->fmr_page_size / EHCA_PAGESIZE);
+	pginfo.hwpage_size = e_fmr->hwpage_size;
+	pginfo.num_hwpages =
+		list_len * e_fmr->fmr_page_size / pginfo.hwpage_size;
 	pginfo.u.fmr.page_list = page_list;
-	pginfo.next_hwpage = ((iova & (e_fmr->fmr_page_size-1)) /
-			      EHCA_PAGESIZE);
+	pginfo.next_hwpage =
+		(iova & (e_fmr->fmr_page_size-1)) / pginfo.hwpage_size;
 	pginfo.u.fmr.fmr_pgsize = e_fmr->fmr_page_size;
 
 	ret = ehca_rereg_mr(shca, e_fmr, (u64 *)iova,
@@ -964,7 +1040,7 @@ int ehca_reg_mr(struct ehca_shca *shca,
 	struct ehca_mr_hipzout_parms hipzout;
 
 	ehca_mrmw_map_acl(acl, &hipz_acl);
-	ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl);
+	ehca_mrmw_set_pgsize_hipz_acl(pginfo->hwpage_size, &hipz_acl);
 	if (ehca_use_hp_mr == 1)
 		hipz_acl |= 0x00000001;
 
@@ -987,6 +1063,7 @@ int ehca_reg_mr(struct ehca_shca *shca,
 	/* successful registration */
 	e_mr->num_kpages = pginfo->num_kpages;
 	e_mr->num_hwpages = pginfo->num_hwpages;
+	e_mr->hwpage_size = pginfo->hwpage_size;
 	e_mr->start = iova_start;
 	e_mr->size = size;
 	e_mr->acl = acl;
@@ -1029,6 +1106,9 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
 	u32 i;
 	u64 *kpage;
 
+	if (!pginfo->num_hwpages) /* in case of fmr */
+		return 0;
+
 	kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!kpage) {
 		ehca_err(&shca->ib_device, "kpage alloc failed");
@@ -1036,7 +1116,7 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
 		goto ehca_reg_mr_rpages_exit0;
 	}
 
-	/* max 512 pages per shot */
+	/* max MAX_RPAGES ehca mr pages per register call */
 	for (i = 0; i < NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES); i++) {
 
 		if (i == NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES) - 1) {
@@ -1049,8 +1129,8 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
 		ret = ehca_set_pagebuf(pginfo, rnum, kpage);
 		if (ret) {
 			ehca_err(&shca->ib_device, "ehca_set_pagebuf "
-					 "bad rc, ret=%x rnum=%x kpage=%p",
-					 ret, rnum, kpage);
+				 "bad rc, ret=%x rnum=%x kpage=%p",
+				 ret, rnum, kpage);
 			goto ehca_reg_mr_rpages_exit1;
 		}
 
@@ -1065,9 +1145,10 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
 		} else
 			rpage = *kpage;
 
-		h_ret = hipz_h_register_rpage_mr(shca->ipz_hca_handle, e_mr,
-						 0, /* pagesize 4k */
-						 0, rpage, rnum);
+		h_ret = hipz_h_register_rpage_mr(
+			shca->ipz_hca_handle, e_mr,
+			ehca_encode_hwpage_size(pginfo->hwpage_size),
+			0, rpage, rnum);
 
 		if (i == NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES) - 1) {
 			/*
@@ -1131,7 +1212,7 @@ inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca,
 	struct ehca_mr_hipzout_parms hipzout;
 
 	ehca_mrmw_map_acl(acl, &hipz_acl);
-	ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl);
+	ehca_mrmw_set_pgsize_hipz_acl(pginfo->hwpage_size, &hipz_acl);
 
 	kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
 	if (!kpage) {
@@ -1182,6 +1263,7 @@ inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca,
 		 */
 		e_mr->num_kpages = pginfo->num_kpages;
 		e_mr->num_hwpages = pginfo->num_hwpages;
+		e_mr->hwpage_size = pginfo->hwpage_size;
 		e_mr->start = iova_start;
 		e_mr->size = size;
 		e_mr->acl = acl;
@@ -1268,13 +1350,14 @@ int ehca_rereg_mr(struct ehca_shca *shca,
 
 		/* set some MR values */
 		e_mr->flags = save_mr.flags;
+		e_mr->hwpage_size = save_mr.hwpage_size;
 		e_mr->fmr_page_size = save_mr.fmr_page_size;
 		e_mr->fmr_max_pages = save_mr.fmr_max_pages;
 		e_mr->fmr_max_maps = save_mr.fmr_max_maps;
 		e_mr->fmr_map_cnt = save_mr.fmr_map_cnt;
 
 		ret = ehca_reg_mr(shca, e_mr, iova_start, size, acl,
-				      e_pd, pginfo, lkey, rkey);
+				  e_pd, pginfo, lkey, rkey);
 		if (ret) {
 			u32 offset = (u64)(&e_mr->flags) - (u64)e_mr;
 			memcpy(&e_mr->flags, &(save_mr.flags),
@@ -1355,6 +1438,7 @@ int ehca_unmap_one_fmr(struct ehca_shca *shca,
 
 	/* set some MR values */
 	e_fmr->flags = save_fmr.flags;
+	e_fmr->hwpage_size = save_fmr.hwpage_size;
 	e_fmr->fmr_page_size = save_fmr.fmr_page_size;
 	e_fmr->fmr_max_pages = save_fmr.fmr_max_pages;
 	e_fmr->fmr_max_maps = save_fmr.fmr_max_maps;
@@ -1363,8 +1447,6 @@ int ehca_unmap_one_fmr(struct ehca_shca *shca,
 
 	memset(&pginfo, 0, sizeof(pginfo));
 	pginfo.type = EHCA_MR_PGI_FMR;
-	pginfo.num_kpages = 0;
-	pginfo.num_hwpages = 0;
 	ret = ehca_reg_mr(shca, e_fmr, NULL,
 			  (e_fmr->fmr_max_pages * e_fmr->fmr_page_size),
 			  e_fmr->acl, e_pd, &pginfo, &tmp_lkey,
@@ -1373,7 +1455,6 @@ int ehca_unmap_one_fmr(struct ehca_shca *shca,
 		u32 offset = (u64)(&e_fmr->flags) - (u64)e_fmr;
 		memcpy(&e_fmr->flags, &(save_mr.flags),
 		       sizeof(struct ehca_mr) - offset);
-		goto ehca_unmap_one_fmr_exit0;
 	}
 
 ehca_unmap_one_fmr_exit0:
@@ -1401,7 +1482,7 @@ int ehca_reg_smr(struct ehca_shca *shca,
 	struct ehca_mr_hipzout_parms hipzout;
 
 	ehca_mrmw_map_acl(acl, &hipz_acl);
-	ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl);
+	ehca_mrmw_set_pgsize_hipz_acl(e_origmr->hwpage_size, &hipz_acl);
 
 	h_ret = hipz_h_register_smr(shca->ipz_hca_handle, e_newmr, e_origmr,
 				    (u64)iova_start, hipz_acl, e_pd->fw_pd,
@@ -1420,6 +1501,7 @@ int ehca_reg_smr(struct ehca_shca *shca,
 	/* successful registration */
 	e_newmr->num_kpages = e_origmr->num_kpages;
 	e_newmr->num_hwpages = e_origmr->num_hwpages;
+	e_newmr->hwpage_size   = e_origmr->hwpage_size;
 	e_newmr->start = iova_start;
 	e_newmr->size = e_origmr->size;
 	e_newmr->acl = acl;
@@ -1452,6 +1534,7 @@ int ehca_reg_internal_maxmr(
 	struct ib_phys_buf ib_pbuf;
 	u32 num_kpages;
 	u32 num_hwpages;
+	u64 hw_pgsize;
 
 	e_mr = ehca_mr_new();
 	if (!e_mr) {
@@ -1468,13 +1551,15 @@ int ehca_reg_internal_maxmr(
 	ib_pbuf.size = size_maxmr;
 	num_kpages = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size_maxmr,
 				PAGE_SIZE);
-	num_hwpages = NUM_CHUNKS(((u64)iova_start % EHCA_PAGESIZE) + size_maxmr,
-				 EHCA_PAGESIZE);
+	hw_pgsize = ehca_get_max_hwpage_size(shca);
+	num_hwpages = NUM_CHUNKS(((u64)iova_start % hw_pgsize) + size_maxmr,
+				 hw_pgsize);
 
 	memset(&pginfo, 0, sizeof(pginfo));
 	pginfo.type = EHCA_MR_PGI_PHYS;
 	pginfo.num_kpages = num_kpages;
 	pginfo.num_hwpages = num_hwpages;
+	pginfo.hwpage_size = hw_pgsize;
 	pginfo.u.phy.num_phys_buf = 1;
 	pginfo.u.phy.phys_buf_array = &ib_pbuf;
 
@@ -1523,7 +1608,7 @@ int ehca_reg_maxmr(struct ehca_shca *shca,
 	struct ehca_mr_hipzout_parms hipzout;
 
 	ehca_mrmw_map_acl(acl, &hipz_acl);
-	ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl);
+	ehca_mrmw_set_pgsize_hipz_acl(e_origmr->hwpage_size, &hipz_acl);
 
 	h_ret = hipz_h_register_smr(shca->ipz_hca_handle, e_newmr, e_origmr,
 				    (u64)iova_start, hipz_acl, e_pd->fw_pd,
@@ -1539,6 +1624,7 @@ int ehca_reg_maxmr(struct ehca_shca *shca,
 	/* successful registration */
 	e_newmr->num_kpages = e_origmr->num_kpages;
 	e_newmr->num_hwpages = e_origmr->num_hwpages;
+	e_newmr->hwpage_size = e_origmr->hwpage_size;
 	e_newmr->start = iova_start;
 	e_newmr->size = e_origmr->size;
 	e_newmr->acl = acl;
@@ -1684,6 +1770,7 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
 	u64 pgaddr;
 	u32 i = 0;
 	u32 j = 0;
+	int hwpages_per_kpage = PAGE_SIZE / pginfo->hwpage_size;
 
 	/* loop over desired chunk entries */
 	chunk      = pginfo->u.usr.next_chunk;
@@ -1695,7 +1782,7 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
 				<< PAGE_SHIFT ;
 			*kpage = phys_to_abs(pgaddr +
 					     (pginfo->next_hwpage *
-					      EHCA_PAGESIZE));
+					      pginfo->hwpage_size));
 			if ( !(*kpage) ) {
 				ehca_gen_err("pgaddr=%lx "
 					     "chunk->page_list[i]=%lx "
@@ -1708,8 +1795,7 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
 			(pginfo->hwpage_cnt)++;
 			(pginfo->next_hwpage)++;
 			kpage++;
-			if (pginfo->next_hwpage %
-			    (PAGE_SIZE / EHCA_PAGESIZE) == 0) {
+			if (pginfo->next_hwpage % hwpages_per_kpage == 0) {
 				(pginfo->kpage_cnt)++;
 				(pginfo->u.usr.next_nmap)++;
 				pginfo->next_hwpage = 0;
@@ -1738,6 +1824,143 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
 	return ret;
 }
 
+/*
+ * check given pages for contiguous layout
+ * last page addr is returned in prev_pgaddr for further check
+ */
+static int ehca_check_kpages_per_ate(struct scatterlist *page_list,
+				     int start_idx, int end_idx,
+				     u64 *prev_pgaddr)
+{
+	int t;
+	for (t = start_idx; t <= end_idx; t++) {
+		u64 pgaddr = page_to_pfn(page_list[t].page) << PAGE_SHIFT;
+		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",
+				     pgaddr, *prev_pgaddr, t);
+			return -EINVAL;
+		}
+		*prev_pgaddr = pgaddr;
+	}
+	return 0;
+}
+
+/* PAGE_SIZE < pginfo->hwpage_size */
+static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
+				  u32 number,
+				  u64 *kpage)
+{
+	int ret = 0;
+	struct ib_umem_chunk *prev_chunk;
+	struct ib_umem_chunk *chunk;
+	u64 pgaddr, prev_pgaddr;
+	u32 i = 0;
+	u32 j = 0;
+	int kpages_per_hwpage = pginfo->hwpage_size / PAGE_SIZE;
+	int nr_kpages = kpages_per_hwpage;
+
+	/* loop over desired chunk entries */
+	chunk      = pginfo->u.usr.next_chunk;
+	prev_chunk = pginfo->u.usr.next_chunk;
+	list_for_each_entry_continue(
+		chunk, (&(pginfo->u.usr.region->chunk_list)), list) {
+		for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) {
+			if (nr_kpages == kpages_per_hwpage) {
+				pgaddr = ( page_to_pfn(chunk->page_list[i].page)
+					   << PAGE_SHIFT );
+				*kpage = phys_to_abs(pgaddr);
+				if ( !(*kpage) ) {
+					ehca_gen_err("pgaddr=%lx i=%x",
+						     pgaddr, i);
+					ret = -EFAULT;
+					return ret;
+				}
+				/*
+				 * The first page in a hwpage must be aligned;
+				 * the first MR page is exempt from this rule.
+				 */
+				if (pgaddr & (pginfo->hwpage_size - 1)) {
+					if (pginfo->hwpage_cnt) {
+						ehca_gen_err(
+							"invalid alignment "
+							"pgaddr=%lx i=%x "
+							"mr_pgsize=%lx",
+							pgaddr, i,
+							pginfo->hwpage_size);
+						ret = -EFAULT;
+						return ret;
+					}
+					/* first MR page */
+					pginfo->kpage_cnt =
+						(pgaddr &
+						 (pginfo->hwpage_size - 1)) >>
+						PAGE_SHIFT;
+					nr_kpages -= pginfo->kpage_cnt;
+					*kpage = phys_to_abs(
+						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)));
+				prev_pgaddr = pgaddr;
+				i++;
+				pginfo->kpage_cnt++;
+				pginfo->u.usr.next_nmap++;
+				nr_kpages--;
+				if (!nr_kpages)
+					goto next_kpage;
+				continue;
+			}
+			if (i + nr_kpages > chunk->nmap) {
+				ret = ehca_check_kpages_per_ate(
+					chunk->page_list, i,
+					chunk->nmap - 1, &prev_pgaddr);
+				if (ret) return ret;
+				pginfo->kpage_cnt += chunk->nmap - i;
+				pginfo->u.usr.next_nmap += chunk->nmap - i;
+				nr_kpages -= chunk->nmap - i;
+				break;
+			}
+
+			ret = ehca_check_kpages_per_ate(chunk->page_list, i,
+							i + nr_kpages - 1,
+							&prev_pgaddr);
+			if (ret) return ret;
+			i += nr_kpages;
+			pginfo->kpage_cnt += nr_kpages;
+			pginfo->u.usr.next_nmap += nr_kpages;
+next_kpage:
+			nr_kpages = kpages_per_hwpage;
+			(pginfo->hwpage_cnt)++;
+			kpage++;
+			j++;
+			if (j >= number) break;
+		}
+		if ((pginfo->u.usr.next_nmap >= chunk->nmap) &&
+		    (j >= number)) {
+			pginfo->u.usr.next_nmap = 0;
+			prev_chunk = chunk;
+			break;
+		} else if (pginfo->u.usr.next_nmap >= chunk->nmap) {
+			pginfo->u.usr.next_nmap = 0;
+			prev_chunk = chunk;
+		} else if (j >= number)
+			break;
+		else
+			prev_chunk = chunk;
+	}
+	pginfo->u.usr.next_chunk =
+		list_prepare_entry(prev_chunk,
+				   (&(pginfo->u.usr.region->chunk_list)),
+				   list);
+	return ret;
+}
+
 int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
 			  u32 number,
 			  u64 *kpage)
@@ -1750,9 +1973,10 @@ int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
 	/* loop over desired phys_buf_array entries */
 	while (i < number) {
 		pbuf   = pginfo->u.phy.phys_buf_array + pginfo->u.phy.next_buf;
-		num_hw  = NUM_CHUNKS((pbuf->addr % EHCA_PAGESIZE) +
-				     pbuf->size, EHCA_PAGESIZE);
-		offs_hw = (pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE;
+		num_hw  = NUM_CHUNKS((pbuf->addr % pginfo->hwpage_size) +
+				     pbuf->size, pginfo->hwpage_size);
+		offs_hw = (pbuf->addr & ~(pginfo->hwpage_size - 1)) /
+			pginfo->hwpage_size;
 		while (pginfo->next_hwpage < offs_hw + num_hw) {
 			/* sanity check */
 			if ((pginfo->kpage_cnt >= pginfo->num_kpages) ||
@@ -1768,21 +1992,23 @@ int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
 				return -EFAULT;
 			}
 			*kpage = phys_to_abs(
-				(pbuf->addr & EHCA_PAGEMASK)
-				+ (pginfo->next_hwpage * EHCA_PAGESIZE));
+				(pbuf->addr & ~(pginfo->hwpage_size - 1)) +
+				(pginfo->next_hwpage * pginfo->hwpage_size));
 			if ( !(*kpage) && pbuf->addr ) {
-				ehca_gen_err("pbuf->addr=%lx "
-					     "pbuf->size=%lx "
+				ehca_gen_err("pbuf->addr=%lx pbuf->size=%lx "
 					     "next_hwpage=%lx", pbuf->addr,
-					     pbuf->size,
-					     pginfo->next_hwpage);
+					     pbuf->size, pginfo->next_hwpage);
 				return -EFAULT;
 			}
 			(pginfo->hwpage_cnt)++;
 			(pginfo->next_hwpage)++;
-			if (pginfo->next_hwpage %
-			    (PAGE_SIZE / EHCA_PAGESIZE) == 0)
-				(pginfo->kpage_cnt)++;
+			if (PAGE_SIZE >= pginfo->hwpage_size) {
+				if (pginfo->next_hwpage %
+				    (PAGE_SIZE / pginfo->hwpage_size) == 0)
+					(pginfo->kpage_cnt)++;
+			} else
+				pginfo->kpage_cnt += pginfo->hwpage_size /
+					PAGE_SIZE;
 			kpage++;
 			i++;
 			if (i >= number) break;
@@ -1806,8 +2032,8 @@ int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
 	/* loop over desired page_list entries */
 	fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem;
 	for (i = 0; i < number; i++) {
-		*kpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) +
-				     pginfo->next_hwpage * EHCA_PAGESIZE);
+		*kpage = phys_to_abs((*fmrlist & ~(pginfo->hwpage_size - 1)) +
+				     pginfo->next_hwpage * pginfo->hwpage_size);
 		if ( !(*kpage) ) {
 			ehca_gen_err("*fmrlist=%lx fmrlist=%p "
 				     "next_listelem=%lx next_hwpage=%lx",
@@ -1817,15 +2043,38 @@ int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
 			return -EFAULT;
 		}
 		(pginfo->hwpage_cnt)++;
-		(pginfo->next_hwpage)++;
-		kpage++;
-		if (pginfo->next_hwpage %
-		    (pginfo->u.fmr.fmr_pgsize / EHCA_PAGESIZE) == 0) {
-			(pginfo->kpage_cnt)++;
-			(pginfo->u.fmr.next_listelem)++;
-			fmrlist++;
-			pginfo->next_hwpage = 0;
+		if (pginfo->u.fmr.fmr_pgsize >= pginfo->hwpage_size) {
+			if (pginfo->next_hwpage %
+			    (pginfo->u.fmr.fmr_pgsize /
+			     pginfo->hwpage_size) == 0) {
+				(pginfo->kpage_cnt)++;
+				(pginfo->u.fmr.next_listelem)++;
+				fmrlist++;
+				pginfo->next_hwpage = 0;
+			} else
+				(pginfo->next_hwpage)++;
+		} else {
+			unsigned int cnt_per_hwpage = pginfo->hwpage_size /
+				pginfo->u.fmr.fmr_pgsize;
+			unsigned int j;
+			u64 prev = *kpage;
+			/* check if adrs are contiguous */
+			for (j = 1; j < cnt_per_hwpage; j++) {
+				u64 p = phys_to_abs(fmrlist[j] &
+						    ~(pginfo->hwpage_size - 1));
+				if (prev + pginfo->u.fmr.fmr_pgsize != p) {
+					ehca_gen_err("uncontiguous fmr pages "
+						     "found prev=%lx p=%lx "
+						     "idx=%x", prev, p, i + j);
+					return -EINVAL;
+				}
+				prev = p;
+			}
+			pginfo->kpage_cnt += cnt_per_hwpage;
+			pginfo->u.fmr.next_listelem += cnt_per_hwpage;
+			fmrlist += cnt_per_hwpage;
 		}
+		kpage++;
 	}
 	return ret;
 }
@@ -1842,7 +2091,9 @@ int ehca_set_pagebuf(struct ehca_mr_pginfo *pginfo,
 		ret = ehca_set_pagebuf_phys(pginfo, number, kpage);
 		break;
 	case EHCA_MR_PGI_USER:
-		ret = ehca_set_pagebuf_user1(pginfo, number, kpage);
+		ret = PAGE_SIZE >= pginfo->hwpage_size ?
+			ehca_set_pagebuf_user1(pginfo, number, kpage) :
+			ehca_set_pagebuf_user2(pginfo, number, kpage);
 		break;
 	case EHCA_MR_PGI_FMR:
 		ret = ehca_set_pagebuf_fmr(pginfo, number, kpage);
@@ -1895,9 +2146,9 @@ void ehca_mrmw_map_acl(int ib_acl,
 /*----------------------------------------------------------------------*/
 
 /* sets page size in hipz access control for MR/MW. */
-void ehca_mrmw_set_pgsize_hipz_acl(u32 *hipz_acl) /*INOUT*/
+void ehca_mrmw_set_pgsize_hipz_acl(u32 pgsize, u32 *hipz_acl) /*INOUT*/
 {
-	return; /* HCA supports only 4k */
+	*hipz_acl |= (ehca_encode_hwpage_size(pgsize) << 24);
 } /* end ehca_mrmw_set_pgsize_hipz_acl() */
 
 /*----------------------------------------------------------------------*/
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.h b/drivers/infiniband/hw/ehca/ehca_mrmw.h
index 24f13fe..bc8f4e3 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.h
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.h
@@ -111,7 +111,7 @@ int ehca_mr_is_maxmr(u64 size,
 void ehca_mrmw_map_acl(int ib_acl,
 		       u32 *hipz_acl);
 
-void ehca_mrmw_set_pgsize_hipz_acl(u32 *hipz_acl);
+void ehca_mrmw_set_pgsize_hipz_acl(u32 pgsize, u32 *hipz_acl);
 
 void ehca_mrmw_reverse_map_acl(const u32 *hipz_acl,
 			       int *ib_acl);
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
index 3394e05..358796c 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -427,7 +427,8 @@ u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
 {
 	return ehca_plpar_hcall_norets(H_REGISTER_RPAGES,
 				       adapter_handle.handle,      /* r4  */
-				       queue_type | pagesize << 8, /* r5  */
+				       (u64)queue_type | ((u64)pagesize) << 8,
+				       /* r5  */
 				       resource_handle,	           /* r6  */
 				       logical_address_of_page,    /* r7  */
 				       count,	                   /* r8  */
@@ -724,6 +725,9 @@ 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 */
@@ -746,8 +750,22 @@ u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
 			     const u64 logical_address_of_page,
 			     const u64 count)
 {
+	extern int ehca_debug_level;
 	u64 ret;
 
+	if (unlikely(ehca_debug_level >= 2)) {
+		if (count > 1) {
+			u64 *kpage;
+			int i;
+			kpage = (u64 *)abs_to_virt(logical_address_of_page);
+			for (i = 0; i < count; i++)
+				ehca_gen_dbg("kpage[%d]=%p",
+					     i, (void *)kpage[i]);
+		} else
+			ehca_gen_dbg("kpage=%p",
+				     (void *)logical_address_of_page);
+	}
+
 	if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
 		ehca_gen_err("logical_address_of_page not on a 4k boundary "
 			     "adapter_handle=%lx mr=%p mr_handle=%lx "
-- 
1.5.2

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes
  2007-07-12 15:45 [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Joachim Fenkes
                   ` (9 preceding siblings ...)
  2007-07-12 15:54 ` [PATCH 10/10] IB/ehca: Support large page MRs Joachim Fenkes
@ 2007-07-12 17:15 ` Roland Dreier
  2007-07-13  8:26   ` Joachim Fenkes
  10 siblings, 1 reply; 28+ messages in thread
From: Roland Dreier @ 2007-07-12 17:15 UTC (permalink / raw)
  To: Joachim Fenkes
  Cc: LKML, LinuxPPC-Dev, Christoph Raisch, OF-General, Stefan Roscher

 > Note that patch 7 will introduce a few lines over 80 chars that will be
 > unindented in patch 8 - I hope that's okay with you.

That's fine -- the 80 column rule is one thing I don't worry about too
much; absurdly long lines are bad, but if a line is, say, 84 chars and
breaking it makes the code uglier, then I just leave the 84 char line.

 > [09/10] fixes a lot of checkpatch.pl warnings

Are these warnings from earlier patches in the series, or problems
that already existed in the code?  If they are coming from other
patches in the series, please just fix the earlier patches before I
merge them.

Thanks,
  Roland

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes
  2007-07-12 17:15 ` [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Roland Dreier
@ 2007-07-13  8:26   ` Joachim Fenkes
  0 siblings, 0 replies; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-13  8:26 UTC (permalink / raw)
  To: Roland Dreier
  Cc: LKML, LinuxPPC-Dev, Christoph Raisch, OF-General, Stefan Roscher

>  > [09/10] fixes a lot of checkpatch.pl warnings
> 
> Are these warnings from earlier patches in the series, or problems
> that already existed in the code?  If they are coming from other
> patches in the series, please just fix the earlier patches before I
> merge them.

Nam did a diff -Nurp empty_dir ehca | checkpatch.pl and fixed all the
existing problems in the code. That's why this is such a big hunk -
we've been doing the pointer-typecast thing wrong for a long time,
for example.

Joachim

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/10] IB/ehca: Support for multiple event queues
  2007-07-12 15:46 ` [PATCH 01/10] IB/ehca: Support for multiple event queues Joachim Fenkes
@ 2007-07-16 16:04   ` Roland Dreier
  2007-07-16 20:34     ` Joachim Fenkes
  2007-07-16 20:37     ` Hoang-Nam Nguyen
  0 siblings, 2 replies; 28+ messages in thread
From: Roland Dreier @ 2007-07-16 16:04 UTC (permalink / raw)
  To: Joachim Fenkes
  Cc: LKML, LinuxPPC-Dev, Christoph Raisch, OF-General, Stefan Roscher

 > The eHCA driver can now handle multiple event queues (read: interrupt
 > sources) instead of one. The number of available EQs is selected via the
 > nr_eqs module parameter.

 > CQs are either assigned to the EQs based on the comp_vector index or, if the
 > dist_eqs module parameter is supplied, using a round-robin scheme.

Do you have any data on how well this round-robin assignment works?
It seems not quite right to me for the driver to advertise nr_eqs
completion vectors, but then if round-robin is turned on to ignore the
consumer's decision about which vector to use.

Maybe if round-robin is turned on you should report 0 as the number of
completion vectors?  Or maybe we should allow well-known values for
the completion vector passed to ib_create_cq to allow consumers to
specify a policy (like round robin) instead of a particular vector?
Maybe the whole interface is broken and we should only be exposing
policies to consumers instead of the specific vector?

I think I would rather hold off on multiple EQs for this merge window
and plan on having something really solid and thought-out for 2.6.24.

 - R.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 04/10] IB/ehca: use common error code mapping instead of specific ones
  2007-07-12 15:49 ` [PATCH 04/10] IB/ehca: use common error code mapping instead of specific ones Joachim Fenkes
@ 2007-07-16 17:14   ` Roland Dreier
  2007-07-16 20:35     ` Joachim Fenkes
  0 siblings, 1 reply; 28+ messages in thread
From: Roland Dreier @ 2007-07-16 17:14 UTC (permalink / raw)
  To: Joachim Fenkes
  Cc: LKML, LinuxPPC-Dev, Christoph Raisch, OF-General, Stefan Roscher

 > @@ -161,8 +161,11 @@ static inline int ehca2ib_return_code(u64 ehca_rc)

applied, but as a further cleanup it seems that ehca2ib_return_code()
should be moved into a .c file and moved out of line -- I think it
would probably shrink the compiled code quite a bit, and as far as I
can see it is never used in the data path where the function call
overhead would matter at all.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 10/10] IB/ehca: Support large page MRs
  2007-07-12 15:54 ` [PATCH 10/10] IB/ehca: Support large page MRs Joachim Fenkes
@ 2007-07-16 17:37   ` Roland Dreier
  2007-07-16 21:11     ` Joachim Fenkes
  0 siblings, 1 reply; 28+ messages in thread
From: Roland Dreier @ 2007-07-16 17:37 UTC (permalink / raw)
  To: Joachim Fenkes
  Cc: LKML, LinuxPPC-Dev, Christoph Raisch, OF-General, Stefan Roscher

 > Add support for MR pages larger than 4K on eHCA2. This reduces firmware
 > memory consumption. If enabled via the mr_largepage module parameter, the MR
 > page size will be determined based on the MR length and the hardware
 > capabilities - if the MR is >= 16M, 16M pages are used, for example.

Why the module parameter?  Is there any reason a user would want to
turn this off?  Or conversely, why is it off by default?

Also this patch seems to depend heavily on the multiple EQ patch,
which I am holding off on now.  So you may want to rebase to my
current tree, which has all the ehca patches except the EQ one.

 >  static ssize_t ehca_show_nr_eqs(struct device *dev,
 >  				struct device_attribute *attr,
 >  				char *buf)
 >  {
 >  	return sprintf(buf, "%d\n", ehca_nr_eqs);
 >  }
 > -
 >  static DEVICE_ATTR(nr_eqs, S_IRUGO, ehca_show_nr_eqs, NULL);

Although trivial, this chunk doesn't really belong in this patch --
just fix it up in the multiple EQ patch (which I haven't merged yet).

 - R.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/10] IB/ehca: Support for multiple event queues
  2007-07-16 16:04   ` Roland Dreier
@ 2007-07-16 20:34     ` Joachim Fenkes
  2007-07-16 20:37     ` Hoang-Nam Nguyen
  1 sibling, 0 replies; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-16 20:34 UTC (permalink / raw)
  To: Roland Dreier
  Cc: LKML, LinuxPPC-Dev, Christoph Raisch, OF-General, Stefan Roscher

Roland Dreier <rdreier@cisco.com> wrote on 16.07.2007 18:04:26:

> It seems not quite right to me for the driver to advertise nr_eqs
> completion vectors, but then if round-robin is turned on to ignore the
> consumer's decision about which vector to use.

The round-robin feature was primarily meant as a debug/evaluation feature; 
it is not supposed to be active by default. ULP programmers can, for 
example, quickly evaluate the performance increase that comp_vectors could 
give them, without changing their code. Without this debug option, the 
comp_vector policy is still up to the ULPs.
 
> Maybe if round-robin is turned on you should report 0 as the number of
> completion vectors?

That sounds like a reasonable idea -- I'll change that right away.

> Maybe the whole interface is broken and we should only be exposing
> policies to consumers instead of the specific vector?

If so, I think the policies should be handled by the IB core code instead 
of being re-invented by each driver. The IB core would then again pass 
actual comp_vector values to the driver.
 
> I think I would rather hold off on multiple EQs for this merge window
> and plan on having something really solid and thought-out for 2.6.24.

It's your call, but the code is there and I don't expect it to change a 
lot later, so it could be used by others to get a first impression of 
what's possible using comp_vectors and to gather some experience with 
them.

Regards,
  Joachim

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 04/10] IB/ehca: use common error code mapping instead of specific ones
  2007-07-16 17:14   ` Roland Dreier
@ 2007-07-16 20:35     ` Joachim Fenkes
  0 siblings, 0 replies; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-16 20:35 UTC (permalink / raw)
  To: Roland Dreier
  Cc: LKML, LinuxPPC-Dev, Christoph Raisch, OF-General, Stefan Roscher

Roland Dreier <rdreier@cisco.com> wrote on 16.07.2007 19:14:03:

> applied, but as a further cleanup it seems that ehca2ib_return_code()
> should be moved into a .c file and moved out of line -- I think it
> would probably shrink the compiled code quite a bit, and as far as I
> can see it is never used in the data path where the function call
> overhead would matter at all.

Sounds reasonable; I'll put it in the next patch series.

Joachim

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/10] IB/ehca: Support for multiple event queues
  2007-07-16 16:04   ` Roland Dreier
  2007-07-16 20:34     ` Joachim Fenkes
@ 2007-07-16 20:37     ` Hoang-Nam Nguyen
  2007-07-17  3:48       ` Roland Dreier
  1 sibling, 1 reply; 28+ messages in thread
From: Hoang-Nam Nguyen @ 2007-07-16 20:37 UTC (permalink / raw)
  To: Roland Dreier
  Cc: Joachim Fenkes, LKML, LinuxPPC-Dev, Christoph Raisch, OF-General,
	Stefan Roscher

Roland Dreier <rdreier@cisco.com> wrote on 16.07.2007 18:04:26:
> Do you have any data on how well this round-robin assignment works?
> It seems not quite right to me for the driver to advertise nr_eqs
> completion vectors, but then if round-robin is turned on to ignore the
> consumer's decision about which vector to use.
No, I've no figures to provide here. The background of this dist_eqs
option is actually to allow us testing across all event queues
without to change the testcases resp consumers to use certain
event queue number. Thus, I should comment it as EXPERIMENTAL?
> Maybe if round-robin is turned on you should report 0 as the number of
> completion vectors?  Or maybe we should allow well-known values for
> the completion vector passed to ib_create_cq to allow consumers to
> specify a policy (like round robin) instead of a particular vector?
> Maybe the whole interface is broken and we should only be exposing
> policies to consumers instead of the specific vector?
Agree in that device driver should not overwrite consumer's policy
of event queue assigment. Since dist_eqs is disabled as default,
there's no issue, isn't it?
Regarding ib_verbs: perhaps we should provide create/destroy_eq()
and let upper level protocols or consumers dictate the assignment
to cq by passing an event queue pointer to create_cq()...
> I think I would rather hold off on multiple EQs for this merge window
> and plan on having something really solid and thought-out for 2.6.24.
Fair enough. However why don't let us gather experience with this
feature now? Should we remove dist_eqs option for more consistency?
Thanks
Nam

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 10/10] IB/ehca: Support large page MRs
  2007-07-16 17:37   ` Roland Dreier
@ 2007-07-16 21:11     ` Joachim Fenkes
  2007-07-17  3:50       ` Roland Dreier
  0 siblings, 1 reply; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-16 21:11 UTC (permalink / raw)
  To: Roland Dreier
  Cc: LKML, LinuxPPC-Dev, Christoph Raisch, OF-General, Stefan Roscher

Roland Dreier <rdreier@cisco.com> wrote on 16.07.2007 19:37:09:

>  > If enabled via the mr_largepage module parameter, 
> 
> Why the module parameter?  Is there any reason a user would want to
> turn this off?  Or conversely, why is it off by default?

We're pretty confident this new feature works, but as with all new and 
possibly experimental features, there are chances it might explode your 
machine when activated. So, like with the scaling code, we want the user 
to make the conscious decision of using this code instead of activating it 
by default.
 
>  >  static ssize_t ehca_show_nr_eqs(struct device *dev,
>  >              struct device_attribute *attr,
>  >              char *buf)
>  >  {
>  >     return sprintf(buf, "%d\n", ehca_nr_eqs);
>  >  }
>  > -
>  >  static DEVICE_ATTR(nr_eqs, S_IRUGO, ehca_show_nr_eqs, NULL);
> 
> Although trivial, this chunk doesn't really belong in this patch --
> just fix it up in the multiple EQ patch (which I haven't merged yet).

Sure thing.

Regards,
  Joachim

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/10] IB/ehca: Support for multiple event queues
  2007-07-16 20:37     ` Hoang-Nam Nguyen
@ 2007-07-17  3:48       ` Roland Dreier
  2007-07-17  4:37         ` Michael S. Tsirkin
  2007-07-17  5:57         ` [ofa-general] " Shirley Ma
  0 siblings, 2 replies; 28+ messages in thread
From: Roland Dreier @ 2007-07-17  3:48 UTC (permalink / raw)
  To: Hoang-Nam Nguyen
  Cc: Joachim Fenkes, LKML, LinuxPPC-Dev, Christoph Raisch, OF-General,
	Stefan Roscher

 > No, I've no figures to provide here. The background of this dist_eqs
 > option is actually to allow us testing across all event queues
 > without to change the testcases resp consumers to use certain
 > event queue number. Thus, I should comment it as EXPERIMENTAL?

Seems like it's just development/testing code that shouldn't escape
into the wild?

 > > I think I would rather hold off on multiple EQs for this merge window
 > > and plan on having something really solid and thought-out for 2.6.24.

 > Fair enough. However why don't let us gather experience with this
 > feature now? Should we remove dist_eqs option for more consistency?

As I said I definitely think the dist_eqs switch doesn't sound like
something we want to expose to people.

With that said I still am not sure about putting the multiple EQs
feature in this release.  All the infrastructure is there to make
experimenting with it fairly painless (just the low-level driver needs
to change), and I still haven't seen much code using the feature or
even any anecdotal information about the performance impact.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 10/10] IB/ehca: Support large page MRs
  2007-07-16 21:11     ` Joachim Fenkes
@ 2007-07-17  3:50       ` Roland Dreier
  2007-07-17  6:29         ` Joachim Fenkes
  0 siblings, 1 reply; 28+ messages in thread
From: Roland Dreier @ 2007-07-17  3:50 UTC (permalink / raw)
  To: Joachim Fenkes
  Cc: LKML, LinuxPPC-Dev, Christoph Raisch, OF-General, Stefan Roscher

 > > Why the module parameter?  Is there any reason a user would want to
 > > turn this off?  Or conversely, why is it off by default?
 > 
 > We're pretty confident this new feature works, but as with all new and 
 > possibly experimental features, there are chances it might explode your 
 > machine when activated. So, like with the scaling code, we want the user 
 > to make the conscious decision of using this code instead of activating it 
 > by default.

OK, I guess.  So can we expect to, say, change the default to turning
it on for 2.6.24 and remove the option entirely (so it's always on) in
2.6.25?

 - R.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/10] IB/ehca: Support for multiple event queues
  2007-07-17  3:48       ` Roland Dreier
@ 2007-07-17  4:37         ` Michael S. Tsirkin
  2007-07-17 17:52           ` Roland Dreier
  2007-07-17  5:57         ` [ofa-general] " Shirley Ma
  1 sibling, 1 reply; 28+ messages in thread
From: Michael S. Tsirkin @ 2007-07-17  4:37 UTC (permalink / raw)
  To: Roland Dreier
  Cc: Joachim Fenkes, LKML, LinuxPPC-Dev, Hoang-Nam Nguyen, OF-General,
	Stefan Roscher

> I still haven't seen much code using the feature or
> even any anecdotal information about the performance impact.

Here's some anecdotal evidence :)
http://lists.openfabrics.org/pipermail/general/2007-May/035758.html

-- 
MST

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [ofa-general] Re: [PATCH 01/10] IB/ehca: Support for multiple event queues
  2007-07-17  3:48       ` Roland Dreier
  2007-07-17  4:37         ` Michael S. Tsirkin
@ 2007-07-17  5:57         ` Shirley Ma
  1 sibling, 0 replies; 28+ messages in thread
From: Shirley Ma @ 2007-07-17  5:57 UTC (permalink / raw)
  To: Roland Dreier
  Cc: Joachim Fenkes, LKML, LinuxPPC-Dev, general-bounces,
	Hoang-Nam Nguyen, OF-General, Stefan Roscher

[-- Attachment #1: Type: text/plain, Size: 364 bytes --]





Hello Roland,

>I still haven't seen much code using the feature or
>even any anecdotal information about the performance impact.

The multiple links performance has been significant improved according to
the prototype IPoIB-UD mode test for eHCA driver esepcially for two links
on the same adapter. I haven't tried mthca (PCI-X and PCI-E) yet.

Thanks
Shirley

[-- Attachment #2: Type: text/html, Size: 446 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 10/10] IB/ehca: Support large page MRs
  2007-07-17  3:50       ` Roland Dreier
@ 2007-07-17  6:29         ` Joachim Fenkes
  0 siblings, 0 replies; 28+ messages in thread
From: Joachim Fenkes @ 2007-07-17  6:29 UTC (permalink / raw)
  To: Roland Dreier
  Cc: LKML, LinuxPPC-Dev, Christoph Raisch, OF-General, Stefan Roscher

Roland Dreier <rdreier@cisco.com> wrote on 17.07.2007 05:50:13:

>  > > Why the module parameter?  Is there any reason a user would want to
>  > > turn this off?  Or conversely, why is it off by default?
>  > 
>  > We're pretty confident this new feature works, but as with all new 
and 
>  > possibly experimental features, there are chances it might explode 
your 
>  > machine when activated. So, like with the scaling code, we want the 
user 
>  > to make the conscious decision of using this code instead of 
activating it 
>  > by default.
> 
> OK, I guess.  So can we expect to, say, change the default to turning
> it on for 2.6.24 and remove the option entirely (so it's always on) in
> 2.6.25?

Deal.

Joachim

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/10] IB/ehca: Support for multiple event queues
  2007-07-17  4:37         ` Michael S. Tsirkin
@ 2007-07-17 17:52           ` Roland Dreier
  2007-07-17 21:32             ` Michael S. Tsirkin
  2007-07-19 15:03             ` Hoang-Nam Nguyen
  0 siblings, 2 replies; 28+ messages in thread
From: Roland Dreier @ 2007-07-17 17:52 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Joachim Fenkes, LKML, LinuxPPC-Dev, Hoang-Nam Nguyen, OF-General,
	Stefan Roscher

 > Here's some anecdotal evidence :)
 > http://lists.openfabrics.org/pipermail/general/2007-May/035758.html

Right, but then we went on to say that we probably want to use
multiple vectors to separate out multiple HCA ports rather than
send/sreceive on the same port.  And the current IPoIB implementation
of having that second CQ seems suboptimal anyway, since it seems to
leave us susceptible to the interrupt overload that NAPI was supposed
to solve.

At a higher level, I'm left wondering why nobody talked about multiple
EQs during the last months of the 2.6.22 process and now all of a
sudden it becomes urgent in the last few days of the 2.6.23 merge
window.  That's not really how I like to merge features....

 - R.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/10] IB/ehca: Support for multiple event queues
  2007-07-17 17:52           ` Roland Dreier
@ 2007-07-17 21:32             ` Michael S. Tsirkin
  2007-07-19 15:03             ` Hoang-Nam Nguyen
  1 sibling, 0 replies; 28+ messages in thread
From: Michael S. Tsirkin @ 2007-07-17 21:32 UTC (permalink / raw)
  To: Roland Dreier
  Cc: Joachim Fenkes, LKML, LinuxPPC-Dev, Hoang-Nam Nguyen, OF-General,
	Michael S. Tsirkin, Stefan Roscher

> Quoting Roland Dreier <rdreier@cisco.com>:
> Subject: Re: [PATCH 01/10] IB/ehca: Support for multiple event queues
> 
>  > Here's some anecdotal evidence :)
>  > http://lists.openfabrics.org/pipermail/general/2007-May/035758.html
> 
> Right, but then we went on to say that we probably want to use
> multiple vectors to separate out multiple HCA ports rather than
> send/sreceive on the same port.  And the current IPoIB implementation
> of having that second CQ seems suboptimal anyway, since it seems to
> leave us susceptible to the interrupt overload that NAPI was supposed
> to solve.

Sure, the ipoib patch is just a proof of concept anyway.
And I'm actually working on merging send/recv CQs now,
to address the livelocks.

> At a higher level, I'm left wondering why nobody talked about multiple
> EQs during the last months of the 2.6.22 process and now all of a
> sudden it becomes urgent in the last few days of the 2.6.23 merge
> window.

I don't see any emergency in merging the IPoIB hack either.

I just hoped that once we merge the core changes people will start
experimenting with multiple vectors. This did not seem to have happened.
Could this be because there's no low level driver support upstream yet?

So I wonder whether merging the mthca patch [that was patch 2 of the series]
in 2.6.23 will finally get the
ball rolling, get people to experiment with multiple vectors
in userspace, and that will hopefully teach us something.

> That's not really how I like to merge features....

If you look just at the mthca patch in isolation,
do you still see a problem?

-- 
MST

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/10] IB/ehca: Support for multiple event queues
  2007-07-17 17:52           ` Roland Dreier
  2007-07-17 21:32             ` Michael S. Tsirkin
@ 2007-07-19 15:03             ` Hoang-Nam Nguyen
  1 sibling, 0 replies; 28+ messages in thread
From: Hoang-Nam Nguyen @ 2007-07-19 15:03 UTC (permalink / raw)
  To: Roland Dreier
  Cc: Joachim Fenkes, LKML, LinuxPPC-Dev, Michael S. Tsirkin,
	OF-General, Stefan Roscher

Roland Dreier <rdreier@cisco.com> wrote on 17.07.2007 19:52:55:
> At a higher level, I'm left wondering why nobody talked about multiple
> EQs during the last months of the 2.6.22 process and now all of a
> sudden it becomes urgent in the last few days of the 2.6.23 merge
> window.  That's not really how I like to merge features....
OK, let keep multiple eqs for next release with a more stable
verbs def.
For the other patch to support MR with large pages we'll resend
it (without deps on multiple eqs patch) to you soon.
Regards
Nam

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2007-07-19 15:04 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-12 15:45 [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Joachim Fenkes
2007-07-12 15:46 ` [PATCH 01/10] IB/ehca: Support for multiple event queues Joachim Fenkes
2007-07-16 16:04   ` Roland Dreier
2007-07-16 20:34     ` Joachim Fenkes
2007-07-16 20:37     ` Hoang-Nam Nguyen
2007-07-17  3:48       ` Roland Dreier
2007-07-17  4:37         ` Michael S. Tsirkin
2007-07-17 17:52           ` Roland Dreier
2007-07-17 21:32             ` Michael S. Tsirkin
2007-07-19 15:03             ` Hoang-Nam Nguyen
2007-07-17  5:57         ` [ofa-general] " Shirley Ma
2007-07-12 15:47 ` [PATCH 02/10] IB/ehca: Fix HW level autodetection Joachim Fenkes
2007-07-12 15:48 ` [PATCH 03/10] IB/ehca: fix memory leak in error path of ehca_get_dma_mr() Joachim Fenkes
2007-07-12 15:49 ` [PATCH 04/10] IB/ehca: use common error code mapping instead of specific ones Joachim Fenkes
2007-07-16 17:14   ` Roland Dreier
2007-07-16 20:35     ` Joachim Fenkes
2007-07-12 15:51 ` [PATCH 05/10] IB/ehca: use #define for "pages per register_rpage" instead of hardcoded value Joachim Fenkes
2007-07-12 15:51 ` [PATCH 06/10] IB/ehca: use macro to calculate number of chunks in a mem block Joachim Fenkes
2007-07-12 15:52 ` [PATCH 07/10] IB/ehca: MR/MW structure refactoring Joachim Fenkes
2007-07-12 15:53 ` [PATCH 08/10] IB/ehca: Restructure ehca_set_pagebuf() Joachim Fenkes
2007-07-12 15:53 ` [PATCH 09/10] IB/ehca: Fix warnings issued by checkpatch.pl Joachim Fenkes
2007-07-12 15:54 ` [PATCH 10/10] IB/ehca: Support large page MRs Joachim Fenkes
2007-07-16 17:37   ` Roland Dreier
2007-07-16 21:11     ` Joachim Fenkes
2007-07-17  3:50       ` Roland Dreier
2007-07-17  6:29         ` Joachim Fenkes
2007-07-12 17:15 ` [PATCH 00/10] IB/ehca: Multiple Event Queues, MR/MW rework, large page MRs, fixes Roland Dreier
2007-07-13  8:26   ` Joachim Fenkes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).