[PATCH] IB/ehca: Fix CQE flags reporting

2009-09-01 Thread Joachim Fenkes
Was reporting CQE flags in the wrong bit positions, causing consumers to
miss incoming immediate data.

Signed-off-by: Joachim Fenkes 
---

Please review and queue for 2.6.32 if you think it's okay. Thanks!
  Joachim

 drivers/infiniband/hw/ehca/ehca_reqs.c |6 +-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c 
b/drivers/infiniband/hw/ehca/ehca_reqs.c
index 5a3d96f..8fd88cd 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -786,7 +786,11 @@ repoll:
wc->slid = cqe->rlid;
wc->dlid_path_bits = cqe->dlid;
wc->src_qp = cqe->remote_qp_number;
-   wc->wc_flags = cqe->w_completion_flags;
+   /*
+* HW has "Immed data present" and "GRH present" in bits 6 and 5.
+* SW defines those in bits 1 and 0, so we can just shift and mask.
+*/
+   wc->wc_flags = (cqe->w_completion_flags >> 5) & 3;
wc->ex.imm_data = cpu_to_be32(cqe->immediate_data);
wc->sl = cqe->service_level;
 
-- 
1.6.0.4




___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [ewg] [PATCH] IB/ehca: Construct MAD redirect replies from request MAD

2009-08-28 Thread Joachim Fenkes
Hal Rosenstock  wrote on 27.08.2009 15:31:40:

> I don't think it should be hard coded. IMO it would be better to default 
to 18
> and somehow able to be adjusted (via a (dynamic) module parameter ?).

I don't see how making this a parameter would benefit any end user, while 
on the other hand it clutters up our parameter list.

Changing RespTimeValue won't influence the IB performance or user-visible 
behavior of our driver in any way, and in fact, all RespTimeValue says is 
"Please use a timeout of one second for all future MADs you send me", only 
there won't be any more MADs in the future because we just redirected the 
client to someone else. So, the RespTimeValue field is a don't care in the 
redirection scenario. Setting it to an arbitrary, but legal value isn't 
much more than a concession towards any broken clients that may be out 
there.

Given that you seem to like the rest of the code and Jason hasn't spoken 
up yet, I think we can have Roland merge this patch. Roland, what do you 
think?

Regards,
  Joachim

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [ewg] [PATCH] IB/ehca: Construct MAD redirect replies from request MAD

2009-08-27 Thread Joachim Fenkes
Hal Rosenstock  wrote on 26.08.2009 17:15:03:

> Thanks for doing this. It looks sane to me. The only issue I recall that 

> appears to be remaining is a better setting of 
ClassPortInfo:RespTimeValue 
> rather than hardcoding. Perhaps using the value from PortInfo is the way 
to go
> (ideally it would be that value from the port to which the the requester 
is 
> being redirected to but that might not be so easy to get from this port.

I don't think that effort will be necessary or even legal. The requestor 
will react to the redirection with another Get(ClassPortInfo) to the 
redirection target, which will reply with its own RespTimeValue, so our 
driver should speak for itself. Since we don't know when our MAD 
processing and sending of the response is going to be scheduled (we're not 
running on real-time constraints here), we play it safe and return 18, 
which amounts to roughly a second. 

Make sense?

Regards
  Joachim
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH] IB/ehca: Construct MAD redirect replies from request MAD

2009-08-26 Thread Joachim Fenkes
The old code used a lot of hardcoded values, which might not be valid in all
environments (especially routed fabrics or partitioned subnets). Copy as
much information as possible from the incoming request to prevent that.

Signed-off-by: Joachim Fenkes 
---

Hal, Jason -- here's the change I promised. Looks okay to you?
Roland -- if Hal and Jason don't object, please queue this up for the next
kernel. Thanks!

Regards,
  Joachim

 drivers/infiniband/hw/ehca/ehca_sqp.c |   47 
 1 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_sqp.c 
b/drivers/infiniband/hw/ehca/ehca_sqp.c
index c568b28..8c1213f 100644
--- a/drivers/infiniband/hw/ehca/ehca_sqp.c
+++ b/drivers/infiniband/hw/ehca/ehca_sqp.c
@@ -125,14 +125,30 @@ struct ib_perf {
u8 data[192];
 } __attribute__ ((packed));
 
+/* TC/SL/FL packed into 32 bits, as in ClassPortInfo */
+struct tcslfl {
+   u32 tc:8;
+   u32 sl:4;
+   u32 fl:20;
+} __attribute__ ((packed));
+
+/* IP Version/TC/FL packed into 32 bits, as in GRH */
+struct vertcfl {
+   u32 ver:4;
+   u32 tc:8;
+   u32 fl:20;
+} __attribute__ ((packed));
 
 static int ehca_process_perf(struct ib_device *ibdev, u8 port_num,
+struct ib_wc *in_wc, struct ib_grh *in_grh,
 struct ib_mad *in_mad, struct ib_mad *out_mad)
 {
struct ib_perf *in_perf = (struct ib_perf *)in_mad;
struct ib_perf *out_perf = (struct ib_perf *)out_mad;
struct ib_class_port_info *poi =
(struct ib_class_port_info *)out_perf->data;
+   struct tcslfl *tcslfl =
+   (struct tcslfl *)&poi->redirect_tcslfl;
struct ehca_shca *shca =
container_of(ibdev, struct ehca_shca, ib_device);
struct ehca_sport *sport = &shca->sport[port_num - 1];
@@ -158,10 +174,29 @@ static int ehca_process_perf(struct ib_device *ibdev, u8 
port_num,
poi->base_version = 1;
poi->class_version = 1;
poi->resp_time_value = 18;
-   poi->redirect_lid = sport->saved_attr.lid;
-   poi->redirect_qp = sport->pma_qp_nr;
+
+   /* copy local routing information from WC where applicable */
+   tcslfl->sl = in_wc->sl;
+   poi->redirect_lid  =
+   sport->saved_attr.lid | in_wc->dlid_path_bits;
+   poi->redirect_qp   = sport->pma_qp_nr;
poi->redirect_qkey = IB_QP1_QKEY;
-   poi->redirect_pkey = IB_DEFAULT_PKEY_FULL;
+
+   ehca_query_pkey(ibdev, port_num, in_wc->pkey_index,
+   &poi->redirect_pkey);
+
+   /* if request was globally routed, copy route info */
+   if (in_grh) {
+   struct vertcfl *vertcfl =
+   (struct vertcfl *)&in_grh->version_tclass_flow;
+   memcpy(poi->redirect_gid, in_grh->dgid.raw,
+  sizeof(poi->redirect_gid));
+   tcslfl->tc= vertcfl->tc;
+   tcslfl->fl= vertcfl->fl;
+   } else
+   /* else only fill in default GID */
+   ehca_query_gid(ibdev, port_num, 0,
+  (union ib_gid *)&poi->redirect_gid);
 
ehca_dbg(ibdev, "ehca_pma_lid=%x ehca_pma_qp=%x",
 sport->saved_attr.lid, sport->pma_qp_nr);
@@ -183,8 +218,7 @@ perf_reply:
 
 int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
 struct ib_wc *in_wc, struct ib_grh *in_grh,
-struct ib_mad *in_mad,
-struct ib_mad *out_mad)
+struct ib_mad *in_mad, struct ib_mad *out_mad)
 {
int ret;
 
@@ -196,7 +230,8 @@ int ehca_process_mad(struct ib_device *ibdev, int 
mad_flags, u8 port_num,
return IB_MAD_RESULT_SUCCESS;
 
ehca_dbg(ibdev, "port_num=%x src_qp=%x", port_num, in_wc->src_qp);
-   ret = ehca_process_perf(ibdev, port_num, in_mad, out_mad);
+   ret = ehca_process_perf(ibdev, port_num, in_wc, in_grh,
+   in_mad, out_mad);
 
return ret;
 }
-- 
1.6.0.4


___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH] IB/ehca: Remove superfluous bitmasks from QP control block

2009-06-03 Thread Joachim Fenkes
All the fields in the control block are nicely right-aligned, so no masking
is necessary.

Signed-off-by: Joachim Fenkes 
---
 drivers/infiniband/hw/ehca/ehca_classes_pSeries.h |   28 -
 drivers/infiniband/hw/ehca/ehca_qp.c  |   18 +++-
 2 files changed, 5 insertions(+), 41 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h 
b/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
index 1798e64..689c357 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
@@ -165,7 +165,6 @@ struct hcp_modify_qp_control_block {
 #define MQPCB_MASK_ALT_P_KEY_IDXEHCA_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_QPEHCA_BMASK_IBM(13, 13)
@@ -176,60 +175,33 @@ struct hcp_modify_qp_control_block {
 #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_CLASSEHCA_BMASK_IBM(25, 25)
-#define MQPCB_TRAFFIC_CLASS EHCA_BMASK_IBM(24, 31)
 #define MQPCB_MASK_HOP_LIMITEHCA_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_IDXEHCA_BMASK_IBM(24, 31)
 #define MQPCB_MASK_FLOW_LABEL   EHCA_BMASK_IBM(28, 28)
-#define MQPCB_FLOW_LABELEHCA_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_ALEHCA_BMASK_IBM(29, 31)
 #define MQPCB_MASK_TIMEOUT_AL   EHCA_BMASK_IBM(34, 34)
-#define MQPCB_TIMEOUT_ALEHCA_BMASK_IBM(27, 31)
 #define MQPCB_MASK_MAX_STATIC_RATE_AL   EHCA_BMASK_IBM(35, 35)
-#define MQPCB_MAX_STATIC_RATE_ALEHCA_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_ALEHCA_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_ALEHCA_BMASK_IBM(41, 41)
-#define MQPCB_SOURCE_GID_IDX_AL EHCA_BMASK_IBM(24, 31)
 #define MQPCB_MASK_FLOW_LABEL_ALEHCA_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

Re: [PATCH] IB/ehca: Change misleading error message

2008-11-26 Thread Joachim Fenkes
Roland Dreier <[EMAIL PROTECTED]> wrote on 26.11.2008 00:13:51:

> That's too bad... I applied this patch but out of curiousity, why
> doesn't the hot-remove/hot-add work?  I would have thought that
> re-registering all of memory after the hot-add would do the right thing.

That's right, but right now, we simply try to register all of memory from 
KERNELBASE to high_memory, which works right until we have memory holes in 
the middle; then the hypervisor will reject our page registrations. Same 
goes for huge (16GB) pages, by the way. We're working on a solution to 
this.

Cheers,
  Joachim
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] IB/ehca: Change misleading error message

2008-11-25 Thread Joachim Fenkes
The error message printed when the eHCA driver prevents memory hotplug is
misleading -- the user might think that hot-removing the lhca, hotplugging
memory, then hot-adding the lhca again will work, but it doesn't.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_main.c |3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index bb02a86..bec7e02 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -994,8 +994,7 @@ static int ehca_mem_notifier(struct notifier_block *nb,
if (printk_timed_ratelimit(&ehca_dmem_warn_time,
   30 * 1000))
ehca_gen_err("DMEM operations are not allowed"
-"as long as an ehca adapter is"
-"attached to the LPAR");
+"in conjunction with eHCA");
return NOTIFY_BAD;
}
}
-- 
1.5.5


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] IB/ehca: Fix locking for shca_list_lock

2008-11-21 Thread Joachim Fenkes
shca_list_lock is taken from softirq context in ehca_poll_eqs, so we need to
lock IRQ safe elsewhere.

Signed-off-by: Michael Ellerman <[EMAIL PROTECTED]>
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---

On Friday 21 November 2008 17:02, Johannes Berg wrote:
> On Fri, 2008-11-21 at 16:37 +0100, Joachim Fenkes wrote:
> 
> > +   u64 flags;
> 
> > -   spin_lock(&shca_list_lock);
> > +   spin_lock_irqsave(&shca_list_lock, flags);
> 
> That's wrong and I think will give a warning on all machines where
> u64 != unsigned long. Might not particularly matter in this case.

Doesn't matter for a ppc64 only driver, but you're right nonetheless. Thanks.
 
> Also, generally it seems wrong to say "fix lockdep failure" when the
> patch really fixes a bug that lockdep happened to find.

Whatever -- changed.

Here's the updated patch.

Regards,
  Joachim


 drivers/infiniband/hw/ehca/ehca_main.c |   17 ++---
 1 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index bb02a86..169aa1a 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -717,6 +717,7 @@ static int __devinit ehca_probe(struct of_device *dev,
const u64 *handle;
struct ib_pd *ibpd;
int ret, i, eq_size;
+   unsigned long flags;
 
handle = of_get_property(dev->node, "ibm,hca-handle", NULL);
if (!handle) {
@@ -830,9 +831,9 @@ static int __devinit ehca_probe(struct of_device *dev,
ehca_err(&shca->ib_device,
 "Cannot create device attributes  ret=%d", ret);
 
-   spin_lock(&shca_list_lock);
+   spin_lock_irqsave(&shca_list_lock, flags);
list_add(&shca->shca_list, &shca_list);
-   spin_unlock(&shca_list_lock);
+   spin_unlock_irqrestore(&shca_list_lock, flags);
 
return 0;
 
@@ -878,6 +879,7 @@ probe1:
 static int __devexit ehca_remove(struct of_device *dev)
 {
struct ehca_shca *shca = dev->dev.driver_data;
+   unsigned long flags;
int ret;
 
sysfs_remove_group(&dev->dev.kobj, &ehca_dev_attr_grp);
@@ -915,9 +917,9 @@ static int __devexit ehca_remove(struct of_device *dev)
 
ib_dealloc_device(&shca->ib_device);
 
-   spin_lock(&shca_list_lock);
+   spin_lock_irqsave(&shca_list_lock, flags);
list_del(&shca->shca_list);
-   spin_unlock(&shca_list_lock);
+   spin_unlock_irqrestore(&shca_list_lock, flags);
 
return ret;
 }
@@ -975,6 +977,7 @@ static int ehca_mem_notifier(struct notifier_block *nb,
 unsigned long action, void *data)
 {
static unsigned long ehca_dmem_warn_time;
+   unsigned long flags;
 
switch (action) {
case MEM_CANCEL_OFFLINE:
@@ -985,12 +988,12 @@ static int ehca_mem_notifier(struct notifier_block *nb,
case MEM_GOING_ONLINE:
case MEM_GOING_OFFLINE:
/* only ok if no hca is attached to the lpar */
-   spin_lock(&shca_list_lock);
+   spin_lock_irqsave(&shca_list_lock, flags);
if (list_empty(&shca_list)) {
-   spin_unlock(&shca_list_lock);
+   spin_unlock_irqrestore(&shca_list_lock, flags);
return NOTIFY_OK;
} else {
-   spin_unlock(&shca_list_lock);
+   spin_unlock_irqrestore(&shca_list_lock, flags);
if (printk_timed_ratelimit(&ehca_dmem_warn_time,
   30 * 1000))
ehca_gen_err("DMEM operations are not allowed"
-- 
1.5.5



___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] IB/ehca: Fix lockdep failures for shca_list_lock

2008-11-21 Thread Joachim Fenkes
From: Michael Ellerman <[EMAIL PROTECTED]>

shca_list_lock is taken from softirq context in ehca_poll_eqs, so we need to
lock IRQ safe elsewhere.

Signed-off-by: Michael Ellerman <[EMAIL PROTECTED]>
Acked-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_main.c |   17 ++---
 1 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index bb02a86..021c454 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -717,6 +717,7 @@ static int __devinit ehca_probe(struct of_device *dev,
const u64 *handle;
struct ib_pd *ibpd;
int ret, i, eq_size;
+   u64 flags;
 
handle = of_get_property(dev->node, "ibm,hca-handle", NULL);
if (!handle) {
@@ -830,9 +831,9 @@ static int __devinit ehca_probe(struct of_device *dev,
ehca_err(&shca->ib_device,
 "Cannot create device attributes  ret=%d", ret);
 
-   spin_lock(&shca_list_lock);
+   spin_lock_irqsave(&shca_list_lock, flags);
list_add(&shca->shca_list, &shca_list);
-   spin_unlock(&shca_list_lock);
+   spin_unlock_irqrestore(&shca_list_lock, flags);
 
return 0;
 
@@ -878,6 +879,7 @@ probe1:
 static int __devexit ehca_remove(struct of_device *dev)
 {
struct ehca_shca *shca = dev->dev.driver_data;
+   u64 flags;
int ret;
 
sysfs_remove_group(&dev->dev.kobj, &ehca_dev_attr_grp);
@@ -915,9 +917,9 @@ static int __devexit ehca_remove(struct of_device *dev)
 
ib_dealloc_device(&shca->ib_device);
 
-   spin_lock(&shca_list_lock);
+   spin_lock_irqsave(&shca_list_lock, flags);
list_del(&shca->shca_list);
-   spin_unlock(&shca_list_lock);
+   spin_unlock_irqrestore(&shca_list_lock, flags);
 
return ret;
 }
@@ -975,6 +977,7 @@ static int ehca_mem_notifier(struct notifier_block *nb,
 unsigned long action, void *data)
 {
static unsigned long ehca_dmem_warn_time;
+   unsigned long flags;
 
switch (action) {
case MEM_CANCEL_OFFLINE:
@@ -985,12 +988,12 @@ static int ehca_mem_notifier(struct notifier_block *nb,
case MEM_GOING_ONLINE:
case MEM_GOING_OFFLINE:
/* only ok if no hca is attached to the lpar */
-   spin_lock(&shca_list_lock);
+   spin_lock_irqsave(&shca_list_lock, flags);
if (list_empty(&shca_list)) {
-   spin_unlock(&shca_list_lock);
+   spin_unlock_irqrestore(&shca_list_lock, flags);
return NOTIFY_OK;
} else {
-   spin_unlock(&shca_list_lock);
+   spin_unlock_irqrestore(&shca_list_lock, flags);
if (printk_timed_ratelimit(&ehca_dmem_warn_time,
   30 * 1000))
ehca_gen_err("DMEM operations are not allowed"
-- 
1.5.5



___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH] IB/ehca: Fix suppression of port activation events

2008-11-11 Thread Joachim Fenkes
Roland Dreier <[EMAIL PROTECTED]> wrote on 10.11.2008 21:36:23:

>  > A previous fix introduced a regression where port activation events 
were
>  > dropped unconditionally if port autodetection was not enabled. Fixed.
> 
> Is this a fix to "IB/ehca: Remove reference to special QP in case of
> port activation failure"?  Because if so I can roll it into that patch,
> since Linus hasn't pulled it yet.

Yes, that would be splendid, thank you!

Cheers,
  Joachim
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] IB/ehca: Fix suppression of port activation events

2008-11-07 Thread Joachim Fenkes
A previous fix introduced a regression where port activation events were
dropped unconditionally if port autodetection was not enabled. Fixed.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---

Roland -- this patch is made against your for-linus branch. Please review
and apply if you think it's okay. Hope it's not too late for the next kernel.

Joachim

 drivers/infiniband/hw/ehca/ehca_irq.c |   45 +++-
 1 files changed, 27 insertions(+), 18 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c 
b/drivers/infiniband/hw/ehca/ehca_irq.c
index 9e43459..757035e 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -359,34 +359,43 @@ static void notify_port_conf_change(struct ehca_shca 
*shca, int port_num)
*old_attr = new_attr;
 }
 
+/* replay modify_qp for sqps -- return 0 if all is well, 1 if AQP1 destroyed */
+static int replay_modify_qp(struct ehca_sport *sport)
+{
+   int aqp1_destroyed;
+   unsigned long flags;
+
+   spin_lock_irqsave(&sport->mod_sqp_lock, flags);
+
+   aqp1_destroyed = !sport->ibqp_sqp[IB_QPT_GSI];
+
+   if (sport->ibqp_sqp[IB_QPT_SMI])
+   ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]);
+   if (!aqp1_destroyed)
+   ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]);
+
+   spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
+
+   return aqp1_destroyed;
+}
+
 static void parse_ec(struct ehca_shca *shca, u64 eqe)
 {
u8 ec   = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe);
u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe);
u8 spec_event;
struct ehca_sport *sport = &shca->sport[port - 1];
-   unsigned long flags;
 
switch (ec) {
case 0x30: /* port availability change */
if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) {
-   /* only for autodetect mode important */
-   if (ehca_nr_ports >= 0)
-   break;
-
-   int suppress_event;
-   /* replay modify_qp for sqps */
-   spin_lock_irqsave(&sport->mod_sqp_lock, flags);
-   suppress_event = !sport->ibqp_sqp[IB_QPT_GSI];
-   if (sport->ibqp_sqp[IB_QPT_SMI])
-   ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]);
-   if (!suppress_event)
-   ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]);
-   spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
-
-   /* AQP1 was destroyed, ignore this event */
-   if (suppress_event)
-   break;
+   /* only replay modify_qp calls in autodetect mode;
+* if AQP1 was destroyed, the port is already down
+* again and we can drop the event.
+*/
+   if (ehca_nr_ports < 0)
+   if (replay_modify_qp(sport))
+   break;
 
sport->port_state = IB_PORT_ACTIVE;
dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
-- 
1.5.5




___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH] ibmebus/of_platform: Move "name" sysfs attribute into generic OF devices

2008-08-19 Thread Joachim Fenkes
Paul Mackerras <[EMAIL PROTECTED]> wrote on 19.08.2008 06:14:00:
 
> > Recent of_platform changes made of_bus_type_init() overwrite the bus 
type's
> > .dev_attrs list, so move ibmebus' "name" attribute (which is needed by 
eHCA
> > userspace support) into generic OF device code. Tested on POWER.
> 
> Is this a bugfix that is needed for 2.6.27?

Yes, definitely. The eHCA userspace driver relies on the name attribute to 
check for valid adapters (it checks that the name is "lhca"), so with the 
name attribute gone, eHCA userspace will cease to work.

Regards,
  Joachim
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] ibmebus/of_platform: Move "name" sysfs attribute into generic OF devices

2008-08-05 Thread Joachim Fenkes
Recent of_platform changes made of_bus_type_init() overwrite the bus type's
.dev_attrs list, so move ibmebus' "name" attribute (which is needed by eHCA
userspace support) into generic OF device code. Tested on POWER.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 arch/powerpc/kernel/ibmebus.c |   12 
 drivers/of/device.c   |   10 ++
 2 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 9d42eb5..a063622 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -233,17 +233,6 @@ void ibmebus_free_irq(u32 ist, void *dev_id)
 }
 EXPORT_SYMBOL(ibmebus_free_irq);
 
-static ssize_t name_show(struct device *dev,
-struct device_attribute *attr, char *buf)
-{
-   return sprintf(buf, "%s\n", to_of_device(dev)->node->name);
-}
-
-static struct device_attribute ibmebus_dev_attrs[] = {
-   __ATTR_RO(name),
-   __ATTR_NULL
-};
-
 static char *ibmebus_chomp(const char *in, size_t count)
 {
char *out = kmalloc(count + 1, GFP_KERNEL);
@@ -327,7 +316,6 @@ static struct bus_attribute ibmebus_bus_attrs[] = {
 
 struct bus_type ibmebus_bus_type = {
.uevent= of_device_uevent,
-   .dev_attrs = ibmebus_dev_attrs,
.bus_attrs = ibmebus_bus_attrs
 };
 EXPORT_SYMBOL(ibmebus_bus_type);
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 8a1d93a..51e5214 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -57,6 +57,15 @@ static ssize_t devspec_show(struct device *dev,
return sprintf(buf, "%s\n", ofdev->node->full_name);
 }
 
+static ssize_t name_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct of_device *ofdev;
+
+   ofdev = to_of_device(dev);
+   return sprintf(buf, "%s\n", ofdev->node->name);
+}
+
 static ssize_t modalias_show(struct device *dev,
struct device_attribute *attr, char *buf)
 {
@@ -71,6 +80,7 @@ static ssize_t modalias_show(struct device *dev,
 
 struct device_attribute of_platform_device_attrs[] = {
__ATTR_RO(devspec),
+   __ATTR_RO(name),
__ATTR_RO(modalias),
__ATTR_NULL
 };
-- 
1.5.5





___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 2/2] IB/ehca: Default value for Local CA ACK Delay

2008-07-21 Thread Joachim Fenkes
Some firmware versions report a Local CA ACK Delay of 0. In that case,
return a more sensible default value of 12 (-> 16 msec) instead.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_hca.c |4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c 
b/drivers/infiniband/hw/ehca/ehca_hca.c
index bc3b37d..4628822 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -114,7 +114,9 @@ int ehca_query_device(struct ib_device *ibdev, struct 
ib_device_attr *props)
}
 
props->max_pkeys   = 16;
-   props->local_ca_ack_delay  = min_t(u8, rblock->local_ca_ack_delay, 255);
+   /* Some FW versions say 0 here; insert sensible value in that case */
+   props->local_ca_ack_delay  = rblock->local_ca_ack_delay ?
+   min_t(u8, rblock->local_ca_ack_delay, 255) : 12;
props->max_raw_ipv6_qp = limit_uint(rblock->max_raw_ipv6_qp);
props->max_raw_ethy_qp = limit_uint(rblock->max_raw_ethy_qp);
props->max_mcast_grp   = limit_uint(rblock->max_mcast_grp);
-- 
1.5.5


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 1/2] IB/ehca: Filter PATH_MIG events if QP was never armed

2008-07-21 Thread Joachim Fenkes
Certain firmware versions sometimes cause spurious PATH_MIG events to occur
during QP creation. Filter these events by making sure PATH_MIG events are
only handed down when they actually make sense (i.e. when the QP has been
armed at least once).

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |1 +
 drivers/infiniband/hw/ehca/ehca_irq.c |4 
 drivers/infiniband/hw/ehca/ehca_qp.c  |2 ++
 3 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h 
b/drivers/infiniband/hw/ehca/ehca_classes.h
index 1e9e99a..0b0618e 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -194,6 +194,7 @@ struct ehca_qp {
u32 packet_count;
atomic_t nr_events; /* events seen */
wait_queue_head_t wait_completion;
+   int mig_armed;
 };
 
 #define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c 
b/drivers/infiniband/hw/ehca/ehca_irq.c
index 0792d93..99642a6 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -178,6 +178,10 @@ static void dispatch_qp_event(struct ehca_shca *shca, 
struct ehca_qp *qp,
 {
struct ib_event event;
 
+   /* PATH_MIG without the QP ever having been armed is false alarm */
+   if (event_type == IB_EVENT_PATH_MIG && !qp->mig_armed)
+   return;
+
event.device = &shca->ib_device;
event.event = event_type;
 
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c 
b/drivers/infiniband/hw/ehca/ehca_qp.c
index 3f59587..ea13efd 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -1460,6 +1460,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
goto modify_qp_exit2;
}
mqpcb->path_migration_state = attr->path_mig_state + 1;
+   if (attr->path_mig_state == IB_MIG_REARM)
+   my_qp->mig_armed = 1;
update_mask |=
EHCA_BMASK_SET(MQPCB_MASK_PATH_MIGRATION_STATE, 1);
}
-- 
1.5.5


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 0/2] IB/ehca: Two minor circumventions

2008-07-21 Thread Joachim Fenkes
[1/2] fixes spurious PATH_MIG events with certain FW versions
[2/2] inserts a default value for Local CA ACK Delay

Please review these patches and queue them for inclusion into the kernel if
you think they're okay.

Thanks!
  Joachim

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] IB/ehca: Make device table externally visible

2008-07-01 Thread Joachim Fenkes
This gives ehca an autogenerated modalias and therefore enables automatic 
loading.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_main.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index 482103e..598844d 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -923,6 +923,7 @@ static struct of_device_id ehca_device_table[] =
},
{},
 };
+MODULE_DEVICE_TABLE(of, ehca_device_table);
 
 static struct of_platform_driver ehca_driver = {
.name= "ehca",
-- 
1.5.5


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] IB/ehca: Reject recv WRs if QP is in RESET state

2008-06-09 Thread Joachim Fenkes
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
On Friday 06 June 2008 22:20, Dotan Barak wrote:

> I checked the code in the ehca driver and noticed that
> post RR to a QP is being accepted in any state (including the RESET state).

You're right, this is only consistent -- thanks for pointing it out!

Regards,
  Joachim

 drivers/infiniband/hw/ehca/ehca_reqs.c |   12 ++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c 
b/drivers/infiniband/hw/ehca/ehca_reqs.c
index f093b00..ad197f4 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -544,8 +544,16 @@ int ehca_post_recv(struct ib_qp *qp,
   struct ib_recv_wr *recv_wr,
   struct ib_recv_wr **bad_recv_wr)
 {
-   return internal_post_recv(container_of(qp, struct ehca_qp, ib_qp),
- qp->device, recv_wr, bad_recv_wr);
+   struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
+
+   /* Reject WR if QP is in RESET state */
+   if (unlikely(my_qp->state == IB_QPS_RESET)) {
+   ehca_err(qp->device, "Invalid QP state  qp_state=%d qpn=%x",
+my_qp->state, qp->qp_num);
+   return -EINVAL;
+   }
+
+   return internal_post_recv(my_qp, qp->device, recv_wr, bad_recv_wr);
 }
 
 int ehca_post_srq_recv(struct ib_srq *srq,
-- 
1.5.5

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


IB/ehca: Reject send WRs only for RESET, INIT and RTR state

2008-06-06 Thread Joachim Fenkes
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_reqs.c |6 --
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c 
b/drivers/infiniband/hw/ehca/ehca_reqs.c
index bbe0436..f093b00 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -421,8 +421,10 @@ int ehca_post_send(struct ib_qp *qp,
int ret = 0;
unsigned long flags;
 
-   if (unlikely(my_qp->state != IB_QPS_RTS)) {
-   ehca_err(qp->device, "QP not in RTS state  qpn=%x", qp->qp_num);
+   /* Reject WR if QP is in RESET, INIT or RTR state */
+   if (unlikely(my_qp->state < IB_QPS_RTS)) {
+   ehca_err(qp->device, "Invalid QP state  qp_state=%d qpn=%x",
+my_qp->state, qp->qp_num);
return -EINVAL;
}
 
-- 
1.5.5


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 1/5] IB/ehca: Prevent posting of SQ WQEs if QP not in RTS

2008-04-21 Thread Joachim Fenkes
On Monday 21 April 2008 10:04, Joachim Fenkes wrote:

> + if (unlikely(my_qp->state != IB_QPS_RTS)) {
> + ehca_err(qp->device, "QP not in RTS state  qpn=%x", qp->qp_num);
> + return -EINVAL;
> + }

Myself, I'm not very happy with using EINVAL, but I can't think of a more
fitting return code. Also, this is what nes, amso and cxgb3 return in such a
case; ipath posts an error CQE and mthca/mlx4 don't do this check at all
(AFAICS).

Better suggestions, anyone?

Regards,
  Joachim

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 5/5] IB/ehca: Bump version number to 0026

2008-04-21 Thread Joachim Fenkes
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_main.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index 45fe35a..6504897 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -50,7 +50,7 @@
 #include "ehca_tools.h"
 #include "hcp_if.h"
 
-#define HCAD_VERSION "0025"
+#define HCAD_VERSION "0026"
 
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Christoph Raisch <[EMAIL PROTECTED]>");
-- 
1.5.5


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 4/5] IB/ehca: Make some module parameters bool, update descriptions

2008-04-21 Thread Joachim Fenkes
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_main.c |   37 +++
 1 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index ab02ac8..45fe35a 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -69,41 +69,40 @@ int ehca_static_rate   = -1;
 int ehca_scaling_code  = 0;
 int ehca_lock_hcalls   = -1;
 
-module_param_named(open_aqp1, ehca_open_aqp1, int, S_IRUGO);
-module_param_named(debug_level,   ehca_debug_level,   int, S_IRUGO);
-module_param_named(hw_level,  ehca_hw_level,  int, S_IRUGO);
-module_param_named(nr_ports,  ehca_nr_ports,  int, S_IRUGO);
-module_param_named(use_hp_mr, ehca_use_hp_mr, int, S_IRUGO);
-module_param_named(port_act_time, ehca_port_act_time, int, S_IRUGO);
-module_param_named(poll_all_eqs,  ehca_poll_all_eqs,  int, S_IRUGO);
-module_param_named(static_rate,   ehca_static_rate,   int, S_IRUGO);
-module_param_named(scaling_code,  ehca_scaling_code,  int, S_IRUGO);
+module_param_named(open_aqp1, ehca_open_aqp1, bool, S_IRUGO);
+module_param_named(debug_level,   ehca_debug_level,   int,  S_IRUGO);
+module_param_named(hw_level,  ehca_hw_level,  int,  S_IRUGO);
+module_param_named(nr_ports,  ehca_nr_ports,  int,  S_IRUGO);
+module_param_named(use_hp_mr, ehca_use_hp_mr, bool, S_IRUGO);
+module_param_named(port_act_time, ehca_port_act_time, int,  S_IRUGO);
+module_param_named(poll_all_eqs,  ehca_poll_all_eqs,  bool, S_IRUGO);
+module_param_named(static_rate,   ehca_static_rate,   int,  S_IRUGO);
+module_param_named(scaling_code,  ehca_scaling_code,  bool, S_IRUGO);
 module_param_named(lock_hcalls,   ehca_lock_hcalls,   bool, S_IRUGO);
 
 MODULE_PARM_DESC(open_aqp1,
-"AQP1 on startup (0: no (default), 1: yes)");
+"Open AQP1 on startup (default: no)");
 MODULE_PARM_DESC(debug_level,
 "Amount of debug output (0: none (default), 1: traces, "
 "2: some dumps, 3: lots)");
 MODULE_PARM_DESC(hw_level,
-"hardware level"
-" (0: autosensing (default), 1: v. 0.20, 2: v. 0.21)");
+"Hardware level (0: autosensing (default), "
+"0x10..0x14: eHCA, 0x20..0x23: eHCA2)");
 MODULE_PARM_DESC(nr_ports,
 "number of connected ports (-1: autodetect, 1: port one only, "
 "2: two ports (default)");
 MODULE_PARM_DESC(use_hp_mr,
-"high performance MRs (0: no (default), 1: yes)");
+"Use high performance MRs (default: no)");
 MODULE_PARM_DESC(port_act_time,
-"time to wait for port activation (default: 30 sec)");
+"Time to wait for port activation (default: 30 sec)");
 MODULE_PARM_DESC(poll_all_eqs,
-"polls all event queues periodically"
-" (0: no, 1: yes (default))");
+"Poll all event queues periodically (default: yes)");
 MODULE_PARM_DESC(static_rate,
-"set permanent static rate (default: disabled)");
+"Set permanent static rate (default: no static rate)");
 MODULE_PARM_DESC(scaling_code,
-"set scaling code (0: disabled/default, 1: enabled)");
+"Enable scaling code (default: no)");
 MODULE_PARM_DESC(lock_hcalls,
-"serialize all hCalls made by the driver "
+"Serialize all hCalls made by the driver "
 "(default: autodetect)");
 
 DEFINE_RWLOCK(ehca_qp_idr_lock);
-- 
1.5.5


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 3/5] IB/ehca: Remove mr_largepage parameter

2008-04-21 Thread Joachim Fenkes
Always enable large page support; didn't seem to cause problems for anyone.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_main.c |   22 +++---
 1 files changed, 3 insertions(+), 19 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index 4379bef..ab02ac8 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -60,7 +60,6 @@ MODULE_VERSION(HCAD_VERSION);
 static int ehca_open_aqp1 = 0;
 static int ehca_hw_level  = 0;
 static int ehca_poll_all_eqs  = 1;
-static int ehca_mr_largepage  = 1;
 
 int ehca_debug_level   = 0;
 int ehca_nr_ports  = 2;
@@ -79,7 +78,6 @@ module_param_named(port_act_time, ehca_port_act_time, int, 
S_IRUGO);
 module_param_named(poll_all_eqs,  ehca_poll_all_eqs,  int, S_IRUGO);
 module_param_named(static_rate,   ehca_static_rate,   int, S_IRUGO);
 module_param_named(scaling_code,  ehca_scaling_code,  int, S_IRUGO);
-module_param_named(mr_largepage,  ehca_mr_largepage,  int, S_IRUGO);
 module_param_named(lock_hcalls,   ehca_lock_hcalls,   bool, S_IRUGO);
 
 MODULE_PARM_DESC(open_aqp1,
@@ -104,9 +102,6 @@ MODULE_PARM_DESC(static_rate,
 "set permanent static rate (default: disabled)");
 MODULE_PARM_DESC(scaling_code,
 "set scaling code (0: disabled/default, 1: enabled)");
-MODULE_PARM_DESC(mr_largepage,
-"use large page for MR (0: use PAGE_SIZE (default), "
-"1: use large page depending on MR size");
 MODULE_PARM_DESC(lock_hcalls,
 "serialize all hCalls made by the driver "
 "(default: autodetect)");
@@ -357,11 +352,9 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
 
/* translate supported MR page sizes; always support 4K */
shca->hca_cap_mr_pgsize = EHCA_PAGESIZE;
-   if (ehca_mr_largepage) { /* support extra sizes only if enabled */
-   for (i = 0; i < ARRAY_SIZE(pgsize_map); i += 2)
-   if (rblock->memory_page_size_supported & pgsize_map[i])
-   shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
-   }
+   for (i = 0; i < ARRAY_SIZE(pgsize_map); i += 2)
+   if (rblock->memory_page_size_supported & pgsize_map[i])
+   shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
 
/* query max MTU from first port -- it's the same for all ports */
port = (struct hipz_query_port *)rblock;
@@ -663,14 +656,6 @@ static ssize_t ehca_show_adapter_handle(struct device *dev,
 }
 static DEVICE_ATTR(adapter_handle, S_IRUGO, ehca_show_adapter_handle, NULL);
 
-static ssize_t ehca_show_mr_largepage(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
-   return sprintf(buf, "%d\n", ehca_mr_largepage);
-}
-static DEVICE_ATTR(mr_largepage, S_IRUGO, ehca_show_mr_largepage, NULL);
-
 static struct attribute *ehca_dev_attrs[] = {
&dev_attr_adapter_handle.attr,
&dev_attr_num_ports.attr,
@@ -687,7 +672,6 @@ static struct attribute *ehca_dev_attrs[] = {
&dev_attr_cur_mw.attr,
&dev_attr_max_pd.attr,
&dev_attr_max_ah.attr,
-   &dev_attr_mr_largepage.attr,
NULL
 };
 
-- 
1.5.5


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 2/5] IB/ehca: Move high-volume debug output to higher debug levels

2008-04-21 Thread Joachim Fenkes
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_irq.c|2 +-
 drivers/infiniband/hw/ehca/ehca_main.c   |   14 ++--
 drivers/infiniband/hw/ehca/ehca_mrmw.c   |   16 ++
 drivers/infiniband/hw/ehca/ehca_qp.c |   12 
 drivers/infiniband/hw/ehca/ehca_reqs.c   |   46 ++---
 drivers/infiniband/hw/ehca/ehca_uverbs.c |6 +--
 drivers/infiniband/hw/ehca/hcp_if.c  |   23 ---
 7 files changed, 63 insertions(+), 56 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c 
b/drivers/infiniband/hw/ehca/ehca_irq.c
index b5ca94c..ca5eb0c 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -633,7 +633,7 @@ static inline int find_next_online_cpu(struct 
ehca_comp_pool *pool)
unsigned long flags;
 
WARN_ON_ONCE(!in_interrupt());
-   if (ehca_debug_level)
+   if (ehca_debug_level >= 3)
ehca_dmp(&cpu_online_map, sizeof(cpumask_t), "");
 
spin_lock_irqsave(&pool->last_cpu_lock, flags);
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index 65b3362..4379bef 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -85,8 +85,8 @@ module_param_named(lock_hcalls,   ehca_lock_hcalls,   bool, 
S_IRUGO);
 MODULE_PARM_DESC(open_aqp1,
 "AQP1 on startup (0: no (default), 1: yes)");
 MODULE_PARM_DESC(debug_level,
-"debug level"
-" (0: no debug traces (default), 1: with debug traces)");
+"Amount of debug output (0: none (default), 1: traces, "
+"2: some dumps, 3: lots)");
 MODULE_PARM_DESC(hw_level,
 "hardware level"
 " (0: autosensing (default), 1: v. 0.20, 2: v. 0.21)");
@@ -275,6 +275,7 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
u64 h_ret;
struct hipz_query_hca *rblock;
struct hipz_query_port *port;
+   const char *loc_code;
 
static const u32 pgsize_map[] = {
HCA_CAP_MR_PGSIZE_4K,  0x1000,
@@ -283,6 +284,12 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
HCA_CAP_MR_PGSIZE_16M, 0x100,
};
 
+   ehca_gen_dbg("Probing adapter %s...",
+shca->ofdev->node->full_name);
+   loc_code = of_get_property(shca->ofdev->node, "ibm,loc-code", NULL);
+   if (loc_code)
+   ehca_gen_dbg(" ... location lode=%s", loc_code);
+
rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!rblock) {
ehca_gen_err("Cannot allocate rblock memory.");
@@ -567,8 +574,7 @@ static int ehca_destroy_aqp1(struct ehca_sport *sport)
 
 static ssize_t ehca_show_debug_level(struct device_driver *ddp, char *buf)
 {
-   return snprintf(buf, PAGE_SIZE, "%d\n",
-   ehca_debug_level);
+   return snprintf(buf, PAGE_SIZE, "%d\n", ehca_debug_level);
 }
 
 static ssize_t ehca_store_debug_level(struct device_driver *ddp,
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c 
b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index f26997f..46ae4eb 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -1794,8 +1794,9 @@ static int ehca_check_kpages_per_ate(struct scatterlist 
*page_list,
int t;
for (t = start_idx; t <= end_idx; t++) {
u64 pgaddr = page_to_pfn(sg_page(&page_list[t])) << PAGE_SHIFT;
-   ehca_gen_dbg("chunk_page=%lx value=%016lx", pgaddr,
-*(u64 *)abs_to_virt(phys_to_abs(pgaddr)));
+   if (ehca_debug_level >= 3)
+   ehca_gen_dbg("chunk_page=%lx value=%016lx", pgaddr,
+*(u64 *)abs_to_virt(phys_to_abs(pgaddr)));
if (pgaddr - PAGE_SIZE != *prev_pgaddr) {
ehca_gen_err("uncontiguous page found pgaddr=%lx "
 "prev_pgaddr=%lx page_list_i=%x",
@@ -1862,10 +1863,13 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo 
*pginfo,
pgaddr &
~(pginfo->hwpage_size - 1));
}
-   ehca_gen_dbg("kpage=%lx chunk_page=%lx "
-"value=%016lx", *kpage, pgaddr,
-*(u64 *)abs_to_virt(
-phys_to_abs(pgaddr)));
+   if (ehca_debug_level >= 3) {
+  

[PATCH 1/5] IB/ehca: Prevent posting of SQ WQEs if QP not in RTS

2008-04-21 Thread Joachim Fenkes
...as required by IB Spec, C10-29.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |1 +
 drivers/infiniband/hw/ehca/ehca_qp.c  |3 +++
 drivers/infiniband/hw/ehca/ehca_reqs.c|5 +
 3 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h 
b/drivers/infiniband/hw/ehca/ehca_classes.h
index 0d13fe0..3d6d946 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -160,6 +160,7 @@ struct ehca_qp {
};
u32 qp_type;
enum ehca_ext_qp_type ext_type;
+   enum ib_qp_state state;
struct ipz_queue ipz_squeue;
struct ipz_queue ipz_rqueue;
struct h_galpas galpas;
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c 
b/drivers/infiniband/hw/ehca/ehca_qp.c
index 3eb14a5..5a653d7 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -550,6 +550,7 @@ static struct ehca_qp *internal_create_qp(
spin_lock_init(&my_qp->spinlock_r);
my_qp->qp_type = qp_type;
my_qp->ext_type = parms.ext_type;
+   my_qp->state = IB_QPS_RESET;
 
if (init_attr->recv_cq)
my_qp->recv_cq =
@@ -1508,6 +1509,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
if (attr_mask & IB_QP_QKEY)
my_qp->qkey = attr->qkey;
 
+   my_qp->state = qp_new_state;
+
 modify_qp_exit2:
if (squeue_locked) { /* this means: sqe -> rts */
spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c 
b/drivers/infiniband/hw/ehca/ehca_reqs.c
index a20bbf4..0b2359e 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -421,6 +421,11 @@ int ehca_post_send(struct ib_qp *qp,
int ret = 0;
unsigned long flags;
 
+   if (unlikely(my_qp->state != IB_QPS_RTS)) {
+   ehca_err(qp->device, "QP not in RTS state  qpn=%x", qp->qp_num);
+   return -EINVAL;
+   }
+
/* LOCK the QUEUE */
spin_lock_irqsave(&my_qp->spinlock_s, flags);
 
-- 
1.5.5


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 0/5] IB/ehca: IB compliance fix, tracing verbosity and module parameters

2008-04-21 Thread Joachim Fenkes
[1/5] makes the driver reject SQ WRs if the QP is not in RTS
[2/5] bumps a lot of tracing into higher debug_levels
[3/5] removes the mr_largepage parameter
[4/5] changes some bool-ish module parms into actual bools,
  also updates some descriptions
[5/5] bumps the version number to 0026

Please review these patches and queue them for inclusion into 2.6.26 if you
think they're okay.

Thanks!
  Joachim

-- 
Joachim Fenkes  --  eHCA Linux Driver Developer and Hardware Tamer
IBM Deutschland Entwicklung GmbH  --  Dept. 3627 (I/O Firmware Dev. 2)
Schoenaicher Strasse 220  --  71032 Boeblingen  --  Germany
eMail: [EMAIL PROTECTED]




___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 1/2] IB/ehca: Update sma_attr also in case of disruptive config change

2008-01-25 Thread Joachim Fenkes
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_irq.c |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c 
b/drivers/infiniband/hw/ehca/ehca_irq.c
index 863b34f..b5ca94c 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -403,6 +403,8 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
sport->port_state = IB_PORT_ACTIVE;
dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
"is active");
+   ehca_query_sma_attr(shca, port,
+   &sport->saved_attr);
} else
notify_port_conf_change(shca, port);
break;
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 2/2] IB/ehca: Add PMA support

2008-01-25 Thread Joachim Fenkes
From: Hoang-Nam Nguyen <[EMAIL PROTECTED]>

This patch enables ehca to redirect any PMA queries to the
actual PMA QP.

Signed-off-by: Hoang-Nam Nguyen <[EMAIL PROTECTED]>
Reviewed-by: Joachim Fenkes <[EMAIL PROTECTED]>
Reviewed-by: Christoph Raisch <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |1 +
 drivers/infiniband/hw/ehca/ehca_iverbs.h  |5 ++
 drivers/infiniband/hw/ehca/ehca_main.c|2 +-
 drivers/infiniband/hw/ehca/ehca_sqp.c |   91 +
 4 files changed, 98 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h 
b/drivers/infiniband/hw/ehca/ehca_classes.h
index f281d16..92cce8a 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -101,6 +101,7 @@ struct ehca_sport {
spinlock_t mod_sqp_lock;
enum ib_port_state port_state;
struct ehca_sma_attr saved_attr;
+   u32 pma_qp_nr;
 };
 
 #define HCA_CAP_MR_PGSIZE_4K  0x8000
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h 
b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index c469bfd..a8a2ea5 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -187,6 +187,11 @@ int ehca_dealloc_ucontext(struct ib_ucontext *context);
 
 int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
 
+int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
+struct ib_wc *in_wc, struct ib_grh *in_grh,
+struct ib_mad *in_mad,
+struct ib_mad *out_mad);
+
 void ehca_poll_eqs(unsigned long data);
 
 int ehca_calc_ipd(struct ehca_shca *shca, int port,
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index 0fe0c84..33b5bac 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -472,7 +472,7 @@ int ehca_init_device(struct ehca_shca *shca)
shca->ib_device.dealloc_fmr = ehca_dealloc_fmr;
shca->ib_device.attach_mcast= ehca_attach_mcast;
shca->ib_device.detach_mcast= ehca_detach_mcast;
-   /* shca->ib_device.process_mad  = ehca_process_mad; */
+   shca->ib_device.process_mad = ehca_process_mad;
shca->ib_device.mmap= ehca_mmap;
 
if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
diff --git a/drivers/infiniband/hw/ehca/ehca_sqp.c 
b/drivers/infiniband/hw/ehca/ehca_sqp.c
index 79e72b2..706d97a 100644
--- a/drivers/infiniband/hw/ehca/ehca_sqp.c
+++ b/drivers/infiniband/hw/ehca/ehca_sqp.c
@@ -39,12 +39,18 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include 
 
 #include "ehca_classes.h"
 #include "ehca_tools.h"
 #include "ehca_iverbs.h"
 #include "hcp_if.h"
 
+#define IB_MAD_STATUS_REDIRECT __constant_htons(0x0002)
+#define IB_MAD_STATUS_UNSUP_VERSION__constant_htons(0x0004)
+#define IB_MAD_STATUS_UNSUP_METHOD __constant_htons(0x0008)
+
+#define IB_PMA_CLASS_PORT_INFO __constant_htons(0x0001)
 
 /**
  * ehca_define_sqp - Defines special queue pair 1 (GSI QP). When special queue
@@ -83,6 +89,9 @@ u64 ehca_define_sqp(struct ehca_shca *shca,
 port, ret);
return ret;
}
+   shca->sport[port - 1].pma_qp_nr = pma_qp_nr;
+   ehca_dbg(&shca->ib_device, "port=%x pma_qp_nr=%x",
+port, pma_qp_nr);
break;
default:
ehca_err(&shca->ib_device, "invalid qp_type=%x",
@@ -109,3 +118,85 @@ u64 ehca_define_sqp(struct ehca_shca *shca,
 
return H_SUCCESS;
 }
+
+struct ib_perf {
+   struct ib_mad_hdr mad_hdr;
+   u8 reserved[40];
+   u8 data[192];
+} __attribute__ ((packed));
+
+
+static int ehca_process_perf(struct ib_device *ibdev, u8 port_num,
+struct ib_mad *in_mad, struct ib_mad *out_mad)
+{
+   struct ib_perf *in_perf = (struct ib_perf *)in_mad;
+   struct ib_perf *out_perf = (struct ib_perf *)out_mad;
+   struct ib_class_port_info *poi =
+   (struct ib_class_port_info *)out_perf->data;
+   struct ehca_shca *shca =
+   container_of(ibdev, struct ehca_shca, ib_device);
+   struct ehca_sport *sport = &shca->sport[port_num - 1];
+
+   ehca_dbg(ibdev, "method=%x", in_perf->mad_hdr.method);
+
+   *out_mad = *in_mad;
+
+   if (in_perf->mad_hdr.class_version != 1) {
+   ehca_warn(ibdev, "Unsupported class_version=%x",
+ in_perf->mad_hdr.class_version);
+   out_perf->mad_hdr.status = IB_MAD_STATUS_UNSUP_VERSION;
+   goto perf_reply;
+   }
+
+   switch (in_perf->mad_hdr.method) {
+   case IB_MGMT_ME

[PATCH 0/2] IB/ehca: PMA support and a minor fix

2008-01-25 Thread Joachim Fenkes
This patchset will fix a minor issue and then add support for Performance
MADs, which redirects all PMA queries to the actual PMA QP.

[1/2] adds a missing query_pma_attr()
[2/2] adds PMA redirection code

The patches will apply, in order, on top of Roland's for-2.6.25 branch.
Please review them and apply for 2.6.25 if you think they're okay.

Thanks and regards,
  Joachim

-- 
Joachim Fenkes  --  eHCA Linux Driver Developer and Hardware Tamer
IBM Deutschland Entwicklung GmbH  --  Dept. 3627 (I/O Firmware Dev. 2)
Schoenaicher Strasse 220  --  71032 Boeblingen  --  Germany
eMail: [EMAIL PROTECTED]



___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] IB/ehca: Prevent sending UD packets to QP0

2008-01-24 Thread Joachim Fenkes
IB spec doesn't allow packets to QP0 sent on any other VL than VL15.
Hardware doesn't filter those packets on the send side, so we need to do
this in the driver and firmware.

As eHCA doesn't support QP0, we can just filter out all traffic going to
QP0, regardless of SL or VL.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_reqs.c |4 
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c 
b/drivers/infiniband/hw/ehca/ehca_reqs.c
index 3aacc8c..2ce8cff 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -209,6 +209,10 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
ehca_gen_err("wr.ud.ah is NULL. qp=%p", qp);
return -EINVAL;
}
+   if (unlikely(send_wr->wr.ud.remote_qpn == 0)) {
+   ehca_gen_err("dest QP# is 0. qp=%x", qp->real_qp_num);
+   return -EINVAL;
+   }
my_av = container_of(send_wr->wr.ud.ah, struct ehca_av, ib_ah);
wqe_p->u.ud_av.ud_av = my_av->av;
 
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 4/4] IB/ehca: Prevent RDMA-related connection failures

2008-01-17 Thread Joachim Fenkes
Some HW revisions of eHCA2 may cause an RC connection to break if they
received RDMA Reads over that connection before. This can be prevented by
assuring that, after the first RDMA Read, the QP receives a new RDMA Read
every few million link packets.

Include code into the driver that inserts an empty (size 0) RDMA Read into
the message stream every now and then if the consumer doesn't post them
frequently enough.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |5 ++
 drivers/infiniband/hw/ehca/ehca_qp.c  |   14 +++-
 drivers/infiniband/hw/ehca/ehca_reqs.c|  112 
 3 files changed, 95 insertions(+), 36 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h 
b/drivers/infiniband/hw/ehca/ehca_classes.h
index 2502366..f281d16 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -183,6 +183,11 @@ struct ehca_qp {
u32 mm_count_squeue;
u32 mm_count_rqueue;
u32 mm_count_galpa;
+   /* unsolicited ack circumvention */
+   int unsol_ack_circ;
+   int mtu_shift;
+   u32 message_count;
+   u32 packet_count;
 };
 
 #define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c 
b/drivers/infiniband/hw/ehca/ehca_qp.c
index bb7ccef..6c050e0 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -592,10 +592,8 @@ static struct ehca_qp *internal_create_qp(
goto create_qp_exit1;
}
 
-   if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
-   parms.sigtype = HCALL_SIGT_EVERY;
-   else
-   parms.sigtype = HCALL_SIGT_BY_WQE;
+   /* Always signal by WQE so we can hide circ. WQEs */
+   parms.sigtype = HCALL_SIGT_BY_WQE;
 
/* UD_AV CIRCUMVENTION */
max_send_sge = init_attr->cap.max_send_sge;
@@ -618,6 +616,10 @@ static struct ehca_qp *internal_create_qp(
parms.squeue.max_sge = max_send_sge;
parms.rqueue.max_sge = max_recv_sge;
 
+   /* RC QPs need one more SWQE for unsolicited ack circumvention */
+   if (qp_type == IB_QPT_RC)
+   parms.squeue.max_wr++;
+
if (EHCA_BMASK_GET(HCA_CAP_MINI_QP, shca->hca_cap)) {
if (HAS_SQ(my_qp))
ehca_determine_small_queue(
@@ -650,6 +652,8 @@ static struct ehca_qp *internal_create_qp(
parms.squeue.act_nr_sges = 1;
parms.rqueue.act_nr_sges = 1;
}
+   /* hide the extra WQE */
+   parms.squeue.act_nr_wqes--;
break;
case IB_QPT_UD:
case IB_QPT_GSI:
@@ -1295,6 +1299,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
}
 
if (attr_mask & IB_QP_PATH_MTU) {
+   /* store ld(MTU) */
+   my_qp->mtu_shift = attr->path_mtu + 7;
mqpcb->path_mtu = attr->path_mtu;
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PATH_MTU, 1);
}
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c 
b/drivers/infiniband/hw/ehca/ehca_reqs.c
index ea91360..3aacc8c 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -50,6 +50,9 @@
 #include "hcp_if.h"
 #include "hipz_fns.h"
 
+/* in RC traffic, insert an empty RDMA READ every this many packets */
+#define ACK_CIRC_THRESHOLD 200
+
 static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
  struct ehca_wqe *wqe_p,
  struct ib_recv_wr *recv_wr)
@@ -81,7 +84,7 @@ 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_dmp( wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe");
+   ehca_dmp(wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe");
}
 
return 0;
@@ -135,7 +138,8 @@ static void trace_send_wr_ud(const struct ib_send_wr 
*send_wr)
 
 static inline int ehca_write_swqe(struct ehca_qp *qp,
  struct ehca_wqe *wqe_p,
- const struct ib_send_wr *send_wr)
+ const struct ib_send_wr *send_wr,
+ int hidden)
 {
u32 idx;
u64 dma_length;
@@ -176,7 +180,9 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
 
wqe_p->wr_flag = 0;
 
-   if (send_wr->send_flags & IB_SEND_SIGNALED)
+   if ((send_wr->send_flags & IB_SEND_SIGNALED ||
+   qp->init_attr.sq_sig_type == IB_SIGNAL_ALL_WR)
+   && !hidden)
wqe_p->wr_flag |= WQE_WRFLAG_REQ_SIGNAL_COM;
 

[PATCH 3/4] IB/ehca: Add "port connection autodetect mode"

2008-01-17 Thread Joachim Fenkes
From: Hoang-Nam Nguyen <[EMAIL PROTECTED]>

This patch enhances ehca with a capability to "autodetect" the ports being
connected physically. In order to utilize that function the module option
nr_ports must be set to -1 (default is 2 - two ports). This feature is
experimental and will made the default later.

More detail:

If the user connects only one port to the switch, current code requires
  1) port one to be connected and
  2) module option nr_ports=1 to be given.

If autodetect is enabled, ehca will not wait at creation of the GSI QP for
the respective port to become active. Since firmware does not accept
modify_qp() while the port is down at initialization, we need to cache all
calls to modify_qp() for the SMI/GSI QP and just return a good return code.

When a port is activated and we get a PORT_ACTIVE event, we replay the
cached modify-qp() parms and re-trigger any posted recv WRs. Only then do we
forward the PORT_ACTIVE event to registered clients.

The result of this autodetect patch is that all ports will be accessible by
the users. Depending on their respective cabling only those ports that are
connected properly will become operable. If a user tries to modify a regular
QP of a non-connected port, modify_qp() will fail. Furthermore, ibv_devinfo
should show the port state accordingly.

Note that this patch primarily improves the loading behaviour of ehca. If
the cable is removed while the driver is operating and plugged in again,
firmware will handle that properly by sending an appropriate async event.

Signed-off-by: Hoang-Nam Nguyen <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |   16 +++
 drivers/infiniband/hw/ehca/ehca_irq.c |   26 -
 drivers/infiniband/hw/ehca/ehca_iverbs.h  |2 +
 drivers/infiniband/hw/ehca/ehca_main.c|7 +-
 drivers/infiniband/hw/ehca/ehca_qp.c  |  162 -
 drivers/infiniband/hw/ehca/ehca_sqp.c |6 +-
 6 files changed, 204 insertions(+), 15 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h 
b/drivers/infiniband/hw/ehca/ehca_classes.h
index 936580d..2502366 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -95,6 +95,10 @@ struct ehca_sma_attr {
 struct ehca_sport {
struct ib_cq *ibcq_aqp1;
struct ib_qp *ibqp_sqp[2];
+   /* lock to serialze modify_qp() calls for sqp in normal
+* and irq path (when event PORT_ACTIVE is received first time)
+*/
+   spinlock_t mod_sqp_lock;
enum ib_port_state port_state;
struct ehca_sma_attr saved_attr;
 };
@@ -141,6 +145,14 @@ enum ehca_ext_qp_type {
EQPT_SRQ   = 3,
 };
 
+/* struct to cache modify_qp()'s parms for GSI/SMI qp */
+struct ehca_mod_qp_parm {
+   int mask;
+   struct ib_qp_attr attr;
+};
+
+#define EHCA_MOD_QP_PARM_MAX 4
+
 struct ehca_qp {
union {
struct ib_qp ib_qp;
@@ -164,6 +176,9 @@ struct ehca_qp {
struct ehca_cq *recv_cq;
unsigned int sqerr_purgeflag;
struct hlist_node list_entries;
+   /* array to cache modify_qp()'s parms for GSI/SMI qp */
+   struct ehca_mod_qp_parm *mod_qp_parm;
+   int mod_qp_parm_idx;
/* mmap counter for resources mapped into user space */
u32 mm_count_squeue;
u32 mm_count_rqueue;
@@ -323,6 +338,7 @@ extern int ehca_port_act_time;
 extern int ehca_use_hp_mr;
 extern int ehca_scaling_code;
 extern int ehca_lock_hcalls;
+extern int ehca_nr_ports;
 
 struct ipzu_queue_resp {
u32 qe_size;  /* queue entry size */
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c 
b/drivers/infiniband/hw/ehca/ehca_irq.c
index 4c734ec..863b34f 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -356,17 +356,33 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
u8 ec   = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe);
u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe);
u8 spec_event;
+   struct ehca_sport *sport = &shca->sport[port - 1];
+   unsigned long flags;
 
switch (ec) {
case 0x30: /* port availability change */
if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) {
-   shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
+   int suppress_event;
+   /* replay modify_qp for sqps */
+   spin_lock_irqsave(&sport->mod_sqp_lock, flags);
+   suppress_event = !sport->ibqp_sqp[IB_QPT_GSI];
+   if (sport->ibqp_sqp[IB_QPT_SMI])
+   ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]);
+   if (!suppress_event)
+   ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]);
+   spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
+
+   /* AQP1 was destroyed, ignore this event */
+   if

[PATCH 2/4] IB/ehca: Define array to store SMI/GSI QPs

2008-01-17 Thread Joachim Fenkes
From: Hoang-Nam Nguyen 

Signed-off-by: Hoang-Nam Nguyen <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |2 +-
 drivers/infiniband/hw/ehca/ehca_main.c|6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h 
b/drivers/infiniband/hw/ehca/ehca_classes.h
index 74d2b72..936580d 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -94,7 +94,7 @@ struct ehca_sma_attr {
 
 struct ehca_sport {
struct ib_cq *ibcq_aqp1;
-   struct ib_qp *ibqp_aqp1;
+   struct ib_qp *ibqp_sqp[2];
enum ib_port_state port_state;
struct ehca_sma_attr saved_attr;
 };
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index 6a56d86..cde486c 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -511,7 +511,7 @@ static int ehca_create_aqp1(struct ehca_shca *shca, u32 
port)
}
sport->ibcq_aqp1 = ibcq;
 
-   if (sport->ibqp_aqp1) {
+   if (sport->ibqp_sqp[IB_QPT_GSI]) {
ehca_err(&shca->ib_device, "AQP1 QP is already created.");
ret = -EPERM;
goto create_aqp1;
@@ -537,7 +537,7 @@ static int ehca_create_aqp1(struct ehca_shca *shca, u32 
port)
ret = PTR_ERR(ibqp);
goto create_aqp1;
}
-   sport->ibqp_aqp1 = ibqp;
+   sport->ibqp_sqp[IB_QPT_GSI] = ibqp;
 
return 0;
 
@@ -550,7 +550,7 @@ static int ehca_destroy_aqp1(struct ehca_sport *sport)
 {
int ret;
 
-   ret = ib_destroy_qp(sport->ibqp_aqp1);
+   ret = ib_destroy_qp(sport->ibqp_sqp[IB_QPT_GSI]);
if (ret) {
ehca_gen_err("Cannot destroy AQP1 QP. ret=%i", ret);
return ret;
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 1/4] IB/ehca: Remove CQ-QP-link before destroying QP in error path of create_qp()

2008-01-17 Thread Joachim Fenkes
From: Hoang-Nam Nguyen 

Signed-off-by: Hoang-Nam Nguyen <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_qp.c |5 -
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c 
b/drivers/infiniband/hw/ehca/ehca_qp.c
index f116eb7..26c6a94 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -769,12 +769,15 @@ static struct ehca_qp *internal_create_qp(
if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
ehca_err(pd->device, "Copy to udata failed");
ret = -EINVAL;
-   goto create_qp_exit4;
+   goto create_qp_exit5;
}
}
 
return my_qp;
 
+create_qp_exit5:
+   ehca_cq_unassign_qp(my_qp->send_cq, my_qp->real_qp_num);
+
 create_qp_exit4:
if (HAS_RQ(my_qp))
ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 0/4] IB/ehca: fixes, port connectivity autodetection, problem workaround

2008-01-17 Thread Joachim Fenkes
This patchset will fix a minor issue, introduce port connectivity
autodetection and work around an RDMA-related problem in eHCA2.

[1/4] fixes an error path in destroy_qp()
[2/4] stores the SMI/GSI QPs in a per-port array
[3/4] adds port connectivity autodetection
[4/4] adds the aforementioned workaround

The patches will apply, in order, on top of Roland's for-2.6.25 branch.
Please review them and apply for 2.6.25 if you think they're okay.

Thanks and regards,
  Joachim

-- 
Joachim Fenkes  --  eHCA Linux Driver Developer and Hardware Tamer
IBM Deutschland Entwicklung GmbH  --  Dept. 3627 (I/O Firmware Dev. 2)
Schoenaicher Strasse 220  --  71032 Boeblingen  --  Germany
eMail: [EMAIL PROTECTED]


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH] [POWERPC] make ibmebus use of_(un)register_driver

2008-01-14 Thread Joachim Fenkes
On Monday 14 January 2008 07:46, Stephen Rothwell wrote:

> diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
> index 1844359..2a6a388 100644
> --- a/arch/powerpc/kernel/ibmebus.c
> +++ b/arch/powerpc/kernel/ibmebus.c
> @@ -197,16 +197,13 @@ int ibmebus_register_driver(struct of_platform_driver 
> *drv)
>   /* If the driver uses devices that ibmebus doesn't know, add them */
>   ibmebus_create_devices(drv->match_table);
> 
> - drv->driver.name   = drv->name;
> - drv->driver.bus= &ibmebus_bus_type;
> -
> - return driver_register(&drv->driver);
> + return of_register_driver(drv, &ibmebus_bus_type);
>  }
>  EXPORT_SYMBOL(ibmebus_register_driver);
> 
>  void ibmebus_unregister_driver(struct of_platform_driver *drv)
>  {
> - driver_unregister(&drv->driver);
> + of_unregister_driver(drv);
>  }
>  EXPORT_SYMBOL(ibmebus_unregister_driver);

Looks like a transparent change to me. Good one.

Joachim

Acked-by: Joachim Fenkes <[EMAIL PROTECTED]>

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


RE: [ofa-general] Re: [ewg] Re: [PATCH] IB/ehca: Serialize HCA-related hCalls on POWER5

2007-12-13 Thread Joachim Fenkes
"Caitlin Bestler" <[EMAIL PROTECTED]> wrote on 13.12.2007 
22:08:34:

> To clarify, an FMR Work Request is simply posted to the SendQ like
> any other Work Request (of course the QP has to be privileged, or
> it will complete in error). An SQ Post should never block.

This would require hardware support, wouldn't it? eHCA2 doesn't have this 
kind of support, so FMR WRs are not an option here.

J.
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [ofa-general] Re: [ewg] Re: [PATCH] IB/ehca: Serialize HCA-related hCalls on POWER5

2007-12-13 Thread Joachim Fenkes
[EMAIL PROTECTED] wrote on 13.12.2007 20:22:49:

> On Dec 13, 2007 12:30 AM, Or Gerlitz <[EMAIL PROTECTED]> wrote:
> > The current implementation of the open iscsi initiator makes sure to
> > issue commands in thread (sleepable) context, see iscsi_xmitworker and
> > references to it in drivers/scsi/libiscsi.c , so this keeps ehca users
> > safe for the time being.

> I agree, *some* form of FMR support is important for iSER (and probably
> for NFS over RDMA as well). Rather than adding a crippled NO FMR
> mode it would make more sense to add support for FMR Work Requests.
> I'm not certain what, if any, impact that would have on the Power5 
problem,
> but that's certainly a cleaner path for iWARP.

Well, FMR WRs wouldn't change the eHCA issue -- the driver would have to 
make an hCall in any case, and the architecture says that the hCalls used 
in this scenario might return H_LONG_BUSY, causing the driver to sleep. No 
way around that. Because of this, eHCA's FMRs are actually standard MRs 
with a different API.

If, as Or said, the iSCSI initiator issues commands in sleepable context 
anyway, nothing would be lost by using standard MRs as a fallback solution 
if FMRs aren't available, would it?

J.

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] IB/ehca: Fix lock flag location, bump version number

2007-12-13 Thread Joachim Fenkes
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---

This addresses a comment of Roland and bumps the version number. If it's not
too late, please apply for 2.6.24. Thanks!

 drivers/infiniband/hw/ehca/ehca_classes.h |1 +
 drivers/infiniband/hw/ehca/ehca_main.c|2 +-
 drivers/infiniband/hw/ehca/hcp_if.c   |1 -
 3 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h 
b/drivers/infiniband/hw/ehca/ehca_classes.h
index 87f12d4..74d2b72 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -322,6 +322,7 @@ extern int ehca_static_rate;
 extern int ehca_port_act_time;
 extern int ehca_use_hp_mr;
 extern int ehca_scaling_code;
+extern int ehca_lock_hcalls;
 
 struct ipzu_queue_resp {
u32 qe_size;  /* queue entry size */
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index c7bff3e..6a56d86 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -50,7 +50,7 @@
 #include "ehca_tools.h"
 #include "hcp_if.h"
 
-#define HCAD_VERSION "0024"
+#define HCAD_VERSION "0025"
 
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Christoph Raisch <[EMAIL PROTECTED]>");
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c 
b/drivers/infiniband/hw/ehca/hcp_if.c
index 331b5e8..7029aa6 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -89,7 +89,6 @@
 #define HCALL9_REGS_FORMAT HCALL7_REGS_FORMAT " r11=%lx r12=%lx"
 
 static DEFINE_SPINLOCK(hcall_lock);
-extern int ehca_lock_hcalls;
 
 static u32 get_longbusy_msecs(int longbusy_rc)
 {
-- 
1.5.2



___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH] IB/ehca: Serialize HCA-related hCalls on POWER5

2007-12-11 Thread Joachim Fenkes
Roland Dreier <[EMAIL PROTECTED]> wrote on 10.12.2007 22:47:37:

> It's a big problem.  If you cannot implement FMRs in such a way that
> you can handling having map_phys_fmr being called in a context that
> can't sleep, then I think the only option is to remove your FMR
> support.

That's kind of what I feared you would say =)

> It's an optional device feature, so this should be OK
> (although the iSER driver currently seems to depend on a device
> supporting FMRs, which is probably going to be a problem with iWARP
> support in the future anyway).

I don't feel very well with removing code from the driver that iSER seems 
to depend on. Are there plans to fix this in iSER?

In reality, PHYP rarely ever returns H_LONG_BUSY, and we haven't had any 
problems with iSER in the field yet. I admit that our FMR code is 
dangerous, but I prefer "dangerous but working for the customer" over "not 
working for the customer at all".
 
Maybe we can agree on keeping the status quo until no more ULPs depend on 
FMR, then remove FMR from ehca? If so, we'd also let the _irqsave 
spinlocks around hCalls stay in place.

Regards,
  Joachim
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] IB/ehca: Serialize HCA-related hCalls if necessary

2007-12-10 Thread Joachim Fenkes
Several pSeries firmware versions share a rare locking issue in the
HCA-related hCalls. Check for a feature flag that indicates the issue being
fixed and serialize all HCA hCalls if not.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---

This is the revised version of my previous patch, which does not rely on the
processor version any longer.

 drivers/infiniband/hw/ehca/ehca_main.c |   13 +
 drivers/infiniband/hw/ehca/hcp_if.c|   28 +++-
 drivers/infiniband/hw/ehca/hipz_hw.h   |1 +
 3 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index 90d4334..c7bff3e 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -43,6 +43,7 @@
 #ifdef CONFIG_PPC_64K_PAGES
 #include 
 #endif
+
 #include "ehca_classes.h"
 #include "ehca_iverbs.h"
 #include "ehca_mrmw.h"
@@ -66,6 +67,7 @@ int ehca_poll_all_eqs  = 1;
 int ehca_static_rate   = -1;
 int ehca_scaling_code  = 0;
 int ehca_mr_largepage  = 1;
+int ehca_lock_hcalls   = -1;
 
 module_param_named(open_aqp1, ehca_open_aqp1, int, S_IRUGO);
 module_param_named(debug_level,   ehca_debug_level,   int, S_IRUGO);
@@ -77,6 +79,7 @@ module_param_named(poll_all_eqs,  ehca_poll_all_eqs,  int, 
S_IRUGO);
 module_param_named(static_rate,   ehca_static_rate,   int, S_IRUGO);
 module_param_named(scaling_code,  ehca_scaling_code,  int, S_IRUGO);
 module_param_named(mr_largepage,  ehca_mr_largepage,  int, S_IRUGO);
+module_param_named(lock_hcalls,   ehca_lock_hcalls,   bool, S_IRUGO);
 
 MODULE_PARM_DESC(open_aqp1,
 "AQP1 on startup (0: no (default), 1: yes)");
@@ -102,6 +105,9 @@ MODULE_PARM_DESC(scaling_code,
 MODULE_PARM_DESC(mr_largepage,
 "use large page for MR (0: use PAGE_SIZE (default), "
 "1: use large page depending on MR size");
+MODULE_PARM_DESC(lock_hcalls,
+"serialize all hCalls made by the driver "
+"(default: autodetect)");
 
 DEFINE_RWLOCK(ehca_qp_idr_lock);
 DEFINE_RWLOCK(ehca_cq_idr_lock);
@@ -258,6 +264,7 @@ static struct cap_descr {
{ HCA_CAP_UD_LL_QP, "HCA_CAP_UD_LL_QP" },
{ HCA_CAP_RESIZE_MR, "HCA_CAP_RESIZE_MR" },
{ HCA_CAP_MINI_QP, "HCA_CAP_MINI_QP" },
+   { HCA_CAP_H_ALLOC_RES_SYNC, "HCA_CAP_H_ALLOC_RES_SYNC" },
 };
 
 static int ehca_sense_attributes(struct ehca_shca *shca)
@@ -333,6 +340,12 @@ static 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);
 
+   /* Autodetect hCall locking -- the "H_ALLOC_RESOURCE synced" flag is
+* a firmware property, so it's valid across all adapters
+*/
+   if (ehca_lock_hcalls == -1)
+   ehca_lock_hcalls = !(shca->hca_cap & HCA_CAP_H_ALLOC_RES_SYNC);
+
/* translate supported MR page sizes; always support 4K */
shca->hca_cap_mr_pgsize = EHCA_PAGESIZE;
if (ehca_mr_largepage) { /* support extra sizes only if enabled */
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c 
b/drivers/infiniband/hw/ehca/hcp_if.c
index c16a213..331b5e8 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -89,6 +89,7 @@
 #define HCALL9_REGS_FORMAT HCALL7_REGS_FORMAT " r11=%lx r12=%lx"
 
 static DEFINE_SPINLOCK(hcall_lock);
+extern int ehca_lock_hcalls;
 
 static u32 get_longbusy_msecs(int longbusy_rc)
 {
@@ -120,26 +121,21 @@ static long ehca_plpar_hcall_norets(unsigned long opcode,
unsigned long arg7)
 {
long ret;
-   int i, sleep_msecs, do_lock;
-   unsigned long flags;
+   int i, sleep_msecs;
+   unsigned long flags = 0;
 
ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
 
-   /* lock H_FREE_RESOURCE(MR) against itself and H_ALLOC_RESOURCE(MR) */
-   if ((opcode == H_FREE_RESOURCE) && (arg7 == 5)) {
-   arg7 = 0; /* better not upset firmware */
-   do_lock = 1;
-   }
-
for (i = 0; i < 5; i++) {
-   if (do_lock)
+   /* serialize hCalls to work around firmware issue */
+   if (ehca_lock_hcalls)
spin_lock_irqsave(&hcall_lock, flags);
 
ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
 arg5, arg6, arg7);
 
-   if (do_lock)
+   if (ehca_lock_hcalls)
spin_unlock_irqrestore(&hcall_lock, flags);
 
if (H_IS_LONG_BUSY(ret)) {
@@ -174,24 +170,22 @@ static long 

Re: [PATCH] IB/ehca: Serialize HCA-related hCalls on POWER5

2007-12-10 Thread Joachim Fenkes
Hi, guys,

> We're taking this to the firmware architects at the moment, but they're 
not 
> very fond of the idea of reporting the absence of bugs through 
capability 
> flags, as this could quickly lead to the exhaustion of flag bits. We'll 
let 
> the discussion stew for a bit, but if we don't get this flag, we'll have 
to 
> resort to the CPU features.

The architects have spoken, and we're getting a capability flag for this. 
I'll repost my patch with new autodetection code that doesn't involve 
checking the processor version.
 
> >  > Regarding the performance problem, have you checked whether 
converting all
> >  > your spin_lock_irqsave to spin_lock/spin_lock_irq improves your 
performance
> >  > on the older machines? Maybe it's already fast enough that way.
> > 
> > It does seem that the only places that the hcall_lock is taken also
> > use msleep, so they must always be in process context.  So you can
> > safely just use spin_lock(), right?
>
> As Arnd said, there are hCalls that will never return H_LONG_BUSY_*, 
such as 
> H_QUERY_PORT and chums, so they will never sleep. The surrounding 
functions, 
> though, are not prepared to be called from interrupt context (GFP_KERNEL 
comes
> to mind), so I agree that a simple spin_lock() will suffice. Thanks, 
Arnd, for
> pointing this out.

As I pointed out in my earlier mail, there's still an issue with 
map_phys_fmr possibly sleeping. Let's keep the irqsave for the time being 
and revisit this part once we find a solution to map_phys_fmr.

Regards,
  Joachim
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH] IB/ehca: Serialize HCA-related hCalls on POWER5

2007-12-10 Thread Joachim Fenkes
On Monday 10 December 2007 00:22, Roland Dreier wrote:
> Fair enough... according to Documentation/infiniband/core_locking.txt,
> the only driver methods that cannot sleep are:
> 
> [...]
> map_phys_fmr

In fact, we do use hCalls there. Our hardware doesn't actually support FMRs,
so we translate a "map FMR" into a "reallocate PMR", which doesn't work
without hCalls. What's more, the hCalls involved (e.g. H_FREE_RESOURCE)
might well return H_LONG_BUSY, so the whole operation might sleep; no way
around it.

How should we deal with this?

Thanks,
  Joachim

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] IB/ehca: Return correct #SGEs for SRQ

2007-12-10 Thread Joachim Fenkes
Firmware would round up the number of SGEs to four, because the WQE
structure holds four SGEs. For SRQ, only three are supported, so return a
fixed value instead.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---

The patch will apply cleanly on top of Roland's git. Please review and apply
for 2.6.24 -- Thanks!

 drivers/infiniband/hw/ehca/ehca_qp.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c 
b/drivers/infiniband/hw/ehca/ehca_qp.c
index dd12668..eff5fb5 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -838,7 +838,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
 
/* copy back return values */
srq_init_attr->attr.max_wr = qp_init_attr.cap.max_recv_wr;
-   srq_init_attr->attr.max_sge = qp_init_attr.cap.max_recv_sge;
+   srq_init_attr->attr.max_sge = 3;
 
/* drive SRQ into RTR state */
mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
@@ -1750,7 +1750,7 @@ int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr 
*srq_attr)
}
 
srq_attr->max_wr = qpcb->max_nr_outst_recv_wr - 1;
-   srq_attr->max_sge = qpcb->actual_nr_sges_in_rq_wqe;
+   srq_attr->max_sge = 3;
srq_attr->srq_limit = EHCA_BMASK_GET(
MQPCB_CURR_SRQ_LIMIT, qpcb->curr_srq_limit);
 
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH] IB/ehca: Serialize HCA-related hCalls on POWER5

2007-12-07 Thread Joachim Fenkes
Roland Dreier <[EMAIL PROTECTED]> wrote on 06.12.2007 19:27:09:

>  > > +   ehca_lock_hcalls = 
!(cur_cpu_spec->cpu_user_features
>  > > +& PPC_FEATURE_ARCH_2_05);
> 
>  > We already talked about this yesterday, but I still feel that 
checking the
>  > instruction set of the CPU should not be used to determine whether a
>  > specific device driver implementation is used int hypervisor.
> 
> I had the same reaction... is testing cpu_user_features really the
> best way to detect this issue?

I concur it's not nice, but it was the only feasible method we could find 
without adding a "bug fixed" feature flag to the partition<->firmware 
interface. The firmware version reported in the OFDT is not a reliable 
enough source, and even if it were, it would require a lot of string 
parsing and matching against tables.

We're taking this to the firmware architects at the moment, but they're 
not very fond of the idea of reporting the absence of bugs through 
capability flags, as this could quickly lead to the exhaustion of flag 
bits. We'll let the discussion stew for a bit, but if we don't get this 
flag, we'll have to resort to the CPU features.
 
> I'll hold off applying this for a few days so you guys can decide the
> best thing to do.  We'll definitely get some fix into 2.6.24 but we
> have time to make a good decision.

Right.
 
>  > Regarding the performance problem, have you checked whether 
converting all
>  > your spin_lock_irqsave to spin_lock/spin_lock_irq improves your 
performance
>  > on the older machines? Maybe it's already fast enough that way.
> 
> It does seem that the only places that the hcall_lock is taken also
> use msleep, so they must always be in process context.  So you can
> safely just use spin_lock(), right?

As Arnd said, there are hCalls that will never return H_LONG_BUSY_*, such 
as H_QUERY_PORT and chums, so they will never sleep. The surrounding 
functions, though, are not prepared to be called from interrupt context 
(GFP_KERNEL comes to mind), so I agree that a simple spin_lock() will 
suffice. Thanks, Arnd, for pointing this out.

We'll keep you guys posted on the feature flag discussion. Until then, 
have a nice weekend!

Joachim
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] IB/ehca: Serialize HCA-related hCalls on POWER5

2007-12-06 Thread Joachim Fenkes
All firmware versions on POWER5 systems have a locking issue in the
HCA-related hCalls that can cause loss of Infiniband connectivity if
allocate and free calls happen in parallel. This may for example be caused
if two processes are using OpenMPI in parallel.
Circumvent this by serializing all HCA-related hCalls on POWER5.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---

We tested this patch, especially the autodetection, and it works okay.
Please review and apply for 2.6.24-rc5 - thanks!

 drivers/infiniband/hw/ehca/ehca_main.c |   16 
 drivers/infiniband/hw/ehca/hcp_if.c|   28 +++-
 2 files changed, 27 insertions(+), 17 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index 90d4334..8f33d06 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -43,6 +43,9 @@
 #ifdef CONFIG_PPC_64K_PAGES
 #include 
 #endif
+
+#include 
+
 #include "ehca_classes.h"
 #include "ehca_iverbs.h"
 #include "ehca_mrmw.h"
@@ -66,6 +69,7 @@ int ehca_poll_all_eqs  = 1;
 int ehca_static_rate   = -1;
 int ehca_scaling_code  = 0;
 int ehca_mr_largepage  = 1;
+int ehca_lock_hcalls   = -1;
 
 module_param_named(open_aqp1, ehca_open_aqp1, int, S_IRUGO);
 module_param_named(debug_level,   ehca_debug_level,   int, S_IRUGO);
@@ -77,6 +81,7 @@ module_param_named(poll_all_eqs,  ehca_poll_all_eqs,  int, 
S_IRUGO);
 module_param_named(static_rate,   ehca_static_rate,   int, S_IRUGO);
 module_param_named(scaling_code,  ehca_scaling_code,  int, S_IRUGO);
 module_param_named(mr_largepage,  ehca_mr_largepage,  int, S_IRUGO);
+module_param_named(lock_hcalls,   ehca_lock_hcalls,   bool, S_IRUGO);
 
 MODULE_PARM_DESC(open_aqp1,
 "AQP1 on startup (0: no (default), 1: yes)");
@@ -102,6 +107,9 @@ MODULE_PARM_DESC(scaling_code,
 MODULE_PARM_DESC(mr_largepage,
 "use large page for MR (0: use PAGE_SIZE (default), "
 "1: use large page depending on MR size");
+MODULE_PARM_DESC(lock_hcalls,
+"serialize all hCalls made by the driver "
+"(default: autodetect)");
 
 DEFINE_RWLOCK(ehca_qp_idr_lock);
 DEFINE_RWLOCK(ehca_cq_idr_lock);
@@ -924,6 +932,14 @@ int __init ehca_module_init(void)
printk(KERN_INFO "eHCA Infiniband Device Driver "
   "(Version " HCAD_VERSION ")\n");
 
+   /* Autodetect hCall locking -- we can't read the firmware version
+* directly, but we know that starting with POWER6, all firmware
+* versions are good.
+*/
+   if (ehca_lock_hcalls == -1)
+   ehca_lock_hcalls = !(cur_cpu_spec->cpu_user_features
+& PPC_FEATURE_ARCH_2_05);
+
ret = ehca_create_comp_pool();
if (ret) {
ehca_gen_err("Cannot create comp pool.");
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c 
b/drivers/infiniband/hw/ehca/hcp_if.c
index c16a213..331b5e8 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -89,6 +89,7 @@
 #define HCALL9_REGS_FORMAT HCALL7_REGS_FORMAT " r11=%lx r12=%lx"
 
 static DEFINE_SPINLOCK(hcall_lock);
+extern int ehca_lock_hcalls;
 
 static u32 get_longbusy_msecs(int longbusy_rc)
 {
@@ -120,26 +121,21 @@ static long ehca_plpar_hcall_norets(unsigned long opcode,
unsigned long arg7)
 {
long ret;
-   int i, sleep_msecs, do_lock;
-   unsigned long flags;
+   int i, sleep_msecs;
+   unsigned long flags = 0;
 
ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
 
-   /* lock H_FREE_RESOURCE(MR) against itself and H_ALLOC_RESOURCE(MR) */
-   if ((opcode == H_FREE_RESOURCE) && (arg7 == 5)) {
-   arg7 = 0; /* better not upset firmware */
-   do_lock = 1;
-   }
-
for (i = 0; i < 5; i++) {
-   if (do_lock)
+   /* serialize hCalls to work around firmware issue */
+   if (ehca_lock_hcalls)
spin_lock_irqsave(&hcall_lock, flags);
 
ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
 arg5, arg6, arg7);
 
-   if (do_lock)
+   if (ehca_lock_hcalls)
spin_unlock_irqrestore(&hcall_lock, flags);
 
if (H_IS_LONG_BUSY(ret)) {
@@ -174,24 +170,22 @@ static long ehca_plpar_hcall9(unsigned long opcode,
  unsigned long arg9)
 {
long ret;
-   int i, sleep_msecs, do_lock;
+   int i, sleep_msecs;
unsigned long flags = 0;
 
ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_F

[PATCH] IB/ehca: Fix static rate if path faster than link

2007-11-28 Thread Joachim Fenkes
The formula would yield -1 for this, which is wrong in a bad way (max
throttling). Clamp to 0, which is the correct value.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---

This fixes another regression introduced in rc3.
Please review and apply for 2.6.24-rc4. Thanks!

 drivers/infiniband/hw/ehca/ehca_av.c |8 ++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_av.c 
b/drivers/infiniband/hw/ehca/ehca_av.c
index 453eb99..f7782c8 100644
--- a/drivers/infiniband/hw/ehca/ehca_av.c
+++ b/drivers/infiniband/hw/ehca/ehca_av.c
@@ -76,8 +76,12 @@ int ehca_calc_ipd(struct ehca_shca *shca, int port,
 
link = ib_width_enum_to_int(pa.active_width) * pa.active_speed;
 
-   /* IPD = round((link / path) - 1) */
-   *ipd = ((link + (path >> 1)) / path) - 1;
+   if (path >= link)
+   /* no need to throttle if path faster than link */
+   *ipd = 0;
+   else
+   /* IPD = round((link / path) - 1) */
+   *ipd = ((link + (path >> 1)) / path) - 1;
 
return 0;
 }
-- 
1.5.2



___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] IB/ehca: Fix static rate regression

2007-11-22 Thread Joachim Fenkes
Wrong choice of port number caused modify_qp() to fail -- fixed.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
Please apply this for 2.6.24-rc4 as it fixes a regression introduced in rc3.
Thanks!

 drivers/infiniband/hw/ehca/ehca_qp.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c 
b/drivers/infiniband/hw/ehca/ehca_qp.c
index 2e3e654..dd12668 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -1203,7 +1203,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
mqpcb->service_level = attr->ah_attr.sl;
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL, 1);
 
-   if (ehca_calc_ipd(shca, my_qp->init_attr.port_num,
+   if (ehca_calc_ipd(shca, mqpcb->prim_phys_port,
  attr->ah_attr.static_rate,
  &mqpcb->max_static_rate)) {
ret = -EINVAL;
@@ -1302,7 +1302,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
mqpcb->source_path_bits_al = attr->alt_ah_attr.src_path_bits;
mqpcb->service_level_al = attr->alt_ah_attr.sl;
 
-   if (ehca_calc_ipd(shca, my_qp->init_attr.port_num,
+   if (ehca_calc_ipd(shca, mqpcb->alt_phys_port,
  attr->alt_ah_attr.static_rate,
  &mqpcb->max_static_rate_al)) {
ret = -EINVAL;
-- 
1.5.2



___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 2/2] IB/ehca: Fix static rate calculation

2007-11-02 Thread Joachim Fenkes
The IPD formula was a little off and assumed a fixed physical link rate; fix
the formula and query the actual physical link rate, now that we can get it.
Also, refactor the calculation into a common function ehca_calc_ipd() and
use that instead of duplicating code.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_av.c  |   48 +++-
 drivers/infiniband/hw/ehca/ehca_classes.h |1 -
 drivers/infiniband/hw/ehca/ehca_iverbs.h  |3 ++
 drivers/infiniband/hw/ehca/ehca_main.c|3 --
 drivers/infiniband/hw/ehca/ehca_qp.c  |   29 +++--
 5 files changed, 54 insertions(+), 30 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_av.c 
b/drivers/infiniband/hw/ehca/ehca_av.c
index 97d1086..453eb99 100644
--- a/drivers/infiniband/hw/ehca/ehca_av.c
+++ b/drivers/infiniband/hw/ehca/ehca_av.c
@@ -50,6 +50,38 @@
 
 static struct kmem_cache *av_cache;
 
+int ehca_calc_ipd(struct ehca_shca *shca, int port,
+ enum ib_rate path_rate, u32 *ipd)
+{
+   int path = ib_rate_to_mult(path_rate);
+   int link, ret;
+   struct ib_port_attr pa;
+
+   if (path_rate == IB_RATE_PORT_CURRENT) {
+   *ipd = 0;
+   return 0;
+   }
+
+   if (unlikely(path < 0)) {
+   ehca_err(&shca->ib_device, "Invalid static rate! path_rate=%x",
+path_rate);
+   return -EINVAL;
+   }
+
+   ret = ehca_query_port(&shca->ib_device, port, &pa);
+   if (unlikely(ret < 0)) {
+   ehca_err(&shca->ib_device, "Failed to query port  ret=%i", ret);
+   return ret;
+   }
+
+   link = ib_width_enum_to_int(pa.active_width) * pa.active_speed;
+
+   /* IPD = round((link / path) - 1) */
+   *ipd = ((link + (path >> 1)) / path) - 1;
+
+   return 0;
+}
+
 struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
 {
int ret;
@@ -69,15 +101,13 @@ struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct 
ib_ah_attr *ah_attr)
av->av.slid_path_bits = ah_attr->src_path_bits;
 
if (ehca_static_rate < 0) {
-   int ah_mult = ib_rate_to_mult(ah_attr->static_rate);
-   int ehca_mult =
-   ib_rate_to_mult(shca->sport[ah_attr->port_num].rate );
-
-   if (ah_mult >= ehca_mult)
-   av->av.ipd = 0;
-   else
-   av->av.ipd = (ah_mult > 0) ?
-   ((ehca_mult - 1) / ah_mult) : 0;
+   u32 ipd;
+   if (ehca_calc_ipd(shca, ah_attr->port_num,
+ ah_attr->static_rate, &ipd)) {
+   ret = -EINVAL;
+   goto create_ah_exit1;
+   }
+   av->av.ipd = ipd;
} else
av->av.ipd = ehca_static_rate;
 
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h 
b/drivers/infiniband/hw/ehca/ehca_classes.h
index 2d660ae..87f12d4 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -95,7 +95,6 @@ struct ehca_sma_attr {
 struct ehca_sport {
struct ib_cq *ibcq_aqp1;
struct ib_qp *ibqp_aqp1;
-   enum ib_rate  rate;
enum ib_port_state port_state;
struct ehca_sma_attr saved_attr;
 };
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h 
b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index dce503b..5485799 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -189,6 +189,9 @@ int ehca_mmap(struct ib_ucontext *context, struct 
vm_area_struct *vma);
 
 void ehca_poll_eqs(unsigned long data);
 
+int ehca_calc_ipd(struct ehca_shca *shca, int port,
+ enum ib_rate path_rate, u32 *ipd);
+
 #ifdef CONFIG_PPC_64K_PAGES
 void *ehca_alloc_fw_ctrlblock(gfp_t flags);
 void ehca_free_fw_ctrlblock(void *ptr);
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index c6cd38c..90d4334 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -327,9 +327,6 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
shca->hw_level = ehca_hw_level;
ehca_gen_dbg(" ... hardware level=%x", shca->hw_level);
 
-   shca->sport[0].rate = IB_RATE_30_GBPS;
-   shca->sport[1].rate = IB_RATE_30_GBPS;
-
shca->hca_cap = rblock->hca_cap_indicators;
ehca_gen_dbg(" ... HCA capabilities:");
for (i = 0; i < ARRAY_SIZE(hca_cap_descr); i++)
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c 
b/drivers/infiniband/hw/ehca/ehca_qp.c
index de18264..2e3e654 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -1196,10 +1196,6 @

[PATCH 1/2] IB/ehca: Return physical link information in query_port()

2007-11-02 Thread Joachim Fenkes
Newer firmware versions return physical port information to the partition,
so hand that information to the consumer if it's present.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_hca.c |   20 ++--
 drivers/infiniband/hw/ehca/hipz_hw.h  |6 +-
 2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c 
b/drivers/infiniband/hw/ehca/ehca_hca.c
index 15806d1..5bd7b59 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -151,7 +151,6 @@ int ehca_query_port(struct ib_device *ibdev,
}
 
memset(props, 0, sizeof(struct ib_port_attr));
-   props->state = rblock->state;
 
switch (rblock->max_mtu) {
case 0x1:
@@ -188,11 +187,20 @@ int ehca_query_port(struct ib_device *ibdev,
props->subnet_timeout  = rblock->subnet_timeout;
props->init_type_reply = rblock->init_type_reply;
 
-   props->active_width= IB_WIDTH_12X;
-   props->active_speed= 0x1;
-
-   /* at the moment (logical) link state is always LINK_UP */
-   props->phys_state  = 0x5;
+   if (rblock->state && rblock->phys_width) {
+   props->phys_state  = rblock->phys_pstate;
+   props->state   = rblock->phys_state;
+   props->active_width= rblock->phys_width;
+   props->active_speed= rblock->phys_speed;
+   } else {
+   /* old firmware releases don't report physical
+* port info, so use default values
+*/
+   props->phys_state  = 5;
+   props->state   = rblock->state;
+   props->active_width= IB_WIDTH_12X;
+   props->active_speed= 0x1;
+   }
 
 query_port1:
ehca_free_fw_ctrlblock(rblock);
diff --git a/drivers/infiniband/hw/ehca/hipz_hw.h 
b/drivers/infiniband/hw/ehca/hipz_hw.h
index d9739e5..485b840 100644
--- a/drivers/infiniband/hw/ehca/hipz_hw.h
+++ b/drivers/infiniband/hw/ehca/hipz_hw.h
@@ -402,7 +402,11 @@ struct hipz_query_port {
u64 max_msg_sz;
u32 max_mtu;
u32 vl_cap;
-   u8  reserved2[1900];
+   u32 phys_pstate;
+   u32 phys_state;
+   u32 phys_speed;
+   u32 phys_width;
+   u8  reserved2[1884];
u64 guid_entries[255];
 } __attribute__ ((packed));
 
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 0/2] IB/ehca: Return physical link information, fix static rate calculation

2007-11-02 Thread Joachim Fenkes
This patchset will fix static rate calculation for the new link speeds
supported by eHCA2. Also, it enables query_port() to return physical link
information instead of constant values, which is needed for the static rate
fix.

[1/2] makes query_port() return actual physical link info where supported
[2/2] fixes static rate calculation based on that info

The patches will apply, in order, on top of Roland's for-2.6.24 branch.
Please review them and apply for 2.6.24-rc2 if you think they're okay.

Thanks and regards,
  Joachim

-- 
Joachim Fenkes  --  eHCA Linux Driver Developer and Hardware Tamer
IBM Deutschland Entwicklung GmbH  --  Dept. 3627 (I/O Firmware Dev. 2)
Schoenaicher Strasse 220  --  71032 Boeblingen  --  Germany
eMail: [EMAIL PROTECTED]

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 4/5] ibmebus: Move to of_device and of_platform_driver, match eHCA and eHEA drivers

2007-10-17 Thread Joachim Fenkes
On Tuesday 16 October 2007 17:27, Stephen Rothwell wrote:

> One small change - I intend to remove the name and owner fields from
> struct of_platform_driver, so you should not bother initialising the name
> field and just initialise the name field of the embedded struct
> device_driver instead.  This, of course, means that you don't need
> 
>   drv->driver.name = drv->name;
> 
> in ibmebus_register_driver.

I'd prefer to let this line stay in place until you actually make your
change, to keep the data structures consistent as long as the name field is
present. You could remove it in your patch then.

Regards,
  Joachim

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 5/5] IB/ehca: Enable large page MRs by default

2007-10-16 Thread Joachim Fenkes
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_main.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index d477dc3..2f51c13 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -65,7 +65,7 @@ int ehca_port_act_time = 30;
 int ehca_poll_all_eqs  = 1;
 int ehca_static_rate   = -1;
 int ehca_scaling_code  = 0;
-int ehca_mr_largepage  = 0;
+int ehca_mr_largepage  = 1;
 
 module_param_named(open_aqp1, ehca_open_aqp1, int, S_IRUGO);
 module_param_named(debug_level,   ehca_debug_level,   int, S_IRUGO);
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 4/5] IB/ehca: Change meaning of hca_cap_mr_pgsize

2007-10-16 Thread Joachim Fenkes
ehca_shca.hca_cap_mr_pgsize now contains all supported page sizes ORed
together. This makes some checks easier to code and understand, plus we can
return this value verbatim in query_hca(), fixing a problem with SRP
(reported by Anton Blanchard -- thanks!).

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |1 -
 drivers/infiniband/hw/ehca/ehca_hca.c |1 +
 drivers/infiniband/hw/ehca/ehca_main.c|   18 -
 drivers/infiniband/hw/ehca/ehca_mrmw.c|   38 ++--
 4 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h 
b/drivers/infiniband/hw/ehca/ehca_classes.h
index 0f7a55d..365bc5d 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -323,7 +323,6 @@ extern int ehca_static_rate;
 extern int ehca_port_act_time;
 extern int ehca_use_hp_mr;
 extern int ehca_scaling_code;
-extern int ehca_mr_largepage;
 
 struct ipzu_queue_resp {
u32 qe_size;  /* queue entry size */
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c 
b/drivers/infiniband/hw/ehca/ehca_hca.c
index 4aa3ffa..15806d1 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -77,6 +77,7 @@ int ehca_query_device(struct ib_device *ibdev, struct 
ib_device_attr *props)
}
 
memset(props, 0, sizeof(struct ib_device_attr));
+   props->page_size_cap   = shca->hca_cap_mr_pgsize;
props->fw_ver  = rblock->hw_ver;
props->max_mr_size = rblock->max_mr_size;
props->vendor_id   = rblock->vendor_id >> 8;
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index 403467f..d477dc3 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -260,13 +260,20 @@ static struct cap_descr {
{ HCA_CAP_MINI_QP, "HCA_CAP_MINI_QP" },
 };
 
-int ehca_sense_attributes(struct ehca_shca *shca)
+static int ehca_sense_attributes(struct ehca_shca *shca)
 {
int i, ret = 0;
u64 h_ret;
struct hipz_query_hca *rblock;
struct hipz_query_port *port;
 
+   static const u32 pgsize_map[] = {
+   HCA_CAP_MR_PGSIZE_4K,  0x1000,
+   HCA_CAP_MR_PGSIZE_64K, 0x1,
+   HCA_CAP_MR_PGSIZE_1M,  0x10,
+   HCA_CAP_MR_PGSIZE_16M, 0x100,
+   };
+
rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!rblock) {
ehca_gen_err("Cannot allocate rblock memory.");
@@ -329,8 +336,15 @@ 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;
+   /* translate supported MR page sizes; always support 4K */
+   shca->hca_cap_mr_pgsize = EHCA_PAGESIZE;
+   if (ehca_mr_largepage) { /* support extra sizes only if enabled */
+   for (i = 0; i < ARRAY_SIZE(pgsize_map); i += 2)
+   if (rblock->memory_page_size_supported & pgsize_map[i])
+   shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
+   }
 
+   /* query max MTU from first port -- it's the same for all ports */
port = (struct hipz_query_port *)rblock;
h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port);
if (h_ret != H_SUCCESS) {
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c 
b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index b9a788c..bb97915 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -79,9 +79,7 @@ static u32 ehca_encode_hwpage_size(u32 pgsize)
 
 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;
+   return 1UL << ilog2(shca->hca_cap_mr_pgsize);
 }
 
 static struct ehca_mr *ehca_mr_new(void)
@@ -288,7 +286,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, 
u64 length,
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;
-   int ret;
+   int ret, page_shift;
u32 num_kpages;
u32 num_hwpages;
u64 hwpage_size;
@@ -343,19 +341,20 @@ 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);
/* select proper hw_pgsize */
-   if (ehca_mr_largepage &&
-   (shca->h

[PATCH 3/5] IB/ehca: Fix ehca_encode_hwpage_size() and alloc_fmr()

2007-10-16 Thread Joachim Fenkes
Simplify ehca_encode_hwpage_size(), fixing an infinite loop for pgsize == 0
in the process. Fix the bug in alloc_fmr() that triggered the loop.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_mrmw.c |   15 ---
 1 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c 
b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index 16c9efd..b9a788c 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -72,17 +72,9 @@ enum ehca_mr_pgsize {
 
 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;
+   int log = ilog2(pgsize);
+   WARN_ON(log < 12 || log > 24 || log & 3);
+   return (log - 12) / 4;
 }
 
 static u64 ehca_get_max_hwpage_size(struct ehca_shca *shca)
@@ -826,6 +818,7 @@ struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd,
 
/* register MR on HCA */
memset(&pginfo, 0, sizeof(pginfo));
+   pginfo.hwpage_size = hw_pgsize;
/*
 * pginfo.num_hwpages==0, ie register_rpages() will not be called
 * but deferred to map_phys_fmr()
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 2/5] IB/ehca: Fix masking error in {,re}reg_phys_mr()

2007-10-16 Thread Joachim Fenkes
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_mrmw.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c 
b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index da88738..16c9efd 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -259,7 +259,7 @@ struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd,
pginfo.u.phy.num_phys_buf = num_phys_buf;
pginfo.u.phy.phys_buf_array = phys_buf_array;
pginfo.next_hwpage =
-   ((u64)iova_start & ~(hw_pgsize - 1)) / hw_pgsize;
+   ((u64)iova_start & ~PAGE_MASK) / hw_pgsize;
 
ret = ehca_reg_mr(shca, e_mr, iova_start, size, mr_access_flags,
  e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
@@ -547,7 +547,7 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
pginfo.u.phy.num_phys_buf = num_phys_buf;
pginfo.u.phy.phys_buf_array = phys_buf_array;
pginfo.next_hwpage =
-   ((u64)iova_start & ~(hw_pgsize - 1)) / hw_pgsize;
+   ((u64)iova_start & ~PAGE_MASK) / hw_pgsize;
}
if (mr_rereg_mask & IB_MR_REREG_ACCESS)
new_acl = mr_access_flags;
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 1/5] IB/ehca: Supply QP token for SRQ base QPs

2007-10-16 Thread Joachim Fenkes
Because hardware reports the SRQ token in RWQEs of SRQ base QPs, supply the
base QP token as SRQ token, so we can properly find the SRQ base QP.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_qp.c |4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c 
b/drivers/infiniband/hw/ehca/ehca_qp.c
index e2bd62b..de18264 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -451,7 +451,6 @@ static struct ehca_qp *internal_create_qp(
has_srq = 1;
parms.ext_type = EQPT_SRQBASE;
parms.srq_qpn = my_srq->real_qp_num;
-   parms.srq_token = my_srq->token;
}
 
if (is_llqp && has_srq) {
@@ -583,6 +582,9 @@ static struct ehca_qp *internal_create_qp(
goto create_qp_exit1;
}
 
+   if (has_srq)
+   parms.srq_token = my_qp->token;
+
parms.servicetype = ibqptype2servicetype(qp_type);
if (parms.servicetype < 0) {
ret = -EINVAL;
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 0/5] IB/ehca: SRQ and MR/MW fixes

2007-10-16 Thread Joachim Fenkes
Here are some more fixes for the eHCA driver, fixing some problems we found
during internal system test.

[1/5] fixes the QP pointer determination for SRQ base QPs
[2/5] fixes a masking error in {,re}reg_phys_mr()
[3/5] fixes a bug in alloc_fmr() and simplifies some code
[4/5] refactors hca_cap_mr_pgsize and fixes a problem with ib_srp
[5/5] enables large page MRs by default

I built the patches on top of Roland's for-2.6.24 git branch. Please review
and queue them for 2.6.24-rc1 if you're okay with them. Thanks!

Cheers,
  Joachim

-- 
Joachim Fenkes  --  eHCA Linux Driver Developer and Hardware Tamer
IBM Deutschland Entwicklung GmbH  --  Dept. 3627 (I/O Firmware Dev. 2)
Schoenaicher Strasse 220  --  71032 Boeblingen  --  Germany
eMail: [EMAIL PROTECTED]





___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 4/5] ibmebus: Move to of_device and of_platform_driver, match eHCA and eHEA drivers

2007-10-16 Thread Joachim Fenkes
On Tuesday 09 October 2007 10:21, Jan-Bernd Themann wrote:
> Roland Dreier <[EMAIL PROTECTED]> wrote on 03.10.2007 20:05:44:
> >  > > Replace struct ibmebus_dev and struct ibmebus_driver with struct 
of_device
> >  > > and struct of_platform_driver, respectively. Match the external 
ibmebus
> >  > > interface and drivers using it.
> >  > >
> >  > > Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
> >  >
> >  > This is somewhat difficult as this patch touches files that are the
> >  > responsibility of three different maintainers. �Is it possible to
> >  > split the patch into three, one for each maintainer (possibly by
> >  > keeping both old and new interfaces around for a little while)?
> >  > 
> >  > If not, then you need to get an Acked-by and an agreement that this
> >  > change can go via the powerpc.git tree from Roland Dreier and Jeff
> >  > Garzik.
> >
> > I don't see anything objectionable in the infiniband parts of the
> > patch -- I don't have any way to test the changes but it all looks
> > like a straightforward conversion to a new platform API.  So:
> >
> > Acked-by: Roland Dreier <[EMAIL PROTECTED]>
> >
> >  - R.
>
> Looks good from eHEA driver perspective.
>
> Acked-by: Jan-Bernd Themann <[EMAIL PROTECTED]>

Jeff, do you have any objections against this patch going into the kernel
via Paul's powerpc.git tree? It touches only a few lines of ehea which are
specific to the bus interface changes.

You can see the full patch here:
  http://patchwork.ozlabs.org/linuxppc/patch?id=13750

If you have no objections, please ack the patch so Paul can include it.

Thanks and regards,
  Joachim

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

[PATCH 5/5] ibmebus: More speaking error return code in ibmebus_store_probe()

2007-09-26 Thread Joachim Fenkes
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 arch/powerpc/kernel/ibmebus.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index c1e2963..0bd186c 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -268,10 +268,10 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
return -ENOMEM;
 
if (bus_find_device(&ibmebus_bus_type, NULL, path,
-ibmebus_match_path)) {
+   ibmebus_match_path)) {
printk(KERN_WARNING "%s: %s has already been probed\n",
   __FUNCTION__, path);
-   rc = -EINVAL;
+   rc = -EEXIST;
goto out;
}
 
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 4/5] ibmebus: Move to of_device and of_platform_driver, match eHCA and eHEA drivers

2007-09-26 Thread Joachim Fenkes
Replace struct ibmebus_dev and struct ibmebus_driver with struct of_device
and struct of_platform_driver, respectively. Match the external ibmebus
interface and drivers using it.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |2 +-
 drivers/net/ehea/ehea.h   |2 +-
 include/asm-powerpc/ibmebus.h |   38 +++
 arch/powerpc/kernel/ibmebus.c |   28 ++-
 drivers/infiniband/hw/ehca/ehca_eq.c  |6 +-
 drivers/infiniband/hw/ehca/ehca_main.c|   32 ++--
 drivers/net/ehea/ehea_main.c  |   72 ++--
 7 files changed, 79 insertions(+), 101 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h 
b/drivers/infiniband/hw/ehca/ehca_classes.h
index c2edd4c..8ca4dd4 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -106,7 +106,7 @@ struct ehca_sport {
 
 struct ehca_shca {
struct ib_device ib_device;
-   struct ibmebus_dev *ibmebus_dev;
+   struct of_device *ofdev;
u8 num_ports;
int hw_level;
struct list_head shca_list;
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 8d58be5..830a66a 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -382,7 +382,7 @@ struct ehea_port_res {
 #define EHEA_MAX_PORTS 16
 struct ehea_adapter {
u64 handle;
-   struct ibmebus_dev *ebus_dev;
+   struct of_device *ofdev;
struct ehea_port *port[EHEA_MAX_PORTS];
struct ehea_eq *neq;   /* notification event queue */
struct workqueue_struct *ehea_wq;
diff --git a/include/asm-powerpc/ibmebus.h b/include/asm-powerpc/ibmebus.h
index 87d396e..1a9d9ae 100644
--- a/include/asm-powerpc/ibmebus.h
+++ b/include/asm-powerpc/ibmebus.h
@@ -43,42 +43,18 @@
 #include 
 #include 
 #include 
-#include 
+#include 
+#include 
 
 extern struct bus_type ibmebus_bus_type;
 
-struct ibmebus_dev {
-   struct of_device ofdev;
-};
+int ibmebus_register_driver(struct of_platform_driver *drv);
+void ibmebus_unregister_driver(struct of_platform_driver *drv);
 
-struct ibmebus_driver {
-   char *name;
-   struct of_device_id *id_table;
-   int (*probe) (struct ibmebus_dev *dev, const struct of_device_id *id);
-   int (*remove) (struct ibmebus_dev *dev);
-   struct device_driver driver;
-};
-
-int ibmebus_register_driver(struct ibmebus_driver *drv);
-void ibmebus_unregister_driver(struct ibmebus_driver *drv);
-
-int ibmebus_request_irq(struct ibmebus_dev *dev,
-   u32 ist,
-   irq_handler_t handler,
-   unsigned long irq_flags, const char * devname,
+int ibmebus_request_irq(u32 ist, irq_handler_t handler,
+   unsigned long irq_flags, const char *devname,
void *dev_id);
-void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id);
-
-static inline struct ibmebus_driver *to_ibmebus_driver(struct device_driver 
*drv)
-{
-   return container_of(drv, struct ibmebus_driver, driver);
-}
-
-static inline struct ibmebus_dev *to_ibmebus_dev(struct device *dev)
-{
-   return container_of(dev, struct ibmebus_dev, ofdev.dev);
-}
-
+void ibmebus_free_irq(u32 ist, void *dev_id);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_IBMEBUS_H */
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 43d4764..c1e2963 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -192,21 +192,26 @@ static int ibmebus_create_devices(const struct 
of_device_id *matches)
return ret;
 }
 
-int ibmebus_register_driver(struct ibmebus_driver *drv)
+int ibmebus_register_driver(struct of_platform_driver *drv)
 {
-   return 0;
+   /* If the driver uses devices that ibmebus doesn't know, add them */
+   ibmebus_create_devices(drv->match_table);
+
+   drv->driver.name   = drv->name;
+   drv->driver.bus= &ibmebus_bus_type;
+
+   return driver_register(&drv->driver);
 }
 EXPORT_SYMBOL(ibmebus_register_driver);
 
-void ibmebus_unregister_driver(struct ibmebus_driver *drv)
+void ibmebus_unregister_driver(struct of_platform_driver *drv)
 {
+   driver_unregister(&drv->driver);
 }
 EXPORT_SYMBOL(ibmebus_unregister_driver);
 
-int ibmebus_request_irq(struct ibmebus_dev *dev,
-   u32 ist,
-   irq_handler_t handler,
-   unsigned long irq_flags, const char * devname,
+int ibmebus_request_irq(u32 ist, irq_handler_t handler,
+   unsigned long irq_flags, const char *devname,
void *dev_id)
 {
unsigned int irq = irq_create_mapping(NULL, ist);
@@ -214,12 +219,11 @@ int ibmebus_request_irq(struct ibmebus_dev *dev,
if (irq == NO_IRQ)
return -EINVAL;

[PATCH 3/5] ibmebus: Add device creation and bus probing based on of_device

2007-09-26 Thread Joachim Fenkes
The devtree root is now searched for devices matching a built-in whitelist
during boot, so these devices appear on the bus from the beginning. It is
still possible to manually add/remove devices to/from the bus by using the
probe/remove sysfs interface. Also, when a device driver registers itself,
the devtree is matched against its matchlist.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 arch/powerpc/kernel/ibmebus.c |  100 +---
 1 files changed, 82 insertions(+), 18 deletions(-)

diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index cc80f84..43d4764 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -51,6 +51,13 @@ static struct device ibmebus_bus_device = { /* fake "parent" 
device */
 
 struct bus_type ibmebus_bus_type;
 
+/* These devices will automatically be added to the bus during init */
+static struct of_device_id builtin_matches[] = {
+   { .compatible = "IBM,lhca" },
+   { .compatible = "IBM,lhea" },
+   {},
+};
+
 static void *ibmebus_alloc_coherent(struct device *dev,
size_t size,
dma_addr_t *dma_handle,
@@ -124,6 +131,67 @@ static struct dma_mapping_ops ibmebus_dma_ops = {
.dma_supported  = ibmebus_dma_supported,
 };
 
+static int ibmebus_match_path(struct device *dev, void *data)
+{
+   struct device_node *dn = to_of_device(dev)->node;
+   return (dn->full_name &&
+   (strcasecmp((char *)data, dn->full_name) == 0));
+}
+
+static int ibmebus_match_node(struct device *dev, void *data)
+{
+   return to_of_device(dev)->node == data;
+}
+
+static int ibmebus_create_device(struct device_node *dn)
+{
+   struct of_device *dev;
+   int ret;
+
+   dev = of_device_alloc(dn, NULL, &ibmebus_bus_device);
+   if (!dev)
+   return -ENOMEM;
+
+   dev->dev.bus = &ibmebus_bus_type;
+   dev->dev.archdata.dma_ops = &ibmebus_dma_ops;
+
+   ret = of_device_register(dev);
+   if (ret) {
+   of_device_free(dev);
+   return ret;
+   }
+
+   return 0;
+}
+
+static int ibmebus_create_devices(const struct of_device_id *matches)
+{
+   struct device_node *root, *child;
+   int ret = 0;
+
+   root = of_find_node_by_path("/");
+
+   for (child = NULL; (child = of_get_next_child(root, child)); ) {
+   if (!of_match_node(matches, child))
+   continue;
+
+   if (bus_find_device(&ibmebus_bus_type, NULL, child,
+   ibmebus_match_node))
+   continue;
+
+   ret = ibmebus_create_device(child);
+   if (ret) {
+   printk(KERN_ERR "%s: failed to create device (%i)",
+  __FUNCTION__, ret);
+   of_node_put(child);
+   break;
+   }
+   }
+
+   of_node_put(root);
+   return ret;
+}
+
 int ibmebus_register_driver(struct ibmebus_driver *drv)
 {
return 0;
@@ -172,18 +240,6 @@ static struct device_attribute ibmebus_dev_attrs[] = {
__ATTR_NULL
 };
 
-static int ibmebus_match_path(struct device *dev, void *data)
-{
-   int rc;
-   struct device_node *dn =
-   of_node_get(to_ibmebus_dev(dev)->ofdev.node);
-
-   rc = (dn->full_name && (strcasecmp((char*)data, dn->full_name) == 0));
-
-   of_node_put(dn);
-   return rc;
-}
-
 static char *ibmebus_chomp(const char *in, size_t count)
 {
char *out = (char*)kmalloc(count + 1, GFP_KERNEL);
@@ -202,9 +258,8 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
   const char *buf, size_t count)
 {
struct device_node *dn = NULL;
-   struct ibmebus_dev *dev;
char *path;
-   ssize_t rc;
+   ssize_t rc = 0;
 
path = ibmebus_chomp(buf, count);
if (!path)
@@ -219,9 +274,8 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
}
 
if ((dn = of_find_node_by_path(path))) {
-/* dev = ibmebus_register_device_node(dn); */
+   rc = ibmebus_create_device(dn);
of_node_put(dn);
-   rc = IS_ERR(dev) ? PTR_ERR(dev) : count;
} else {
printk(KERN_WARNING "%s: no such device node: %s\n",
   __FUNCTION__, path);
@@ -230,7 +284,9 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
 
 out:
kfree(path);
-   return rc;
+   if (rc)
+   return rc;
+   return count;
 }
 
 static ssize_t ibmebus_store_remove(struct bus_type *bus,
@@ -245,7 +301,7 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus,
 
if ((dev = bus_find_device(&ibmeb

[PATCH 2/5] ibmebus: Remove bus match/probe/remove functions

2007-09-26 Thread Joachim Fenkes
Remove old code that will be replaced by rewritten and shorter functions in
the next patch. Keep struct ibmebus_dev and struct ibmebus_driver for now,
but replace ibmebus_{,un}register_driver() by dummy functions. This way, the
kernel will still compile and run during the transition and git bisect will
be happy.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 arch/powerpc/kernel/ibmebus.c |  199 ++---
 1 files changed, 6 insertions(+), 193 deletions(-)

diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index d6a38cd..cc80f84 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -41,6 +41,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -123,183 +124,14 @@ static struct dma_mapping_ops ibmebus_dma_ops = {
.dma_supported  = ibmebus_dma_supported,
 };
 
-static int ibmebus_bus_probe(struct device *dev)
-{
-   struct ibmebus_dev *ibmebusdev= to_ibmebus_dev(dev);
-   struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
-   const struct of_device_id *id;
-   int error = -ENODEV;
-
-   if (!ibmebusdrv->probe)
-   return error;
-
-   id = of_match_device(ibmebusdrv->id_table, &ibmebusdev->ofdev);
-   if (id) {
-   error = ibmebusdrv->probe(ibmebusdev, id);
-   }
-
-   return error;
-}
-
-static int ibmebus_bus_remove(struct device *dev)
-{
-   struct ibmebus_dev *ibmebusdev= to_ibmebus_dev(dev);
-   struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
-
-   if (ibmebusdrv->remove) {
-   return ibmebusdrv->remove(ibmebusdev);
-   }
-
-   return 0;
-}
-
-static void __devinit ibmebus_dev_release(struct device *dev)
-{
-   of_node_put(to_ibmebus_dev(dev)->ofdev.node);
-   kfree(to_ibmebus_dev(dev));
-}
-
-static int __devinit ibmebus_register_device_common(
-   struct ibmebus_dev *dev, const char *name)
-{
-   int err = 0;
-
-   dev->ofdev.dev.parent  = &ibmebus_bus_device;
-   dev->ofdev.dev.bus = &ibmebus_bus_type;
-   dev->ofdev.dev.release = ibmebus_dev_release;
-
-   dev->ofdev.dev.archdata.of_node = dev->ofdev.node;
-   dev->ofdev.dev.archdata.dma_ops = &ibmebus_dma_ops;
-   dev->ofdev.dev.archdata.numa_node = of_node_to_nid(dev->ofdev.node);
-
-   /* An ibmebusdev is based on a of_device. We have to change the
-* bus type to use our own DMA mapping operations.
-*/
-   if ((err = of_device_register(&dev->ofdev)) != 0) {
-   printk(KERN_ERR "%s: failed to register device (%d).\n",
-  __FUNCTION__, err);
-   return -ENODEV;
-   }
-
-   return 0;
-}
-
-static struct ibmebus_dev* __devinit ibmebus_register_device_node(
-   struct device_node *dn)
-{
-   struct ibmebus_dev *dev;
-   int i, len, bus_len;
-
-   dev = kzalloc(sizeof(struct ibmebus_dev), GFP_KERNEL);
-   if (!dev)
-   return ERR_PTR(-ENOMEM);
-
-   dev->ofdev.node = of_node_get(dn);
-
-   len = strlen(dn->full_name + 1);
-   bus_len = min(len, BUS_ID_SIZE - 1);
-   memcpy(dev->ofdev.dev.bus_id, dn->full_name + 1
-  + (len - bus_len), bus_len);
-   for (i = 0; i < bus_len; i++)
-   if (dev->ofdev.dev.bus_id[i] == '/')
-   dev->ofdev.dev.bus_id[i] = '_';
-
-   /* Register with generic device framework. */
-   if (ibmebus_register_device_common(dev, dn->name) != 0) {
-   kfree(dev);
-   return ERR_PTR(-ENODEV);
-   }
-
-   return dev;
-}
-
-static void ibmebus_probe_of_nodes(char* name)
-{
-   struct device_node *dn = NULL;
-
-   while ((dn = of_find_node_by_name(dn, name))) {
-   if (IS_ERR(ibmebus_register_device_node(dn))) {
-   of_node_put(dn);
-   return;
-   }
-   }
-
-   of_node_put(dn);
-
-   return;
-}
-
-static void ibmebus_add_devices_by_id(struct of_device_id *idt)
-{
-   while (strlen(idt->name) > 0) {
-   ibmebus_probe_of_nodes(idt->name);
-   idt++;
-   }
-
-   return;
-}
-
-static int ibmebus_match_name(struct device *dev, void *data)
-{
-   const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
-   const char *name;
-
-   name = of_get_property(ebus_dev->ofdev.node, "name", NULL);
-
-   if (name && (strcmp(data, name) == 0))
-   return 1;
-
-   return 0;
-}
-
-static int ibmebus_unregister_device(struct device *dev)
-{
-   of_device_unregister(to_of_device(dev));
-
-   return 0;
-}
-
-static void ibmebus_remove_devices_by_id(struct of_device_id *idt)
-{
-   struct device *dev;
-
-   w

[PATCH 1/5] PowerPC: Move of_device allocation into of_device.[ch]

2007-09-26 Thread Joachim Fenkes
Extract generic of_device allocation code from of_platform_device_create()
and move it into of_device.[ch], called of_device_alloc(). Also, there's now
of_device_free() which puts the device node.

This way, bus drivers that build on of_platform (like ibmebus will) can
build upon this code instead of reinventing the wheel.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 include/asm-powerpc/of_device.h   |4 ++
 include/linux/of_device.h |5 ++
 arch/powerpc/kernel/of_device.c   |   80 +
 arch/powerpc/kernel/of_platform.c |   70 +---
 4 files changed, 91 insertions(+), 68 deletions(-)

diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h
index ec2a8a2..9ab469d 100644
--- a/include/asm-powerpc/of_device.h
+++ b/include/asm-powerpc/of_device.h
@@ -17,6 +17,10 @@ struct of_device
struct device   dev;/* Generic device interface */
 };
 
+extern struct of_device *of_device_alloc(struct device_node *np,
+const char *bus_id,
+struct device *parent);
+
 extern ssize_t of_device_get_modalias(struct of_device *ofdev,
char *str, ssize_t len);
 extern int of_device_uevent(struct device *dev,
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 91bf84b..212bffb 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -22,5 +22,10 @@ extern int of_device_register(struct of_device *ofdev);
 extern void of_device_unregister(struct of_device *ofdev);
 extern void of_release_dev(struct device *dev);
 
+static inline void of_device_free(struct of_device *dev)
+{
+   of_release_dev(&dev->dev);
+}
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_OF_DEVICE_H */
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
index 89b911e..ecb8b0e 100644
--- a/arch/powerpc/kernel/of_device.c
+++ b/arch/powerpc/kernel/of_device.c
@@ -7,8 +7,88 @@
 #include 
 
 #include 
+#include 
 #include 
 
+static void of_device_make_bus_id(struct of_device *dev)
+{
+   static atomic_t bus_no_reg_magic;
+   struct device_node *node = dev->node;
+   char *name = dev->dev.bus_id;
+   const u32 *reg;
+   u64 addr;
+   int magic;
+
+   /*
+* If it's a DCR based device, use 'd' for native DCRs
+* and 'D' for MMIO DCRs.
+*/
+#ifdef CONFIG_PPC_DCR
+   reg = of_get_property(node, "dcr-reg", NULL);
+   if (reg) {
+#ifdef CONFIG_PPC_DCR_NATIVE
+   snprintf(name, BUS_ID_SIZE, "d%x.%s",
+*reg, node->name);
+#else /* CONFIG_PPC_DCR_NATIVE */
+   addr = of_translate_dcr_address(node, *reg, NULL);
+   if (addr != OF_BAD_ADDR) {
+   snprintf(name, BUS_ID_SIZE,
+"D%llx.%s", (unsigned long long)addr,
+node->name);
+   return;
+   }
+#endif /* !CONFIG_PPC_DCR_NATIVE */
+   }
+#endif /* CONFIG_PPC_DCR */
+
+   /*
+* For MMIO, get the physical address
+*/
+   reg = of_get_property(node, "reg", NULL);
+   if (reg) {
+   addr = of_translate_address(node, reg);
+   if (addr != OF_BAD_ADDR) {
+   snprintf(name, BUS_ID_SIZE,
+"%llx.%s", (unsigned long long)addr,
+node->name);
+   return;
+   }
+   }
+
+   /*
+* No BusID, use the node name and add a globally incremented
+* counter (and pray...)
+*/
+   magic = atomic_add_return(1, &bus_no_reg_magic);
+   snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1);
+}
+
+struct of_device *of_device_alloc(struct device_node *np,
+ const char *bus_id,
+ struct device *parent)
+{
+   struct of_device *dev;
+
+   dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+   if (!dev)
+   return NULL;
+
+   dev->node = of_node_get(np);
+   dev->dev.dma_mask = &dev->dma_mask;
+   dev->dev.parent = parent;
+   dev->dev.release = of_release_dev;
+   dev->dev.archdata.of_node = np;
+   dev->dev.archdata.numa_node = of_node_to_nid(np);
+
+   if (bus_id)
+   strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+   else
+   of_device_make_bus_id(dev);
+
+   return dev;
+}
+EXPORT_SYMBOL(of_device_alloc);
+
 ssize_t of_device_get_modalias(struct of_device *ofdev,
char *str, ssize_t len)
 {
diff --git a/arch/powerpc/kernel/of_platform.c 
b/arch/powerpc/kernel/of_platform.c
index f7

[PATCH 0/5] [REPOST] PowerPC: ibmebus refactoring and fixes

2007-09-26 Thread Joachim Fenkes
This patchset will merge the ibmebus and of_platform bus drivers by basing a
lot of ibmebus functionality on of_platform code and adding the features
specific to ibmebus on top of that.

This is a repost of my previous patchset incorporating Arnd's comments.

I split the actual ibmebus rework into three patches (2/5-4/5) for easier
readability. The kernel will compile during the intermediate states, and
ibmebus will not crash, but not work either.

As a side-effect of patch 3/5, a problem with bus_id collisions in case of
two devices sharing the same location code is resolved -- the bus_id is now
determined differently.

[1/5] moves of_device allocation into of_device.[ch]
[2/5] removes the old bus match/probe/remove functions
[3/5] adds device creation and bus probing based on of_device
[4/5] finally moves to of_device and of_platform_driver by changing
  ibmebus.h and matching the eHCA and eHEA drivers
[5/5] just changes a nit in ibmebus_store_probe()

These patches should apply cleanly, in order, against 2.6.23-rc5 and against
Linus' git. Please review and comment them, and queue them up for 2.6.24 if
you think they're okay.

Thanks and regards,
  Joachim


 arch/powerpc/kernel/ibmebus.c |  267 -
 arch/powerpc/kernel/of_device.c   |   80 +
 arch/powerpc/kernel/of_platform.c |   70 +
 drivers/infiniband/hw/ehca/ehca_classes.h |2 +-
 drivers/infiniband/hw/ehca/ehca_eq.c  |6 +-
 drivers/infiniband/hw/ehca/ehca_main.c|   32 ++--
 drivers/net/ehea/ehea.h   |2 +-
 drivers/net/ehea/ehea_main.c  |   72 
 include/asm-powerpc/ibmebus.h |   38 +
 include/asm-powerpc/of_device.h   |4 +
 include/linux/of_device.h |5 +
 11 files changed, 228 insertions(+), 350 deletions(-)

-- 
Joachim Fenkes  --  eHCA Linux Driver Developer and Hardware Tamer
IBM Deutschland Entwicklung GmbH  --  Dept. 3627 (I/O Firmware Dev. 2)
Schoenaicher Strasse 220  --  71032 Boeblingen  --  Germany
eMail: [EMAIL PROTECTED]


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 1/5] PowerPC: Move of_device allocation into of_device.[ch]

2007-09-26 Thread Joachim Fenkes
Arnd Bergmann <[EMAIL PROTECTED]> wrote on 25.09.2007 16:27:57:

> The patch looks good to me, especially since you did exactly what I
> suggested ;-)

Yes, our discussions were very productive. Thanks and sorry I forgot to 
mention your input.
 
> Maybe the description should have another sentence in it about what
> the change is good for. You have that in the 0/5 mail, but that does
> not go into the changelog, so the information gets lost in the process.

Can do. New patch coming right up!

Joachim
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 2/5] ibmebus: Remove bus match/probe/remove functions

2007-09-26 Thread Joachim Fenkes
Arnd Bergmann <[EMAIL PROTECTED]> wrote on 25.09.2007 16:29:51:

> The description makes it sound like a git-bisect would get broken
> by this patch, which should never happen. If the patch indeed
> ends up with a broken kernel, it would be better to merge it with
> the later patch that fixes the code again.

I took extra care to prevent just that from happening. ibmebus will simply 
be disabled during the transition (because of {un,}register_driver being 
empty dummies), but the kernel builds and boots without problems. So 
unless you're trying to find an ibmebus-based problem, git bisect will be 
fine. I'll repost 2/5 with an updated description.

I split the ibmebus rework into three patches because the merged patch was 
impossible to read. Makes reviewing easier.

Joachim
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 3/5] ibmebus: Add device creation and bus probing based on of_device

2007-09-26 Thread Joachim Fenkes
> > +/* These devices will automatically be added to the bus during init 
*/
> > +static struct of_device_id builtin_matches[] = {
> > +   { .name = "lhca" },
> > +   { .compatible = "IBM,lhca" },
> > +   { .name = "lhea" },
> > +   { .compatible = "IBM,lhea" },
> > +   {},
> > +};
> > +
> 
> Hmm, do you have devices that only have the matching name property
> but not the compatible property? If not, I'd suggest only looking
> for compatible, so you have less chance of false positives.

If a device that's not an lhca is called "lhca", that's its own fault, i 
guess ;) But i concur that looking for the compatible property will 
probably suffice.
 
> > +static int ibmebus_create_device(struct device_node *dn)
> > [...]
> 
> nice!

Thanks.
 
> > -  rc = IS_ERR(dev) ? PTR_ERR(dev) : count;
> > +  rc = rc ? rc : count;
> 
> the last line looks a bit silly. Maybe instead do
> 
>   rc = ibmebus_create_device(dn);
> of_node_put(dn);
>}
> 
>kfree(path);
>if (rc)
>   return rc;
>return count;
> }

More code lines? ;) But yes, that looks more like "standard kernel 
pattern" - I'll change that.

Joachim
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 4/5] ibmebus: Move to of_device and of_platform_driver, match eHCA and eHEA drivers

2007-09-26 Thread Joachim Fenkes
Arnd Bergmann <[EMAIL PROTECTED]> wrote on 25.09.2007 16:42:40:

> This is missing a description,

The description is "ibmebus: Move to of_device and of_platform_driver, 
match eHCA and eHEA drivers" -- I thought that should be enough since the 
patch is rather straightforward. I can add a more detailed description, 
though. Revised patch will follow.

> but the patch looks good.

Thanks =)

Joachim
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 5/5] ibmebus: More speaking error return code in ibmebus_store_probe()

2007-09-25 Thread Joachim Fenkes
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 arch/powerpc/kernel/ibmebus.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 379472f..8c08a98 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -270,10 +270,10 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
return -ENOMEM;
 
if (bus_find_device(&ibmebus_bus_type, NULL, path,
-ibmebus_match_path)) {
+   ibmebus_match_path)) {
printk(KERN_WARNING "%s: %s has already been probed\n",
   __FUNCTION__, path);
-   rc = -EINVAL;
+   rc = -EEXIST;
goto out;
}
 
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 4/5] ibmebus: Move to of_device and of_platform_driver, match eHCA and eHEA drivers

2007-09-25 Thread Joachim Fenkes
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |2 +-
 drivers/net/ehea/ehea.h   |2 +-
 include/asm-powerpc/ibmebus.h |   38 +++
 arch/powerpc/kernel/ibmebus.c |   28 ++-
 drivers/infiniband/hw/ehca/ehca_eq.c  |6 +-
 drivers/infiniband/hw/ehca/ehca_main.c|   32 ++--
 drivers/net/ehea/ehea_main.c  |   72 ++--
 7 files changed, 79 insertions(+), 101 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h 
b/drivers/infiniband/hw/ehca/ehca_classes.h
index c2edd4c..8ca4dd4 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -106,7 +106,7 @@ struct ehca_sport {
 
 struct ehca_shca {
struct ib_device ib_device;
-   struct ibmebus_dev *ibmebus_dev;
+   struct of_device *ofdev;
u8 num_ports;
int hw_level;
struct list_head shca_list;
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 8d58be5..830a66a 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -382,7 +382,7 @@ struct ehea_port_res {
 #define EHEA_MAX_PORTS 16
 struct ehea_adapter {
u64 handle;
-   struct ibmebus_dev *ebus_dev;
+   struct of_device *ofdev;
struct ehea_port *port[EHEA_MAX_PORTS];
struct ehea_eq *neq;   /* notification event queue */
struct workqueue_struct *ehea_wq;
diff --git a/include/asm-powerpc/ibmebus.h b/include/asm-powerpc/ibmebus.h
index 87d396e..1a9d9ae 100644
--- a/include/asm-powerpc/ibmebus.h
+++ b/include/asm-powerpc/ibmebus.h
@@ -43,42 +43,18 @@
 #include 
 #include 
 #include 
-#include 
+#include 
+#include 
 
 extern struct bus_type ibmebus_bus_type;
 
-struct ibmebus_dev {
-   struct of_device ofdev;
-};
+int ibmebus_register_driver(struct of_platform_driver *drv);
+void ibmebus_unregister_driver(struct of_platform_driver *drv);
 
-struct ibmebus_driver {
-   char *name;
-   struct of_device_id *id_table;
-   int (*probe) (struct ibmebus_dev *dev, const struct of_device_id *id);
-   int (*remove) (struct ibmebus_dev *dev);
-   struct device_driver driver;
-};
-
-int ibmebus_register_driver(struct ibmebus_driver *drv);
-void ibmebus_unregister_driver(struct ibmebus_driver *drv);
-
-int ibmebus_request_irq(struct ibmebus_dev *dev,
-   u32 ist,
-   irq_handler_t handler,
-   unsigned long irq_flags, const char * devname,
+int ibmebus_request_irq(u32 ist, irq_handler_t handler,
+   unsigned long irq_flags, const char *devname,
void *dev_id);
-void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id);
-
-static inline struct ibmebus_driver *to_ibmebus_driver(struct device_driver 
*drv)
-{
-   return container_of(drv, struct ibmebus_driver, driver);
-}
-
-static inline struct ibmebus_dev *to_ibmebus_dev(struct device *dev)
-{
-   return container_of(dev, struct ibmebus_dev, ofdev.dev);
-}
-
+void ibmebus_free_irq(u32 ist, void *dev_id);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_IBMEBUS_H */
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index c506e0d..379472f 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -194,21 +194,26 @@ static int ibmebus_create_devices(const struct 
of_device_id *matches)
return ret;
 }
 
-int ibmebus_register_driver(struct ibmebus_driver *drv)
+int ibmebus_register_driver(struct of_platform_driver *drv)
 {
-   return 0;
+   /* If the driver uses devices that ibmebus doesn't know, add them */
+   ibmebus_create_devices(drv->match_table);
+
+   drv->driver.name   = drv->name;
+   drv->driver.bus= &ibmebus_bus_type;
+
+   return driver_register(&drv->driver);
 }
 EXPORT_SYMBOL(ibmebus_register_driver);
 
-void ibmebus_unregister_driver(struct ibmebus_driver *drv)
+void ibmebus_unregister_driver(struct of_platform_driver *drv)
 {
+   driver_unregister(&drv->driver);
 }
 EXPORT_SYMBOL(ibmebus_unregister_driver);
 
-int ibmebus_request_irq(struct ibmebus_dev *dev,
-   u32 ist,
-   irq_handler_t handler,
-   unsigned long irq_flags, const char * devname,
+int ibmebus_request_irq(u32 ist, irq_handler_t handler,
+   unsigned long irq_flags, const char *devname,
void *dev_id)
 {
unsigned int irq = irq_create_mapping(NULL, ist);
@@ -216,12 +221,11 @@ int ibmebus_request_irq(struct ibmebus_dev *dev,
if (irq == NO_IRQ)
return -EINVAL;
 
-   return request_irq(irq, handler,
-  irq_flags, devname, dev_id);
+   return request_irq(irq, handler, irq_flags, devname, dev_id);
 }
 EXPORT_SYMBOL(ibmebus_request_irq);
 

[PATCH 3/5] ibmebus: Add device creation and bus probing based on of_device

2007-09-25 Thread Joachim Fenkes
The devtree root is now searched for devices matching a built-in whitelist
during boot, so these devices appear on the bus from the beginning. It is
still possible to manually add/remove devices to/from the bus by using the
probe/remove sysfs interface. Also, when a device driver registers itself,
the devtree is matched against its matchlist.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 arch/powerpc/kernel/ibmebus.c |   97 ++---
 1 files changed, 81 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index cc80f84..c506e0d 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -51,6 +51,15 @@ static struct device ibmebus_bus_device = { /* fake "parent" 
device */
 
 struct bus_type ibmebus_bus_type;
 
+/* These devices will automatically be added to the bus during init */
+static struct of_device_id builtin_matches[] = {
+   { .name = "lhca" },
+   { .compatible = "IBM,lhca" },
+   { .name = "lhea" },
+   { .compatible = "IBM,lhea" },
+   {},
+};
+
 static void *ibmebus_alloc_coherent(struct device *dev,
size_t size,
dma_addr_t *dma_handle,
@@ -124,6 +133,67 @@ static struct dma_mapping_ops ibmebus_dma_ops = {
.dma_supported  = ibmebus_dma_supported,
 };
 
+static int ibmebus_match_path(struct device *dev, void *data)
+{
+   struct device_node *dn = to_of_device(dev)->node;
+   return (dn->full_name &&
+   (strcasecmp((char *)data, dn->full_name) == 0));
+}
+
+static int ibmebus_match_node(struct device *dev, void *data)
+{
+   return to_of_device(dev)->node == data;
+}
+
+static int ibmebus_create_device(struct device_node *dn)
+{
+   struct of_device *dev;
+   int ret;
+
+   dev = of_device_alloc(dn, NULL, &ibmebus_bus_device);
+   if (!dev)
+   return -ENOMEM;
+
+   dev->dev.bus = &ibmebus_bus_type;
+   dev->dev.archdata.dma_ops = &ibmebus_dma_ops;
+
+   ret = of_device_register(dev);
+   if (ret) {
+   of_device_free(dev);
+   return ret;
+   }
+
+   return 0;
+}
+
+static int ibmebus_create_devices(const struct of_device_id *matches)
+{
+   struct device_node *root, *child;
+   int ret = 0;
+
+   root = of_find_node_by_path("/");
+
+   for (child = NULL; (child = of_get_next_child(root, child)); ) {
+   if (!of_match_node(matches, child))
+   continue;
+
+   if (bus_find_device(&ibmebus_bus_type, NULL, child,
+   ibmebus_match_node))
+   continue;
+
+   ret = ibmebus_create_device(child);
+   if (ret) {
+   printk(KERN_ERR "%s: failed to create device (%i)",
+  __FUNCTION__, ret);
+   of_node_put(child);
+   break;
+   }
+   }
+
+   of_node_put(root);
+   return ret;
+}
+
 int ibmebus_register_driver(struct ibmebus_driver *drv)
 {
return 0;
@@ -172,18 +242,6 @@ static struct device_attribute ibmebus_dev_attrs[] = {
__ATTR_NULL
 };
 
-static int ibmebus_match_path(struct device *dev, void *data)
-{
-   int rc;
-   struct device_node *dn =
-   of_node_get(to_ibmebus_dev(dev)->ofdev.node);
-
-   rc = (dn->full_name && (strcasecmp((char*)data, dn->full_name) == 0));
-
-   of_node_put(dn);
-   return rc;
-}
-
 static char *ibmebus_chomp(const char *in, size_t count)
 {
char *out = (char*)kmalloc(count + 1, GFP_KERNEL);
@@ -202,7 +260,6 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
   const char *buf, size_t count)
 {
struct device_node *dn = NULL;
-   struct ibmebus_dev *dev;
char *path;
ssize_t rc;
 
@@ -219,9 +276,9 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
}
 
if ((dn = of_find_node_by_path(path))) {
-/* dev = ibmebus_register_device_node(dn); */
+   rc = ibmebus_create_device(dn);
of_node_put(dn);
-   rc = IS_ERR(dev) ? PTR_ERR(dev) : count;
+   rc = rc ? rc : count;
} else {
printk(KERN_WARNING "%s: no such device node: %s\n",
   __FUNCTION__, path);
@@ -245,7 +302,7 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus,
 
if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
   ibmebus_match_path))) {
-/* ibmebus_unregister_device(dev); */
+   of_device_unregister(to_of_device(dev));
 
kfree(path);
return count;
@@ -

[PATCH 2/5] ibmebus: Remove bus match/probe/remove functions

2007-09-25 Thread Joachim Fenkes
ibmebus_{,un}register_driver() are replaced by dummy functions because
ibmebus is temporarily unusable in this transitional state.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 arch/powerpc/kernel/ibmebus.c |  199 ++---
 1 files changed, 6 insertions(+), 193 deletions(-)

diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index d6a38cd..cc80f84 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -41,6 +41,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -123,183 +124,14 @@ static struct dma_mapping_ops ibmebus_dma_ops = {
.dma_supported  = ibmebus_dma_supported,
 };
 
-static int ibmebus_bus_probe(struct device *dev)
-{
-   struct ibmebus_dev *ibmebusdev= to_ibmebus_dev(dev);
-   struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
-   const struct of_device_id *id;
-   int error = -ENODEV;
-
-   if (!ibmebusdrv->probe)
-   return error;
-
-   id = of_match_device(ibmebusdrv->id_table, &ibmebusdev->ofdev);
-   if (id) {
-   error = ibmebusdrv->probe(ibmebusdev, id);
-   }
-
-   return error;
-}
-
-static int ibmebus_bus_remove(struct device *dev)
-{
-   struct ibmebus_dev *ibmebusdev= to_ibmebus_dev(dev);
-   struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
-
-   if (ibmebusdrv->remove) {
-   return ibmebusdrv->remove(ibmebusdev);
-   }
-
-   return 0;
-}
-
-static void __devinit ibmebus_dev_release(struct device *dev)
-{
-   of_node_put(to_ibmebus_dev(dev)->ofdev.node);
-   kfree(to_ibmebus_dev(dev));
-}
-
-static int __devinit ibmebus_register_device_common(
-   struct ibmebus_dev *dev, const char *name)
-{
-   int err = 0;
-
-   dev->ofdev.dev.parent  = &ibmebus_bus_device;
-   dev->ofdev.dev.bus = &ibmebus_bus_type;
-   dev->ofdev.dev.release = ibmebus_dev_release;
-
-   dev->ofdev.dev.archdata.of_node = dev->ofdev.node;
-   dev->ofdev.dev.archdata.dma_ops = &ibmebus_dma_ops;
-   dev->ofdev.dev.archdata.numa_node = of_node_to_nid(dev->ofdev.node);
-
-   /* An ibmebusdev is based on a of_device. We have to change the
-* bus type to use our own DMA mapping operations.
-*/
-   if ((err = of_device_register(&dev->ofdev)) != 0) {
-   printk(KERN_ERR "%s: failed to register device (%d).\n",
-  __FUNCTION__, err);
-   return -ENODEV;
-   }
-
-   return 0;
-}
-
-static struct ibmebus_dev* __devinit ibmebus_register_device_node(
-   struct device_node *dn)
-{
-   struct ibmebus_dev *dev;
-   int i, len, bus_len;
-
-   dev = kzalloc(sizeof(struct ibmebus_dev), GFP_KERNEL);
-   if (!dev)
-   return ERR_PTR(-ENOMEM);
-
-   dev->ofdev.node = of_node_get(dn);
-
-   len = strlen(dn->full_name + 1);
-   bus_len = min(len, BUS_ID_SIZE - 1);
-   memcpy(dev->ofdev.dev.bus_id, dn->full_name + 1
-  + (len - bus_len), bus_len);
-   for (i = 0; i < bus_len; i++)
-   if (dev->ofdev.dev.bus_id[i] == '/')
-   dev->ofdev.dev.bus_id[i] = '_';
-
-   /* Register with generic device framework. */
-   if (ibmebus_register_device_common(dev, dn->name) != 0) {
-   kfree(dev);
-   return ERR_PTR(-ENODEV);
-   }
-
-   return dev;
-}
-
-static void ibmebus_probe_of_nodes(char* name)
-{
-   struct device_node *dn = NULL;
-
-   while ((dn = of_find_node_by_name(dn, name))) {
-   if (IS_ERR(ibmebus_register_device_node(dn))) {
-   of_node_put(dn);
-   return;
-   }
-   }
-
-   of_node_put(dn);
-
-   return;
-}
-
-static void ibmebus_add_devices_by_id(struct of_device_id *idt)
-{
-   while (strlen(idt->name) > 0) {
-   ibmebus_probe_of_nodes(idt->name);
-   idt++;
-   }
-
-   return;
-}
-
-static int ibmebus_match_name(struct device *dev, void *data)
-{
-   const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
-   const char *name;
-
-   name = of_get_property(ebus_dev->ofdev.node, "name", NULL);
-
-   if (name && (strcmp(data, name) == 0))
-   return 1;
-
-   return 0;
-}
-
-static int ibmebus_unregister_device(struct device *dev)
-{
-   of_device_unregister(to_of_device(dev));
-
-   return 0;
-}
-
-static void ibmebus_remove_devices_by_id(struct of_device_id *idt)
-{
-   struct device *dev;
-
-   while (strlen(idt->name) > 0) {
-   while ((dev = bus_find_device(&ibmebus_bus_type, NULL,
- (void*)idt->name,
-   

[PATCH 1/5] PowerPC: Move of_device allocation into of_device.[ch]

2007-09-25 Thread Joachim Fenkes
Extract generic of_device allocation code from of_platform_device_create()
and move it into of_device.[ch], called of_device_alloc(). Also, there's now
of_device_free() which puts the device node.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 include/asm-powerpc/of_device.h   |4 ++
 include/linux/of_device.h |5 ++
 arch/powerpc/kernel/of_device.c   |   80 +
 arch/powerpc/kernel/of_platform.c |   70 +---
 4 files changed, 91 insertions(+), 68 deletions(-)

diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h
index ec2a8a2..9ab469d 100644
--- a/include/asm-powerpc/of_device.h
+++ b/include/asm-powerpc/of_device.h
@@ -17,6 +17,10 @@ struct of_device
struct device   dev;/* Generic device interface */
 };
 
+extern struct of_device *of_device_alloc(struct device_node *np,
+const char *bus_id,
+struct device *parent);
+
 extern ssize_t of_device_get_modalias(struct of_device *ofdev,
char *str, ssize_t len);
 extern int of_device_uevent(struct device *dev,
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 91bf84b..212bffb 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -22,5 +22,10 @@ extern int of_device_register(struct of_device *ofdev);
 extern void of_device_unregister(struct of_device *ofdev);
 extern void of_release_dev(struct device *dev);
 
+static inline void of_device_free(struct of_device *dev)
+{
+   of_release_dev(&dev->dev);
+}
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_OF_DEVICE_H */
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
index 89b911e..ecb8b0e 100644
--- a/arch/powerpc/kernel/of_device.c
+++ b/arch/powerpc/kernel/of_device.c
@@ -7,8 +7,88 @@
 #include 
 
 #include 
+#include 
 #include 
 
+static void of_device_make_bus_id(struct of_device *dev)
+{
+   static atomic_t bus_no_reg_magic;
+   struct device_node *node = dev->node;
+   char *name = dev->dev.bus_id;
+   const u32 *reg;
+   u64 addr;
+   int magic;
+
+   /*
+* If it's a DCR based device, use 'd' for native DCRs
+* and 'D' for MMIO DCRs.
+*/
+#ifdef CONFIG_PPC_DCR
+   reg = of_get_property(node, "dcr-reg", NULL);
+   if (reg) {
+#ifdef CONFIG_PPC_DCR_NATIVE
+   snprintf(name, BUS_ID_SIZE, "d%x.%s",
+*reg, node->name);
+#else /* CONFIG_PPC_DCR_NATIVE */
+   addr = of_translate_dcr_address(node, *reg, NULL);
+   if (addr != OF_BAD_ADDR) {
+   snprintf(name, BUS_ID_SIZE,
+"D%llx.%s", (unsigned long long)addr,
+node->name);
+   return;
+   }
+#endif /* !CONFIG_PPC_DCR_NATIVE */
+   }
+#endif /* CONFIG_PPC_DCR */
+
+   /*
+* For MMIO, get the physical address
+*/
+   reg = of_get_property(node, "reg", NULL);
+   if (reg) {
+   addr = of_translate_address(node, reg);
+   if (addr != OF_BAD_ADDR) {
+   snprintf(name, BUS_ID_SIZE,
+"%llx.%s", (unsigned long long)addr,
+node->name);
+   return;
+   }
+   }
+
+   /*
+* No BusID, use the node name and add a globally incremented
+* counter (and pray...)
+*/
+   magic = atomic_add_return(1, &bus_no_reg_magic);
+   snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1);
+}
+
+struct of_device *of_device_alloc(struct device_node *np,
+ const char *bus_id,
+ struct device *parent)
+{
+   struct of_device *dev;
+
+   dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+   if (!dev)
+   return NULL;
+
+   dev->node = of_node_get(np);
+   dev->dev.dma_mask = &dev->dma_mask;
+   dev->dev.parent = parent;
+   dev->dev.release = of_release_dev;
+   dev->dev.archdata.of_node = np;
+   dev->dev.archdata.numa_node = of_node_to_nid(np);
+
+   if (bus_id)
+   strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+   else
+   of_device_make_bus_id(dev);
+
+   return dev;
+}
+EXPORT_SYMBOL(of_device_alloc);
+
 ssize_t of_device_get_modalias(struct of_device *ofdev,
char *str, ssize_t len)
 {
diff --git a/arch/powerpc/kernel/of_platform.c 
b/arch/powerpc/kernel/of_platform.c
index f70e787..1d96b82 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -21,7 +21,6 @@
 #include 

[PATCH 0/5] PowerPC: ibmebus refactoring and fixes

2007-09-25 Thread Joachim Fenkes
This patchset will merge the ibmebus and of_platform bus drivers by basing a
lot of ibmebus functionality on of_platform code and adding the features
specific to ibmebus on top of that.

I split the actual ibmebus rework into three patches (2/5-4/5) for easier
readability. The kernel will compile during the intermediate states, and
ibmebus will not crash, but not work either.

As a side-effect of patch 3/5, a problem with bus_id collisions in case of
two devices sharing the same location code is resolved -- the bus_id is now
determined differently.

[1/5] moves of_device allocation into of_device.[ch]
[2/5] removes the old bus match/probe/remove functions
[3/5] adds device creation and bus probing based on of_device
[4/5] finally moves to of_device and of_platform_driver by changing
  ibmebus.h and matching the eHCA and eHEA drivers
[5/5] just changes a nit in ibmebus_store_probe()

These patches should apply cleanly, in order, against 2.6.23-rc5 and against
Linus' git. Please review and comment them, and queue them up for 2.6.24 if
you think they're okay.

Thanks and regards,
  Joachim

 arch/powerpc/kernel/ibmebus.c |  263 -
 arch/powerpc/kernel/of_device.c   |   80 +
 arch/powerpc/kernel/of_platform.c |   70 +
 drivers/infiniband/hw/ehca/ehca_classes.h |2 +-
 drivers/infiniband/hw/ehca/ehca_eq.c  |6 +-
 drivers/infiniband/hw/ehca/ehca_main.c|   32 ++--
 drivers/net/ehea/ehea.h   |2 +-
 drivers/net/ehea/ehea_main.c  |   72 
 include/asm-powerpc/ibmebus.h |   38 +
 include/asm-powerpc/of_device.h   |4 +
 include/linux/of_device.h |5 +
 11 files changed, 226 insertions(+), 348 deletions(-)

-- 
Joachim Fenkes  --  eHCA Linux Driver Developer and Hardware Tamer
IBM Deutschland Entwicklung GmbH  --  Dept. 3627 (I/O Firmware Dev. 2)
Schoenaicher Strasse 220  --  71032 Boeblingen  --  Germany
eMail: [EMAIL PROTECTED]

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 02/12] IB/ehca: Add 1 is not longer needed because of firmware interface change

2007-09-14 Thread Joachim Fenkes
Roland Dreier <[EMAIL PROTECTED]> wrote on 12.09.2007 22:21:54:

> What happens if someone runs the new driver with older firmware?  Or
> what if someone upgrades the firmware without updating the driver?

Thanks for pointing our noses to this. Your comment triggered some further 
internal discussions about the meaning of the values for the current 
system implementation. We'll think this one over again and repost the 
final solution in time for 2.6.24-rc1.

If the rest of this patchset is okay with you, could you apply it and 
leave out this one patch? The patchset will apply cleanly without it.

Thanks,
  Joachim
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 3/3] IB/ehca: Make sure user pages are from hugetlb before using MR large pages

2007-09-13 Thread Joachim Fenkes
...because, on virtualized hardware like System p, we can't be sure that the
physical pages behind them are contiguous.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_mrmw.c |   25 +++--
 1 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c 
b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index 4c8f3b3..4ba8b7c 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -51,6 +51,7 @@
 
 #define NUM_CHUNKS(length, chunk_size) \
(((length) + (chunk_size - 1)) / (chunk_size))
+
 /* max number of rpages (per hcall register_rpages) */
 #define MAX_RPAGES 512
 
@@ -64,6 +65,11 @@ enum ehca_mr_pgsize {
EHCA_MR_PGSIZE16M = 0x100L
 };
 
+#define EHCA_MR_PGSHIFT4K  12
+#define EHCA_MR_PGSHIFT64K 16
+#define EHCA_MR_PGSHIFT1M  20
+#define EHCA_MR_PGSHIFT16M 24
+
 static u32 ehca_encode_hwpage_size(u32 pgsize)
 {
u32 idx = 0;
@@ -347,17 +353,16 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
/* 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;
+   int page_shift = PAGE_SHIFT;
+   if (e_mr->umem->hugetlb) {
+   /* determine page_shift, clamp between 4K and 16M */
+   page_shift = (fls64(length - 1) + 3) & ~3;
+   page_shift = min(max(page_shift, EHCA_MR_PGSHIFT4K),
+EHCA_MR_PGSHIFT16M);
+   }
+   hwpage_size = 1UL << page_shift;
} else
-   hwpage_size = EHCA_MR_PGSIZE4K;
+   hwpage_size = EHCA_MR_PGSIZE4K; /* ehca1 only supports 4k */
ehca_dbg(pd->device, "hwpage_size=%lx", hwpage_size);
 
 reg_user_mr_fallback:
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 2/3] IB/umem: Add hugetlb flag to struct ib_umem

2007-09-13 Thread Joachim Fenkes
During ib_umem_get(), determine whether all pages from the memory region are
hugetlb pages and report this in the "hugetlb" field. Low-level driver can
use this information if they need it.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/core/umem.c |   20 +++-
 include/rdma/ib_umem.h |1 +
 2 files changed, 20 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 664d2fa..2f54e29 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -37,6 +37,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "uverbs.h"
 
@@ -75,6 +76,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
 {
struct ib_umem *umem;
struct page **page_list;
+   struct vm_area_struct **vma_list;
struct ib_umem_chunk *chunk;
unsigned long locked;
unsigned long lock_limit;
@@ -104,6 +106,9 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
 */
umem->writable  = !!(access & ~IB_ACCESS_REMOTE_READ);
 
+   /* We assume the memory is from hugetlb until proved otherwise */
+   umem->hugetlb   = 1;
+
INIT_LIST_HEAD(&umem->chunk_list);
 
page_list = (struct page **) __get_free_page(GFP_KERNEL);
@@ -112,6 +117,14 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
return ERR_PTR(-ENOMEM);
}
 
+   /*
+* if we can't alloc the vma_list, it's not so bad;
+* just assume the memory is not hugetlb memory
+*/
+   vma_list = (struct vm_area_struct **) __get_free_page(GFP_KERNEL);
+   if (!vma_list)
+   umem->hugetlb = 0;
+
npages = PAGE_ALIGN(size + umem->offset) >> PAGE_SHIFT;
 
down_write(¤t->mm->mmap_sem);
@@ -131,7 +144,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
ret = get_user_pages(current, current->mm, cur_base,
 min_t(int, npages,
   PAGE_SIZE / sizeof (struct page *)),
-1, !umem->writable, page_list, NULL);
+1, !umem->writable, page_list, vma_list);
 
if (ret < 0)
goto out;
@@ -152,6 +165,9 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, 
unsigned long addr,
 
chunk->nents = min_t(int, ret, IB_UMEM_MAX_PAGE_CHUNK);
for (i = 0; i < chunk->nents; ++i) {
+   if (vma_list &&
+   !is_vm_hugetlb_page(vma_list[i + off]))
+   umem->hugetlb = 0;
chunk->page_list[i].page   = page_list[i + off];
chunk->page_list[i].offset = 0;
chunk->page_list[i].length = PAGE_SIZE;
@@ -186,6 +202,8 @@ out:
current->mm->locked_vm = locked;
 
up_write(¤t->mm->mmap_sem);
+   if (vma_list)
+   free_page((unsigned long) vma_list);
free_page((unsigned long) page_list);
 
return ret < 0 ? ERR_PTR(ret) : umem;
diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h
index c533d6c..2229842 100644
--- a/include/rdma/ib_umem.h
+++ b/include/rdma/ib_umem.h
@@ -45,6 +45,7 @@ struct ib_umem {
int offset;
int page_size;
int writable;
+   int hugetlb;
struct list_headchunk_list;
struct work_struct  work;
struct mm_struct   *mm;
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 1/3] IB/ehca: Fix large page HW cap defines

2007-09-13 Thread Joachim Fenkes
From: Hoang-Nam Nguyen <[EMAIL PROTECTED]>

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |8 
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h 
b/drivers/infiniband/hw/ehca/ehca_classes.h
index 206d4eb..c2edd4c 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -99,10 +99,10 @@ struct ehca_sport {
struct ehca_sma_attr saved_attr;
 };
 
-#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
+#define HCA_CAP_MR_PGSIZE_4K  0x8000
+#define HCA_CAP_MR_PGSIZE_64K 0x4000
+#define HCA_CAP_MR_PGSIZE_1M  0x2000
+#define HCA_CAP_MR_PGSIZE_16M 0x1000
 
 struct ehca_shca {
struct ib_device ib_device;
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 0/3] IB/ehca: MR/MW fixes

2007-09-13 Thread Joachim Fenkes
This patchset replaces Nam's previous MR/MW patch (posted by me). I split
the #define fixes into a separate patch and moved the "is the memory from
hugetlbfs?" code into ib_umem_get().

[1/3] fixes the page size HW cap defines
[2/3] adds the hugetlb test to ib_umem_get()
[3/3] finally uses the hugetlb flag in ehca_reg_user_mr()

The patches should apply cleanly, in order, on top of my previous 12-patch
set. Please review the changes and apply the patches for 2.6.24 if they are
okay.

Regards,
  Joachim

-- 
Joachim Fenkes  --  eHCA Linux Driver Developer and Hardware Tamer
IBM Deutschland Entwicklung GmbH  --  Dept. 3627 (I/O Firmware Dev. 2)
Schoenaicher Strasse 220  --  71032 Boeblingen  --  Germany
eMail: [EMAIL PROTECTED]



___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH] IB/ehca: Make sure user pages are from hugetlb before using MR large pages

2007-09-13 Thread Joachim Fenkes
Roland Dreier <[EMAIL PROTECTED]> wrote on 13.09.2007 06:33:45:

>  > -#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
>  > +#define HCA_CAP_MR_PGSIZE_4K  0x8000
>  > +#define HCA_CAP_MR_PGSIZE_64K 0x4000
>  > +#define HCA_CAP_MR_PGSIZE_1M  0x2000
>  > +#define HCA_CAP_MR_PGSIZE_16M 0x1000
> 
> Not sure I understand what this has to do with things... is this an
> unrelated fix?

Kinda. I can put it into its own patch if you want.
 
> I would suggest extending ib_umem_get() to check the vmas and adding a
> member to struct ib_umem to say whether the memory is entirely covered
> by hugetlb pages or not.

I like that approach - one patch coming right up! =)
 
>  > +  default: /* out of mem */
>  > + ib_mr = ERR_PTR(-ENOMEM);
>  > + goto reg_user_mr_exit1;
> 
> It seems like it would be better to just assume the memory is not from
> a hugetlb is ehca_is_mem_hugetlb() fails its memory allocation and
> fall back to the PAGE_SIZE case rather than failing entirely.

If ehca_is_mem_hugetlb() runs out of memory, ehca_reg_mr() is rather 
unlikely to get the memory, but it's worth a try, I'll give you that. I'll 
make the umem patch work that way.

Joachim
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 08/12] IB/ehca: Replace get_paca()->paca_index by the more portable raw_smp_processor_id()

2007-09-12 Thread Joachim Fenkes
We can use raw_smp_processor_id() here because the processor ID is only used
for debug output and may therefore be preemption-unsafe.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---

This is the same patch, but with smp_processor_id() replaced by
raw_smp_processor_id(), as kindly pointed out to me by Nathan. Thanks!

 drivers/infiniband/hw/ehca/ehca_tools.h |   14 +++---
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h 
b/drivers/infiniband/hw/ehca/ehca_tools.h
index f9b264b..4a8346a 100644
--- a/drivers/infiniband/hw/ehca/ehca_tools.h
+++ b/drivers/infiniband/hw/ehca/ehca_tools.h
@@ -73,37 +73,37 @@ extern int ehca_debug_level;
if (unlikely(ehca_debug_level)) \
dev_printk(KERN_DEBUG, (ib_dev)->dma_device, \
   "PU%04x EHCA_DBG:%s " format "\n", \
-  get_paca()->paca_index, __FUNCTION__, \
+  raw_smp_processor_id(), __FUNCTION__, \
   ## arg); \
} while (0)
 
 #define ehca_info(ib_dev, format, arg...) \
dev_info((ib_dev)->dma_device, "PU%04x EHCA_INFO:%s " format "\n", \
-get_paca()->paca_index, __FUNCTION__, ## arg)
+raw_smp_processor_id(), __FUNCTION__, ## arg)
 
 #define ehca_warn(ib_dev, format, arg...) \
dev_warn((ib_dev)->dma_device, "PU%04x EHCA_WARN:%s " format "\n", \
-get_paca()->paca_index, __FUNCTION__, ## arg)
+raw_smp_processor_id(), __FUNCTION__, ## arg)
 
 #define ehca_err(ib_dev, format, arg...) \
dev_err((ib_dev)->dma_device, "PU%04x EHCA_ERR:%s " format "\n", \
-   get_paca()->paca_index, __FUNCTION__, ## arg)
+   raw_smp_processor_id(), __FUNCTION__, ## arg)
 
 /* use this one only if no ib_dev available */
 #define ehca_gen_dbg(format, arg...) \
do { \
if (unlikely(ehca_debug_level)) \
printk(KERN_DEBUG "PU%04x EHCA_DBG:%s " format "\n", \
-  get_paca()->paca_index, __FUNCTION__, ## arg); \
+  raw_smp_processor_id(), __FUNCTION__, ## arg); \
} while (0)
 
 #define ehca_gen_warn(format, arg...) \
printk(KERN_INFO "PU%04x EHCA_WARN:%s " format "\n", \
-  get_paca()->paca_index, __FUNCTION__, ## arg)
+  raw_smp_processor_id(), __FUNCTION__, ## arg)
 
 #define ehca_gen_err(format, arg...) \
printk(KERN_ERR "PU%04x EHCA_ERR:%s " format "\n", \
-  get_paca()->paca_index, __FUNCTION__, ## arg)
+  raw_smp_processor_id(), __FUNCTION__, ## arg)
 
 /**
  * ehca_dmp - printk a memory block, whose length is n*8 bytes.
-- 
1.5.2





___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 08/12] IB/ehca: Replace get_paca()->paca_index by the more portable smp_processor_id()

2007-09-12 Thread Joachim Fenkes
On Tuesday 11 September 2007 16:51, Nathan Lynch wrote:

> > -  get_paca()->paca_index, __FUNCTION__, \
> > +  smp_processor_id(), __FUNCTION__, \
> 
> I think I see these macros used in preemptible code (e.g. ehca_probe),
> where smp_processor_id() will print a warning when
> CONFIG_DEBUG_PREEMPT=y.  Probably better to use raw_smp_processor_id.

You're right, man. The processor id doesn't need to be preemption-safe in this
context, so that would be a bogus warning. Thanks for pointing this out. I'll
post a new version of this patch.

Joachim

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] IB/ehca: Make sure user pages are from hugetlb before using MR large pages

2007-09-12 Thread Joachim Fenkes
From: Hoang-Nam Nguyen <[EMAIL PROTECTED]>

...because, on virtualized hardware like System p, we can't be sure that the
physical pages behind them are contiguous.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---

Another patch for 2.6.24 that will apply cleanly on top of my previous
patchset. Please review and apply. Thanks!

 drivers/infiniband/hw/ehca/ehca_classes.h |8 ++--
 drivers/infiniband/hw/ehca/ehca_mrmw.c|   82 +
 2 files changed, 75 insertions(+), 15 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h 
b/drivers/infiniband/hw/ehca/ehca_classes.h
index 206d4eb..c2edd4c 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -99,10 +99,10 @@ struct ehca_sport {
struct ehca_sma_attr saved_attr;
 };
 
-#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
+#define HCA_CAP_MR_PGSIZE_4K  0x8000
+#define HCA_CAP_MR_PGSIZE_64K 0x4000
+#define HCA_CAP_MR_PGSIZE_1M  0x2000
+#define HCA_CAP_MR_PGSIZE_16M 0x1000
 
 struct ehca_shca {
struct ib_device ib_device;
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c 
b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index 4c8f3b3..1bb9d23 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -41,6 +41,8 @@
  */
 
 #include 
+#include 
+#include 
 
 #include 
 
@@ -51,6 +53,7 @@
 
 #define NUM_CHUNKS(length, chunk_size) \
(((length) + (chunk_size - 1)) / (chunk_size))
+
 /* max number of rpages (per hcall register_rpages) */
 #define MAX_RPAGES 512
 
@@ -279,6 +282,52 @@ reg_phys_mr_exit0:
 } /* end ehca_reg_phys_mr() */
 
 /*--*/
+static int ehca_is_mem_hugetlb(unsigned long addr, unsigned long size)
+{
+   struct vm_area_struct **vma_list;
+   unsigned long cur_base;
+   unsigned long npages;
+   int ret, i;
+
+   vma_list = (struct vm_area_struct **) __get_free_page(GFP_KERNEL);
+   if (!vma_list) {
+   ehca_gen_err("Can not alloc vma_list");
+   return -ENOMEM;
+   }
+
+   down_write(¤t->mm->mmap_sem);
+   npages = PAGE_ALIGN(size + (addr & ~PAGE_MASK)) >> PAGE_SHIFT;
+   cur_base = addr & PAGE_MASK;
+
+   while (npages) {
+   ret = get_user_pages(current, current->mm, cur_base,
+min_t(int, npages,
+  PAGE_SIZE / sizeof (*vma_list)),
+1, 0, NULL, vma_list);
+
+   if (ret < 0) {
+   ehca_gen_err("get_user_pages() failed "
+"ret=%x cur_base=%lx", ret, cur_base);
+   goto is_hugetlb_out;
+   }
+
+   for (i = 0; i < ret; ++i)
+   if (!is_vm_hugetlb_page(vma_list[i])) {
+   ret = 0;
+   goto is_hugetlb_out;
+   }
+
+   cur_base += ret * PAGE_SIZE;
+   npages -= ret;
+   }
+   ret = 1;
+
+is_hugetlb_out:
+   up_write(¤t->mm->mmap_sem);
+   free_page((unsigned long) vma_list);
+
+   return ret;
+}
 
 struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
   u64 virt, int mr_access_flags,
@@ -346,18 +395,29 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 
start, u64 length,
num_kpages = NUM_CHUNKS((virt % PAGE_SIZE) + length, PAGE_SIZE);
/* 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;
+   shca->hca_cap_mr_pgsize & HCA_CAP_MR_PGSIZE_16M) {
+   ret = ehca_is_mem_hugetlb(virt, length);
+   switch (ret) {
+   case 0: /* mem is not from hugetlb */
+   hwpage_size = PAGE_SIZE;
+   break;
+   case 1:
+   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

[PATCH 12/12] IB/ehca: Bump version number and change its format

2007-09-11 Thread Joachim Fenkes
Nobody needed the SVNEHCA_ prefix anyway.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_main.c |6 --
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index 799f218..c84e310 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -49,10 +49,12 @@
 #include "ehca_tools.h"
 #include "hcp_if.h"
 
+#define HCAD_VERSION "0024"
+
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Christoph Raisch <[EMAIL PROTECTED]>");
 MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
-MODULE_VERSION("SVNEHCA_0023");
+MODULE_VERSION(HCAD_VERSION);
 
 int ehca_open_aqp1 = 0;
 int ehca_debug_level   = 0;
@@ -909,7 +911,7 @@ int __init ehca_module_init(void)
int ret;
 
printk(KERN_INFO "eHCA Infiniband Device Driver "
-  "(Rel.: SVNEHCA_0023)\n");
+  "(Version " HCAD_VERSION ")\n");
 
ret = ehca_create_comp_pool();
if (ret) {
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 11/12] IB/ehca: Serialize MR alloc and MR free hvCalls

2007-09-11 Thread Joachim Fenkes
Some firmware levels exhibit a race condition between H_ALLOC_RESOURCE(MR)
and H_FREE_RESOURCE(MR). Work around this problem by locking these hvCalls
against each other.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/hcp_if.c |   28 +---
 1 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/hcp_if.c 
b/drivers/infiniband/hw/ehca/hcp_if.c
index a70a5ed..d3d1ef2 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -120,15 +120,28 @@ static long ehca_plpar_hcall_norets(unsigned long opcode,
unsigned long arg7)
 {
long ret;
-   int i, sleep_msecs;
+   int i, sleep_msecs, do_lock;
+   unsigned long flags;
 
ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
 
+   /* lock H_FREE_RESOURCE(MR) against itself and H_ALLOC_RESOURCE(MR) */
+   if ((opcode == H_FREE_RESOURCE) && (arg7 == 5)) {
+   arg7 = 0; /* better not upset firmware */
+   do_lock = 1;
+   }
+
for (i = 0; i < 5; i++) {
+   if (do_lock)
+   spin_lock_irqsave(&hcall_lock, flags);
+
ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
 arg5, arg6, arg7);
 
+   if (do_lock)
+   spin_unlock_irqrestore(&hcall_lock, flags);
+
if (H_IS_LONG_BUSY(ret)) {
sleep_msecs = get_longbusy_msecs(ret);
msleep_interruptible(sleep_msecs);
@@ -161,23 +174,24 @@ static long ehca_plpar_hcall9(unsigned long opcode,
  unsigned long arg9)
 {
long ret;
-   int i, sleep_msecs, lock_is_set = 0;
+   int i, sleep_msecs, do_lock;
unsigned long flags = 0;
 
ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
 
+   /* lock H_ALLOC_RESOURCE(MR) against itself and H_FREE_RESOURCE(MR) */
+   do_lock = ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5));
+
for (i = 0; i < 5; i++) {
-   if ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5)) {
+   if (do_lock)
spin_lock_irqsave(&hcall_lock, flags);
-   lock_is_set = 1;
-   }
 
ret = plpar_hcall9(opcode, outs,
   arg1, arg2, arg3, arg4, arg5,
   arg6, arg7, arg8, arg9);
 
-   if (lock_is_set)
+   if (do_lock)
spin_unlock_irqrestore(&hcall_lock, flags);
 
if (H_IS_LONG_BUSY(ret)) {
@@ -807,7 +821,7 @@ u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle 
adapter_handle,
return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
   adapter_handle.handle,/* r4 */
   mr->ipz_mr_handle.handle, /* r5 */
-  0, 0, 0, 0, 0);
+  0, 0, 0, 0, 5);
 }
 
 u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 10/12] IB/ehca: Path migration support

2007-09-11 Thread Joachim Fenkes
Rectify some modify_qp() issues related to path migration.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_irq.c |4 +-
 drivers/infiniband/hw/ehca/ehca_qp.c  |   90 -
 2 files changed, 68 insertions(+), 26 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c 
b/drivers/infiniband/hw/ehca/ehca_irq.c
index a925ea5..7093986 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -294,8 +294,8 @@ static void parse_identifier(struct ehca_shca *shca, u64 
eqe)
case 0x11: /* unaffiliated access error */
ehca_err(&shca->ib_device, "Unaffiliated access error.");
break;
-   case 0x12: /* path migrating error */
-   ehca_err(&shca->ib_device, "Path migration error.");
+   case 0x12: /* path migrating */
+   ehca_err(&shca->ib_device, "Path migrating.");
break;
case 0x13: /* interface trace stopped */
ehca_err(&shca->ib_device, "Interface trace stopped.");
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c 
b/drivers/infiniband/hw/ehca/ehca_qp.c
index 7154f62..6c70dee 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -1167,6 +1167,13 @@ static int internal_modify_qp(struct ib_qp *ibqp,
}
 
if (attr_mask & IB_QP_PKEY_INDEX) {
+   if (attr->pkey_index >= 16) {
+   ret = -EINVAL;
+   ehca_err(ibqp->device, "Invalid pkey_index=%x. "
+"ehca_qp=%p qp_num=%x max_pkey_index=f",
+attr->pkey_index, my_qp, ibqp->qp_num);
+   goto modify_qp_exit2;
+   }
mqpcb->prim_p_key_idx = attr->pkey_index;
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_P_KEY_IDX, 1);
}
@@ -1275,50 +1282,78 @@ static int internal_modify_qp(struct ib_qp *ibqp,
int ehca_mult = ib_rate_to_mult(
shca->sport[my_qp->init_attr.port_num].rate);
 
+   if (attr->alt_port_num < 1
+   || attr->alt_port_num > shca->num_ports) {
+   ret = -EINVAL;
+   ehca_err(ibqp->device, "Invalid alt_port=%x. "
+"ehca_qp=%p qp_num=%x num_ports=%x",
+attr->alt_port_num, my_qp, ibqp->qp_num,
+shca->num_ports);
+   goto modify_qp_exit2;
+   }
+   mqpcb->alt_phys_port = attr->alt_port_num;
+
+   if (attr->alt_pkey_index >= 16) {
+   ret = -EINVAL;
+   ehca_err(ibqp->device, "Invalid alt_pkey_index=%x. "
+"ehca_qp=%p qp_num=%x max_pkey_index=f",
+attr->pkey_index, my_qp, ibqp->qp_num);
+   goto modify_qp_exit2;
+   }
+   mqpcb->alt_p_key_idx = attr->alt_pkey_index;
+
+   mqpcb->timeout_al = attr->alt_timeout;
mqpcb->dlid_al = attr->alt_ah_attr.dlid;
-   update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DLID_AL, 1);
mqpcb->source_path_bits_al = attr->alt_ah_attr.src_path_bits;
-   update_mask |=
-   EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS_AL, 1);
mqpcb->service_level_al = attr->alt_ah_attr.sl;
-   update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL_AL, 1);
 
-   if (ah_mult < ehca_mult)
-   mqpcb->max_static_rate = (ah_mult > 0) ?
-   ((ehca_mult - 1) / ah_mult) : 0;
+   if (ah_mult > 0 && ah_mult < ehca_mult)
+   mqpcb->max_static_rate_al = (ehca_mult - 1) / ah_mult;
else
mqpcb->max_static_rate_al = 0;
 
-   update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE_AL, 1);
+   /* OpenIB doesn't support alternate retry counts - copy them */
+   mqpcb->retry_count_al = mqpcb->retry_count;
+   mqpcb->rnr_retry_count_al = mqpcb->rnr_retry_count;
+
+   update_mask |= EHCA_BMASK_SET(MQPCB_MASK_ALT_PHYS_PORT, 1)
+   | EHCA_BMASK_SET(MQPCB_MASK_ALT_P_KEY_IDX, 1)
+   | EHCA_BMASK_SET(MQPCB_MASK_TIMEOUT_AL, 1)
+   | EHCA_BMASK_SET(MQPCB_MASK_DLID_AL, 1)
+   | EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS_AL, 1)
+   | EHCA_BMASK_SET(MQPCB_MASK_SERVICE

[PATCH 08/12] IB/ehca: Replace get_paca()->paca_index by the more portable smp_processor_id()

2007-09-11 Thread Joachim Fenkes
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_tools.h |   14 +++---
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h 
b/drivers/infiniband/hw/ehca/ehca_tools.h
index f9b264b..863f972 100644
--- a/drivers/infiniband/hw/ehca/ehca_tools.h
+++ b/drivers/infiniband/hw/ehca/ehca_tools.h
@@ -73,37 +73,37 @@ extern int ehca_debug_level;
if (unlikely(ehca_debug_level)) \
dev_printk(KERN_DEBUG, (ib_dev)->dma_device, \
   "PU%04x EHCA_DBG:%s " format "\n", \
-  get_paca()->paca_index, __FUNCTION__, \
+  smp_processor_id(), __FUNCTION__, \
   ## arg); \
} while (0)
 
 #define ehca_info(ib_dev, format, arg...) \
dev_info((ib_dev)->dma_device, "PU%04x EHCA_INFO:%s " format "\n", \
-get_paca()->paca_index, __FUNCTION__, ## arg)
+smp_processor_id(), __FUNCTION__, ## arg)
 
 #define ehca_warn(ib_dev, format, arg...) \
dev_warn((ib_dev)->dma_device, "PU%04x EHCA_WARN:%s " format "\n", \
-get_paca()->paca_index, __FUNCTION__, ## arg)
+smp_processor_id(), __FUNCTION__, ## arg)
 
 #define ehca_err(ib_dev, format, arg...) \
dev_err((ib_dev)->dma_device, "PU%04x EHCA_ERR:%s " format "\n", \
-   get_paca()->paca_index, __FUNCTION__, ## arg)
+   smp_processor_id(), __FUNCTION__, ## arg)
 
 /* use this one only if no ib_dev available */
 #define ehca_gen_dbg(format, arg...) \
do { \
if (unlikely(ehca_debug_level)) \
printk(KERN_DEBUG "PU%04x EHCA_DBG:%s " format "\n", \
-  get_paca()->paca_index, __FUNCTION__, ## arg); \
+  smp_processor_id(), __FUNCTION__, ## arg); \
} while (0)
 
 #define ehca_gen_warn(format, arg...) \
printk(KERN_INFO "PU%04x EHCA_WARN:%s " format "\n", \
-  get_paca()->paca_index, __FUNCTION__, ## arg)
+  smp_processor_id(), __FUNCTION__, ## arg)
 
 #define ehca_gen_err(format, arg...) \
printk(KERN_ERR "PU%04x EHCA_ERR:%s " format "\n", \
-  get_paca()->paca_index, __FUNCTION__, ## arg)
+  smp_processor_id(), __FUNCTION__, ## arg)
 
 /**
  * ehca_dmp - printk a memory block, whose length is n*8 bytes.
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 09/12] IB/ehca: Add check for max #SGE to create_qp()

2007-09-11 Thread Joachim Fenkes
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_qp.c |   14 +-
 1 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c 
b/drivers/infiniband/hw/ehca/ehca_qp.c
index d2ab84a..7154f62 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -513,7 +513,7 @@ static struct ehca_qp *internal_create_qp(
} else if (init_attr->cap.max_send_wr > 255) {
ehca_err(pd->device,
 "Invalid Number of "
-"ax_send_wr=%x for UD QP_TYPE=%x",
+"max_send_wr=%x for UD QP_TYPE=%x",
 init_attr->cap.max_send_wr, qp_type);
return ERR_PTR(-EINVAL);
}
@@ -524,6 +524,18 @@ static struct ehca_qp *internal_create_qp(
return ERR_PTR(-EINVAL);
break;
}
+   } else {
+   int max_sge = (qp_type == IB_QPT_UD || qp_type == IB_QPT_SMI
+  || qp_type == IB_QPT_GSI) ? 250 : 252;
+
+   if (init_attr->cap.max_send_sge > max_sge
+   || init_attr->cap.max_recv_sge > max_sge) {
+   ehca_err(pd->device, "Invalid number of SGEs requested "
+"send_sge=%x recv_sge=%x max_sge=%x",
+init_attr->cap.max_send_sge,
+init_attr->cap.max_recv_sge, max_sge);
+   return ERR_PTR(-EINVAL);
+   }
}
 
if (pd->uobject && udata)
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 07/12] IB/ehca: ehca_gen_warn() should always print

2007-09-11 Thread Joachim Fenkes
Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_tools.h |9 +++--
 1 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h 
b/drivers/infiniband/hw/ehca/ehca_tools.h
index 57c77a7..f9b264b 100644
--- a/drivers/infiniband/hw/ehca/ehca_tools.h
+++ b/drivers/infiniband/hw/ehca/ehca_tools.h
@@ -98,15 +98,12 @@ extern int ehca_debug_level;
} while (0)
 
 #define ehca_gen_warn(format, arg...) \
-   do { \
-   if (unlikely(ehca_debug_level)) \
-   printk(KERN_INFO "PU%04x EHCA_WARN:%s " format "\n", \
-  get_paca()->paca_index, __FUNCTION__, ## arg); \
-   } while (0)
+   printk(KERN_INFO "PU%04x EHCA_WARN:%s " format "\n", \
+  get_paca()->paca_index, __FUNCTION__, ## arg)
 
 #define ehca_gen_err(format, arg...) \
printk(KERN_ERR "PU%04x EHCA_ERR:%s " format "\n", \
-   get_paca()->paca_index, __FUNCTION__, ## arg)
+  get_paca()->paca_index, __FUNCTION__, ## arg)
 
 /**
  * ehca_dmp - printk a memory block, whose length is n*8 bytes.
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 06/12] IB/ehca: Print return codes as signed decimal integers

2007-09-11 Thread Joachim Fenkes
...because -12 is easier to read than FFF4.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_cq.c |   14 +++---
 drivers/infiniband/hw/ehca/ehca_hca.c|2 +-
 drivers/infiniband/hw/ehca/ehca_main.c   |   24 +-
 drivers/infiniband/hw/ehca/ehca_mcast.c  |4 +-
 drivers/infiniband/hw/ehca/ehca_mrmw.c   |   75 +++---
 drivers/infiniband/hw/ehca/ehca_qp.c |   46 +-
 drivers/infiniband/hw/ehca/ehca_reqs.c   |2 +-
 drivers/infiniband/hw/ehca/ehca_sqp.c|2 +-
 drivers/infiniband/hw/ehca/ehca_uverbs.c |   18 
 drivers/infiniband/hw/ehca/hcp_if.c  |   20 
 10 files changed, 103 insertions(+), 104 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c 
b/drivers/infiniband/hw/ehca/ehca_cq.c
index d68603d..79c25f5 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -190,7 +190,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int 
cqe, int comp_vector,
 
if (h_ret != H_SUCCESS) {
ehca_err(device, "hipz_h_alloc_resource_cq() failed "
-"h_ret=%lx device=%p", h_ret, device);
+"h_ret=%li device=%p", h_ret, device);
cq = ERR_PTR(ehca2ib_return_code(h_ret));
goto create_cq_exit2;
}
@@ -198,7 +198,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int 
cqe, int comp_vector,
ipz_rc = ipz_queue_ctor(NULL, &my_cq->ipz_queue, param.act_pages,
EHCA_PAGESIZE, sizeof(struct ehca_cqe), 0, 0);
if (!ipz_rc) {
-   ehca_err(device, "ipz_queue_ctor() failed ipz_rc=%x device=%p",
+   ehca_err(device, "ipz_queue_ctor() failed ipz_rc=%i device=%p",
 ipz_rc, device);
cq = ERR_PTR(-EINVAL);
goto create_cq_exit3;
@@ -226,7 +226,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int 
cqe, int comp_vector,
 
if (h_ret < H_SUCCESS) {
ehca_err(device, "hipz_h_register_rpage_cq() failed "
-"ehca_cq=%p cq_num=%x h_ret=%lx counter=%i "
+"ehca_cq=%p cq_num=%x h_ret=%li counter=%i "
 "act_pages=%i", my_cq, my_cq->cq_number,
 h_ret, counter, param.act_pages);
cq = ERR_PTR(-EINVAL);
@@ -238,7 +238,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int 
cqe, int comp_vector,
if ((h_ret != H_SUCCESS) || vpage) {
ehca_err(device, "Registration of pages not "
 "complete ehca_cq=%p cq_num=%x "
-"h_ret=%lx", my_cq, my_cq->cq_number,
+"h_ret=%li", my_cq, my_cq->cq_number,
 h_ret);
cq = ERR_PTR(-EAGAIN);
goto create_cq_exit4;
@@ -246,7 +246,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int 
cqe, int comp_vector,
} else {
if (h_ret != H_PAGE_REGISTERED) {
ehca_err(device, "Registration of page failed "
-"ehca_cq=%p cq_num=%x h_ret=%lx"
+"ehca_cq=%p cq_num=%x h_ret=%li"
 "counter=%i act_pages=%i",
 my_cq, my_cq->cq_number,
 h_ret, counter, param.act_pages);
@@ -298,7 +298,7 @@ create_cq_exit3:
h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 1);
if (h_ret != H_SUCCESS)
ehca_err(device, "hipz_h_destroy_cq() failed ehca_cq=%p "
-"cq_num=%x h_ret=%lx", my_cq, my_cq->cq_number, h_ret);
+"cq_num=%x h_ret=%li", my_cq, my_cq->cq_number, h_ret);
 
 create_cq_exit2:
write_lock_irqsave(&ehca_cq_idr_lock, flags);
@@ -362,7 +362,7 @@ int ehca_destroy_cq(struct ib_cq *cq)
 cq_num);
}
if (h_ret != H_SUCCESS) {
-   ehca_err(device, "hipz_h_destroy_cq() failed h_ret=%lx "
+   ehca_err(device, "hipz_h_destroy_cq() failed h_ret=%li "
 "ehca_cq=%p cq_num=%x", h_ret, my_cq, cq_num);
return ehca2ib_return_code(h_ret);
}
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c 
b/drivers/infini

[PATCH 05/12] IB/ehca: Refactor hvcall tracing

2007-09-11 Thread Joachim Fenkes
Change hvcall trace output towards better readability: reg numbers instead
of argument numbers, return code as signed decimal instead of unsigned hex.

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/hcp_if.c |   57 ++
 1 files changed, 24 insertions(+), 33 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/hcp_if.c 
b/drivers/infiniband/hw/ehca/hcp_if.c
index 8534061..32f465b 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -84,6 +84,10 @@
 #define H_MP_SHUTDOWN   EHCA_BMASK_IBM(48, 48)
 #define H_MP_RESET_QKEY_CTR EHCA_BMASK_IBM(49, 49)
 
+#define HCALL4_REGS_FORMAT "r4=%lx r5=%lx r6=%lx r7=%lx"
+#define HCALL7_REGS_FORMAT HCALL4_REGS_FORMAT " r8=%lx r9=%lx r10=%lx"
+#define HCALL9_REGS_FORMAT HCALL7_REGS_FORMAT " r11=%lx r12=%lx"
+
 static DEFINE_SPINLOCK(hcall_lock);
 
 static u32 get_longbusy_msecs(int longbusy_rc)
@@ -118,8 +122,7 @@ static long ehca_plpar_hcall_norets(unsigned long opcode,
long ret;
int i, sleep_msecs;
 
-   ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
-"arg5=%lx arg6=%lx arg7=%lx",
+   ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
 
for (i = 0; i < 5; i++) {
@@ -133,16 +136,13 @@ static long ehca_plpar_hcall_norets(unsigned long opcode,
}
 
if (ret < H_SUCCESS)
-   ehca_gen_err("opcode=%lx ret=%lx"
-" arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
-" arg5=%lx arg6=%lx arg7=%lx ",
-opcode, ret,
-arg1, arg2, arg3, arg4, arg5,
-arg6, arg7);
-
-   ehca_gen_dbg("opcode=%lx ret=%lx", opcode, ret);
-   return ret;
+   ehca_gen_err("opcode=%lx ret=%li " HCALL7_REGS_FORMAT,
+opcode, ret, arg1, arg2, arg3,
+arg4, arg5, arg6, arg7);
+   else
+   ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret);
 
+   return ret;
}
 
return H_BUSY;
@@ -164,10 +164,8 @@ static long ehca_plpar_hcall9(unsigned long opcode,
int i, sleep_msecs, lock_is_set = 0;
unsigned long flags = 0;
 
-   ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
-"arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx",
-opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
-arg8, arg9);
+   ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
+arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
 
for (i = 0; i < 5; i++) {
if ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5)) {
@@ -188,26 +186,19 @@ static long ehca_plpar_hcall9(unsigned long opcode,
continue;
}
 
-   if (ret < H_SUCCESS)
-   ehca_gen_err("opcode=%lx ret=%lx"
-" arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
-" arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
-" arg9=%lx"
-" out1=%lx out2=%lx out3=%lx out4=%lx"
-" out5=%lx out6=%lx out7=%lx out8=%lx"
-" out9=%lx",
-opcode, ret,
-arg1, arg2, arg3, arg4, arg5,
-arg6, arg7, arg8, arg9,
-outs[0], outs[1], outs[2], outs[3],
+   if (ret < H_SUCCESS) {
+   ehca_gen_err("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT,
+opcode, arg1, arg2, arg3, arg4, arg5,
+arg6, arg7, arg8, arg9);
+   ehca_gen_err("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
+ret, outs[0], outs[1], outs[2], outs[3],
+outs[4], outs[5], outs[6], outs[7],
+outs[8]);
+   } else
+   ehca_gen_dbg("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
+ret, outs[0], outs[1], outs[2], outs[3],
 outs[4], outs[5], outs[6], outs[7],
 outs

[PATCH 04/12] IB/ehca: Use remap_4k_pfn() to map firmware contexts to user space

2007-09-11 Thread Joachim Fenkes
From: Hoang-Nam Nguyen <[EMAIL PROTECTED]>

Use Paul's new remap_4k_pfn() function to map our 4K firmware contexts into
user space on 64K-page machines without exposing neighboring firmware
contexts. Return the context's offset within a 64K page to user space so it
can determine the proper virtual address.

For details about remap_4k_pfn(), see commit 721151d0 or
http://patchwork.ozlabs.org/linuxppc/patch?id=10281

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |4 +++-
 drivers/infiniband/hw/ehca/ehca_cq.c  |2 ++
 drivers/infiniband/hw/ehca/ehca_qp.c  |2 ++
 drivers/infiniband/hw/ehca/ehca_uverbs.c  |6 +++---
 4 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h 
b/drivers/infiniband/hw/ehca/ehca_classes.h
index b5e9603..206d4eb 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -337,6 +337,8 @@ struct ehca_create_cq_resp {
u32 cq_number;
u32 token;
struct ipzu_queue_resp ipz_queue;
+   u32 fw_handle_ofs;
+   u32 dummy;
 };
 
 struct ehca_create_qp_resp {
@@ -347,7 +349,7 @@ struct ehca_create_qp_resp {
u32 qkey;
/* qp_num assigned by ehca: sqp0/1 may have got different numbers */
u32 real_qp_num;
-   u32 dummy; /* padding for 8 byte alignment */
+   u32 fw_handle_ofs;
struct ipzu_queue_resp ipz_squeue;
struct ipzu_queue_resp ipz_rqueue;
 };
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c 
b/drivers/infiniband/hw/ehca/ehca_cq.c
index a6f17e4..d68603d 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -281,6 +281,8 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int 
cqe, int comp_vector,
resp.ipz_queue.queue_length = ipz_queue->queue_length;
resp.ipz_queue.pagesize = ipz_queue->pagesize;
resp.ipz_queue.toggle_state = ipz_queue->toggle_state;
+   resp.fw_handle_ofs = (u32)
+   (my_cq->galpas.user.fw_handle & (PAGE_SIZE - 1));
if (ib_copy_to_udata(udata, &resp, sizeof(resp))) {
ehca_err(device, "Copy to udata failed.");
goto create_cq_exit4;
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c 
b/drivers/infiniband/hw/ehca/ehca_qp.c
index e886e3b..3a3880f 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -751,6 +751,8 @@ static struct ehca_qp *internal_create_qp(
queue2resp(&resp.ipz_squeue, &my_qp->ipz_squeue);
if (HAS_RQ(my_qp))
queue2resp(&resp.ipz_rqueue, &my_qp->ipz_rqueue);
+   resp.fw_handle_ofs = (u32)
+   (my_qp->galpas.user.fw_handle & (PAGE_SIZE - 1));
 
if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
ehca_err(pd->device, "Copy to udata failed");
diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c 
b/drivers/infiniband/hw/ehca/ehca_uverbs.c
index 3340f49..84a16bc 100644
--- a/drivers/infiniband/hw/ehca/ehca_uverbs.c
+++ b/drivers/infiniband/hw/ehca/ehca_uverbs.c
@@ -109,7 +109,7 @@ static int ehca_mmap_fw(struct vm_area_struct *vma, struct 
h_galpas *galpas,
u64 vsize, physical;
 
vsize = vma->vm_end - vma->vm_start;
-   if (vsize != EHCA_PAGESIZE) {
+   if (vsize < EHCA_PAGESIZE) {
ehca_gen_err("invalid vsize=%lx", vma->vm_end - vma->vm_start);
return -EINVAL;
}
@@ -118,8 +118,8 @@ static int ehca_mmap_fw(struct vm_area_struct *vma, struct 
h_galpas *galpas,
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
ehca_gen_dbg("vsize=%lx physical=%lx", vsize, physical);
/* VM_IO | VM_RESERVED are set by remap_pfn_range() */
-   ret = remap_pfn_range(vma, vma->vm_start, physical >> PAGE_SHIFT,
- vsize, vma->vm_page_prot);
+   ret = remap_4k_pfn(vma, vma->vm_start, physical >> EHCA_PAGESHIFT,
+  vma->vm_page_prot);
if (unlikely(ret)) {
ehca_gen_err("remap_pfn_range() failed ret=%x", ret);
return -ENOMEM;
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 03/12] IB/ehca: Support more than 4k QPs for userspace and kernelspace

2007-09-11 Thread Joachim Fenkes
From: Stefan Roscher <[EMAIL PROTECTED]>

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_cq.c |7 ++-
 drivers/infiniband/hw/ehca/ehca_main.c   |2 +-
 drivers/infiniband/hw/ehca/ehca_qp.c |9 +++--
 drivers/infiniband/hw/ehca/ehca_uverbs.c |   22 +++---
 4 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c 
b/drivers/infiniband/hw/ehca/ehca_cq.c
index 81aff36..a6f17e4 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -166,7 +166,6 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int 
cqe, int comp_vector,
write_lock_irqsave(&ehca_cq_idr_lock, flags);
ret = idr_get_new(&ehca_cq_idr, my_cq, &my_cq->token);
write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
-
} while (ret == -EAGAIN);
 
if (ret) {
@@ -176,6 +175,12 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int 
cqe, int comp_vector,
goto create_cq_exit1;
}
 
+   if (my_cq->token > 0x1FF) {
+   cq = ERR_PTR(-ENOMEM);
+   ehca_err(device, "Invalid number of cq. device=%p", device);
+   goto create_cq_exit2;
+   }
+
/*
 * CQs maximum depth is 4GB-64, but we need additional 20 as buffer
 * for receiving errors CQEs.
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c 
b/drivers/infiniband/hw/ehca/ehca_main.c
index 99036b6..1a2c542 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -380,7 +380,7 @@ int ehca_init_device(struct ehca_shca *shca)
strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX);
shca->ib_device.owner   = THIS_MODULE;
 
-   shca->ib_device.uverbs_abi_ver  = 7;
+   shca->ib_device.uverbs_abi_ver  = 8;
shca->ib_device.uverbs_cmd_mask =
(1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
(1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)|
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c 
b/drivers/infiniband/hw/ehca/ehca_qp.c
index 13b61c3..e886e3b 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -557,7 +557,6 @@ static struct ehca_qp *internal_create_qp(
write_lock_irqsave(&ehca_qp_idr_lock, flags);
ret = idr_get_new(&ehca_qp_idr, my_qp, &my_qp->token);
write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
-
} while (ret == -EAGAIN);
 
if (ret) {
@@ -566,11 +565,17 @@ static struct ehca_qp *internal_create_qp(
goto create_qp_exit0;
}
 
+   if (my_qp->token > 0x1FF) {
+   ret = -EINVAL;
+   ehca_err(pd->device, "Invalid number of qp");
+   goto create_qp_exit1;
+   }
+
parms.servicetype = ibqptype2servicetype(qp_type);
if (parms.servicetype < 0) {
ret = -EINVAL;
ehca_err(pd->device, "Invalid qp_type=%x", qp_type);
-   goto create_qp_exit0;
+   goto create_qp_exit1;
}
 
if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c 
b/drivers/infiniband/hw/ehca/ehca_uverbs.c
index 4bc687f..3340f49 100644
--- a/drivers/infiniband/hw/ehca/ehca_uverbs.c
+++ b/drivers/infiniband/hw/ehca/ehca_uverbs.c
@@ -164,7 +164,7 @@ static int ehca_mmap_cq(struct vm_area_struct *vma, struct 
ehca_cq *cq,
int ret;
 
switch (rsrc_type) {
-   case 1: /* galpa fw handle */
+   case 0: /* galpa fw handle */
ehca_dbg(cq->ib_cq.device, "cq_num=%x fw", cq->cq_number);
ret = ehca_mmap_fw(vma, &cq->galpas, &cq->mm_count_galpa);
if (unlikely(ret)) {
@@ -175,7 +175,7 @@ static int ehca_mmap_cq(struct vm_area_struct *vma, struct 
ehca_cq *cq,
}
break;
 
-   case 2: /* cq queue_addr */
+   case 1: /* cq queue_addr */
ehca_dbg(cq->ib_cq.device, "cq_num=%x queue", cq->cq_number);
ret = ehca_mmap_queue(vma, &cq->ipz_queue, &cq->mm_count_queue);
if (unlikely(ret)) {
@@ -201,7 +201,7 @@ static int ehca_mmap_qp(struct vm_area_struct *vma, struct 
ehca_qp *qp,
int ret;
 
switch (rsrc_type) {
-   case 1: /* galpa fw handle */
+   case 0: /* galpa fw handle */
ehca_dbg(qp->ib_qp.device, "qp_num=%x fw", qp->ib_qp.qp_num);
ret = ehca_mmap_fw(vma, &qp->galpas, &qp->mm_count_galpa);
if (unlikely(ret)) {
@@ -212,7 +212,7 @@ static int ehca_mma

[PATCH 02/12] IB/ehca: Add 1 is not longer needed because of firmware interface change

2007-09-11 Thread Joachim Fenkes
From: Stefan Roscher <[EMAIL PROTECTED]>

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/hcp_if.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/hcp_if.c 
b/drivers/infiniband/hw/ehca/hcp_if.c
index 24f4541..8534061 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -317,9 +317,9 @@ u64 hipz_h_alloc_resource_qp(const struct 
ipz_adapter_handle adapter_handle,
 
max_r10_reg =
EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
-  parms->squeue.max_wr + 1)
+  parms->squeue.max_wr)
| EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
-parms->rqueue.max_wr + 1)
+parms->rqueue.max_wr)
| EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
 parms->squeue.max_sge)
| EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 01/12] IB/ehca: Small QP userspace support

2007-09-11 Thread Joachim Fenkes
From: Stefan Roscher <[EMAIL PROTECTED]>

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_qp.c   |7 +++
 drivers/infiniband/hw/ehca/ipz_pt_fn.c |1 +
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c 
b/drivers/infiniband/hw/ehca/ehca_qp.c
index 84d435a..13b61c3 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -273,6 +273,7 @@ static inline void queue2resp(struct ipzu_queue_resp *resp,
resp->queue_length = queue->queue_length;
resp->pagesize = queue->pagesize;
resp->toggle_state = queue->toggle_state;
+   resp->offset = queue->offset;
 }
 
 /*
@@ -598,8 +599,7 @@ static struct ehca_qp *internal_create_qp(
parms.squeue.max_sge = max_send_sge;
parms.rqueue.max_sge = max_recv_sge;
 
-   if (EHCA_BMASK_GET(HCA_CAP_MINI_QP, shca->hca_cap)
-   && !(context && udata)) { /* no small QP support in userspace ATM */
+   if (EHCA_BMASK_GET(HCA_CAP_MINI_QP, shca->hca_cap)) {
if (HAS_SQ(my_qp))
ehca_determine_small_queue(
&parms.squeue, max_send_sge, is_llqp);
@@ -741,8 +741,7 @@ static struct ehca_qp *internal_create_qp(
resp.ext_type = my_qp->ext_type;
resp.qkey = my_qp->qkey;
resp.real_qp_num = my_qp->real_qp_num;
-   resp.ipz_rqueue.offset = my_qp->ipz_rqueue.offset;
-   resp.ipz_squeue.offset = my_qp->ipz_squeue.offset;
+
if (HAS_SQ(my_qp))
queue2resp(&resp.ipz_squeue, &my_qp->ipz_squeue);
if (HAS_RQ(my_qp))
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.c 
b/drivers/infiniband/hw/ehca/ipz_pt_fn.c
index 29bd476..661f8db 100644
--- a/drivers/infiniband/hw/ehca/ipz_pt_fn.c
+++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.c
@@ -158,6 +158,7 @@ static int alloc_small_queue_page(struct ipz_queue *queue, 
struct ehca_pd *pd)
 
queue->queue_pages[0] = (void *)(page->page | (bit << (order + 9)));
queue->small_page = page;
+   queue->offset = bit << (order + 9);
return 1;
 
 out:
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 00/12] IB/ehca: New features and fixes for 2.6.24

2007-09-11 Thread Joachim Fenkes
Here are some fresh eHCA driver features and fixes for your reviewing
pleasure. They have passed internal testing and checkpatch.pl, so we think
they are ready for inclusion.

[01/12] adds userspace support for small QPs
[02/12] changes a nit in firmware communication
[03/12] adds support for more than 4096 QPs/CQs in user space
[04/12] enables mapping firmware contexts into uspace on 64K-page kernels
[05/12] changes hvCall debug trace formatting
[06/12] outputs return codes as signed decimal integers
[07/12] makes warnings also appear in non-debug mode, like they should
[08/12] replaces get_paca()->paca_index by the portable smp_processor_id()
[09/12] checks the allowed max number of SGEs when creating a QP
[10/12] fixes some Path Migration problems
[11/12] works around a firmware race condition
[12/12] bumps the driver's version number

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

Regards,
  Joachim

-- 
Joachim Fenkes  --  eHCA Linux Driver Developer and Hardware Tamer
IBM Deutschland Entwicklung GmbH  --  Dept. 3627 (I/O Firmware Dev. 2)
Schoenaicher Strasse 220  --  71032 Boeblingen  --  Germany
eMail: [EMAIL PROTECTED]




___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 2.6.23] ibmebus: Prevent bus_id collisions

2007-08-31 Thread Joachim Fenkes
> > The plaintiff makes a valid point. How about a staging approach: We 
put 
> > the patch as it is now into 2.6.23 so the problem is fixed, and I'll 
post 
> > a "nice" version with autoloading support and a generic of_make_bus_id 

> > function for 2.6.24. Agree?
> 
> Ok, sounds fair. Can you make sure that the resulting bus_id is the same
> for the final version then?

No, it would change once more -- the current, minimal-invasive, variant of 
the fix uses the full_name -> "[EMAIL PROTECTED]", while of_make_bus_id uses 
another format: "12345678.ehca". I don't think this makes much of a 
difference, though, and users shouldn't rely on the bus_id having a 
certain format anyway, so IMHO we can live with this.

Regards,
  Joachim
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 2.6.23] ibmebus: Prevent bus_id collisions

2007-08-31 Thread Joachim Fenkes
Hi, Arnd,

> The whole logic of dynamically adding and removing device is rather 
bogus,
> and it prevents autoloading of device drivers. of_platform_make_bus_id
> is the function that is responsible for creating unique names over 
there.

The plaintiff makes a valid point. How about a staging approach: We put 
the patch as it is now into 2.6.23 so the problem is fixed, and I'll post 
a "nice" version with autoloading support and a generic of_make_bus_id 
function for 2.6.24. Agree?

Regards,
  Joachim
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 2/2] IB/ehca: SRQ fixes to enable IPoIB CM

2007-08-31 Thread Joachim Fenkes
a) Report max_srq > 0 if SRQ is supported
b) Report "last wqe reached" event when base QP dies

Signed-off-by: Joachim Fenkes <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/ehca/ehca_hca.c |   10 +--
 drivers/infiniband/hw/ehca/ehca_irq.c |   48 +---
 2 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c 
b/drivers/infiniband/hw/ehca/ehca_hca.c
index fc19ef9..cf22472 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -93,9 +93,13 @@ int ehca_query_device(struct ib_device *ibdev, struct 
ib_device_attr *props)
props->max_pd  = min_t(int, rblock->max_pd, INT_MAX);
props->max_ah  = min_t(int, rblock->max_ah, INT_MAX);
props->max_fmr = min_t(int, rblock->max_mr, INT_MAX);
-   props->max_srq = 0;
-   props->max_srq_wr  = 0;
-   props->max_srq_sge = 0;
+
+   if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
+   props->max_srq = props->max_qp;
+   props->max_srq_wr  = props->max_qp_wr;
+   props->max_srq_sge = 3;
+   }
+
props->max_pkeys   = 16;
props->local_ca_ack_delay
= rblock->local_ca_ack_delay;
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c 
b/drivers/infiniband/hw/ehca/ehca_irq.c
index ee06d8b..a925ea5 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -175,41 +175,55 @@ error_data1:
 
 }
 
-static void qp_event_callback(struct ehca_shca *shca, u64 eqe,
- enum ib_event_type event_type, int fatal)
+static void dispatch_qp_event(struct ehca_shca *shca, struct ehca_qp *qp,
+ enum ib_event_type event_type)
 {
struct ib_event event;
-   struct ehca_qp *qp;
-   u32 token = EHCA_BMASK_GET(EQE_QP_TOKEN, eqe);
-
-   read_lock(&ehca_qp_idr_lock);
-   qp = idr_find(&ehca_qp_idr, token);
-   read_unlock(&ehca_qp_idr_lock);
-
-
-   if (!qp)
-   return;
-
-   if (fatal)
-   ehca_error_data(shca, qp, qp->ipz_qp_handle.handle);
 
event.device = &shca->ib_device;
+   event.event = event_type;
 
if (qp->ext_type == EQPT_SRQ) {
if (!qp->ib_srq.event_handler)
return;
 
-   event.event = fatal ? IB_EVENT_SRQ_ERR : event_type;
event.element.srq = &qp->ib_srq;
qp->ib_srq.event_handler(&event, qp->ib_srq.srq_context);
} else {
if (!qp->ib_qp.event_handler)
return;
 
-   event.event = event_type;
event.element.qp = &qp->ib_qp;
qp->ib_qp.event_handler(&event, qp->ib_qp.qp_context);
}
+}
+
+static void qp_event_callback(struct ehca_shca *shca, u64 eqe,
+ enum ib_event_type event_type, int fatal)
+{
+   struct ehca_qp *qp;
+   u32 token = EHCA_BMASK_GET(EQE_QP_TOKEN, eqe);
+
+   read_lock(&ehca_qp_idr_lock);
+   qp = idr_find(&ehca_qp_idr, token);
+   read_unlock(&ehca_qp_idr_lock);
+
+   if (!qp)
+   return;
+
+   if (fatal)
+   ehca_error_data(shca, qp, qp->ipz_qp_handle.handle);
+
+   dispatch_qp_event(shca, qp, fatal && qp->ext_type == EQPT_SRQ ?
+ IB_EVENT_SRQ_ERR : event_type);
+
+   /*
+* eHCA only processes one WQE at a time for SRQ base QPs,
+* so the last WQE has been processed as soon as the QP enters
+* error state.
+*/
+   if (fatal && qp->ext_type == EQPT_SRQBASE)
+   dispatch_qp_event(shca, qp, IB_EVENT_QP_LAST_WQE_REACHED);
 
return;
 }
-- 
1.5.2


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


  1   2   >