* [PATCH 0/5] ib/ehca: Fix stability issues
From: Alexander Schmidt @ 2008-08-12 12:49 UTC (permalink / raw)
To: linuxppc-dev, lkml, of-ewg, of-general, Roland Dreier
Cc: Joachim Fenkes, Stefan Roscher, Christoph Raisch,
Hoang-Nam Nguyen
Hi Roland,
the following patchset contains four small fixes and one bigger patch
(5/5) for addressing some ehca issues we found during cluster test.
[1/5] update qp_state on cached modify_qp()
[2/5] rename goto label in ehca_poll_cq_one()
[3/5] repoll on invalid opcode instead of returning success
[4/5] check idr_find() return value
[5/5] discard double CQE for one WR
They all apply on top of 2.6.27-rc1. If possible, we would like to get
them into 2.6.27.
Regards,
Alexander Schmidt
^ permalink raw reply
* [PATCH 1/5] ib/ehca: update qp_state on cached modify_qp()
From: Alexander Schmidt @ 2008-08-12 12:49 UTC (permalink / raw)
To: linuxppc-dev, lkml, of-ewg, of-general, Roland Dreier
Cc: Joachim Fenkes, Stefan Roscher, Christoph Raisch,
Hoang-Nam Nguyen
In-Reply-To: <20080812143542.0cbde755@BL3D1974.boeblingen.de.ibm.com>
Since the introduction of the port auto-detect mode for ehca, calls to
modify_qp() may be cached in the device driver when the ports are not
activated yet. When a modify_qp() call is cached, the qp state remains
untouched until the port is activated, which will leave the qp in the
reset state. In the reset state, however, it is not allowed to post SQ
WQEs, which confuses applications like ib_mad.
The solution for this problem is to immediately set the qp state as
requested by modify_qp(), even when the call is cached.
Signed-off-by: Alexander Schmidt <alexs@linux.vnet.ibm.com>
---
drivers/infiniband/hw/ehca/ehca_qp.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_qp.c
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -1534,8 +1534,6 @@ static int internal_modify_qp(struct ib_
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);
@@ -1551,6 +1549,8 @@ modify_qp_exit1:
int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int
attr_mask, struct ib_udata *udata)
{
+ int ret = 0;
+
struct ehca_shca *shca = container_of(ibqp->device, struct
ehca_shca, ib_device);
struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp,
ib_qp); @@ -1597,12 +1597,18 @@ int ehca_modify_qp(struct ib_qp *ibqp, s
attr->qp_state,
my_qp->init_attr.port_num, ibqp->qp_type);
spin_unlock_irqrestore(&sport->mod_sqp_lock,
flags);
- return 0;
+ goto out;
}
spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
}
- return internal_modify_qp(ibqp, attr, attr_mask, 0);
+ ret = internal_modify_qp(ibqp, attr, attr_mask, 0);
+
+out:
+ if ((ret == 0) && (attr_mask & IB_QP_STATE))
+ my_qp->state = attr->qp_state;
+
+ return ret;
}
void ehca_recover_sqp(struct ib_qp *sqp)
^ permalink raw reply
* [PATCH 2/5] ib/ehca: rename goto label
From: Alexander Schmidt @ 2008-08-12 12:49 UTC (permalink / raw)
To: linuxppc-dev, lkml, of-ewg, of-general, Roland Dreier
Cc: Joachim Fenkes, Stefan Roscher, Christoph Raisch,
Hoang-Nam Nguyen
In-Reply-To: <20080812143542.0cbde755@BL3D1974.boeblingen.de.ibm.com>
Rename the "poll_cq_one_read_cqe" goto label to what it actually does,
"repoll".
Signed-off-by: Alexander Schmidt <alexs@linux.vnet.ibm.com>
---
drivers/infiniband/hw/ehca/ehca_reqs.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -589,7 +589,7 @@ static inline int ehca_poll_cq_one(struc
struct ehca_qp *my_qp;
int cqe_count = 0, is_error;
-poll_cq_one_read_cqe:
+repoll:
cqe = (struct ehca_cqe *)
ipz_qeit_get_inc_valid(&my_cq->ipz_queue);
if (!cqe) {
@@ -617,7 +617,7 @@ poll_cq_one_read_cqe:
ehca_dmp(cqe, 64, "cq_num=%x qp_num=%x",
my_cq->cq_number,
cqe->local_qp_number); /* ignore this purged cqe */
- goto poll_cq_one_read_cqe;
+ goto repoll;
}
spin_lock_irqsave(&qp->spinlock_s, flags);
purgeflag = qp->sqerr_purgeflag;
@@ -636,7 +636,7 @@ poll_cq_one_read_cqe:
* that caused sqe and turn off purge flag
*/
qp->sqerr_purgeflag = 0;
- goto poll_cq_one_read_cqe;
+ goto repoll;
}
}
^ permalink raw reply
* [PATCH 5/5] ib/ehca: discard double CQE for one WR
From: Alexander Schmidt @ 2008-08-12 12:49 UTC (permalink / raw)
To: linuxppc-dev, lkml, of-ewg, of-general, Roland Dreier
Cc: Joachim Fenkes, Stefan Roscher, Christoph Raisch,
Hoang-Nam Nguyen
In-Reply-To: <20080812143542.0cbde755@BL3D1974.boeblingen.de.ibm.com>
Under rare circumstances, the ehca hardware might erroneously generate
two CQEs for the same WQE, which is not compliant to the IB spec and
will cause unpredictable errors like memory being freed twice. To avoid
this problem, the driver needs to detect the second CQE and discard it.
For this purpose, introduce an array holding as many elements as the SQ
of the QP, called sq_map. Each sq_map entry stores a "reported" flag
for one WQE in the SQ. When a work request is posted to the SQ, the
respective "reported" flag is set to zero. After the arrival of a CQE,
the flag is set to 1, which allows to detect the occurence of a second
CQE.
The mapping between WQE / CQE and the corresponding sq_map element is
implemented by replacing the lowest 16 Bits of the wr_id with the index
in the queue map. The original 16 Bits are stored in the sq_map entry
and are restored when the CQE is passed to the application.
Signed-off-by: Alexander Schmidt <alexs@linux.vnet.ibm.com>
---
drivers/infiniband/hw/ehca/ehca_classes.h | 9 +++++
drivers/infiniband/hw/ehca/ehca_qes.h | 1
drivers/infiniband/hw/ehca/ehca_qp.c | 34 +++++++++++++-----
drivers/infiniband/hw/ehca/ehca_reqs.c | 54
+++++++++++++++++++++++------- 4 files changed, 78 insertions(+), 20
deletions(-)
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -139,6 +139,7 @@ static void trace_send_wr_ud(const struc
static inline int ehca_write_swqe(struct ehca_qp *qp,
struct ehca_wqe *wqe_p,
const struct ib_send_wr *send_wr,
+ u32 sq_map_idx,
int hidden)
{
u32 idx;
@@ -157,7 +158,11 @@ static inline int ehca_write_swqe(struct
/* clear wqe header until sglist */
memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list));
- wqe_p->work_request_id = send_wr->wr_id;
+ wqe_p->work_request_id = send_wr->wr_id & ~QMAP_IDX_MASK;
+ wqe_p->work_request_id |= sq_map_idx & QMAP_IDX_MASK;
+
+ qp->sq_map[sq_map_idx].app_wr_id = send_wr->wr_id &
QMAP_IDX_MASK;
+ qp->sq_map[sq_map_idx].reported = 0;
switch (send_wr->opcode) {
case IB_WR_SEND:
@@ -381,6 +386,7 @@ static inline int post_one_send(struct e
{
struct ehca_wqe *wqe_p;
int ret;
+ u32 sq_map_idx;
u64 start_offset = my_qp->ipz_squeue.current_q_offset;
/* get pointer next to free WQE */
@@ -393,8 +399,15 @@ static inline int post_one_send(struct e
"qp_num=%x", my_qp->ib_qp.qp_num);
return -ENOMEM;
}
+
+ /*
+ * Get the index of the WQE in the send queue. The same index
is used
+ * for writing into the sq_map.
+ */
+ sq_map_idx = start_offset / my_qp->ipz_squeue.qe_size;
+
/* write a SEND WQE into the QUEUE */
- ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr, hidden);
+ ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr, sq_map_idx,
hidden); /*
* if something failed,
* reset the free entry pointer to the start value
@@ -654,8 +667,34 @@ repoll:
my_cq, my_cq->cq_number);
}
- /* we got a completion! */
- wc->wr_id = cqe->work_request_id;
+ read_lock(&ehca_qp_idr_lock);
+ my_qp = idr_find(&ehca_qp_idr, cqe->qp_token);
+ read_unlock(&ehca_qp_idr_lock);
+ if (!my_qp)
+ goto repoll;
+ wc->qp = &my_qp->ib_qp;
+
+ if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT)) {
+ struct ehca_qmap_entry *qmap_entry;
+ /*
+ * We got a send completion and need to restore the
original
+ * wr_id.
+ */
+ qmap_entry = &my_qp->sq_map[cqe->work_request_id &
+ QMAP_IDX_MASK];
+
+ if (qmap_entry->reported) {
+ ehca_warn(cq->device, "Double cqe on
qp_num=%#x",
+ my_qp->real_qp_num);
+ /* found a double cqe, discard it and read
next one */
+ goto repoll;
+ }
+ wc->wr_id = cqe->work_request_id & ~QMAP_IDX_MASK;
+ wc->wr_id |= qmap_entry->app_wr_id;
+ qmap_entry->reported = 1;
+ } else
+ /* We got a receive completion. */
+ wc->wr_id = cqe->work_request_id;
/* eval ib_wc_opcode */
wc->opcode = ib_wc_opcode[cqe->optype]-1;
@@ -678,13 +717,6 @@ repoll:
} else
wc->status = IB_WC_SUCCESS;
- read_lock(&ehca_qp_idr_lock);
- my_qp = idr_find(&ehca_qp_idr, cqe->qp_token);
- read_unlock(&ehca_qp_idr_lock);
- if (!my_qp)
- goto repoll;
- wc->qp = &my_qp->ib_qp;
-
wc->byte_len = cqe->nr_bytes_transferred;
wc->pkey_index = cqe->pkey_index;
wc->slid = cqe->rlid;
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_classes.h
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -156,6 +156,14 @@ struct ehca_mod_qp_parm {
#define EHCA_MOD_QP_PARM_MAX 4
+#define QMAP_IDX_MASK 0xFFFFULL
+
+/* struct for tracking if cqes have been reported to the application */
+struct ehca_qmap_entry {
+ u16 app_wr_id;
+ u16 reported;
+};
+
struct ehca_qp {
union {
struct ib_qp ib_qp;
@@ -165,6 +173,7 @@ struct ehca_qp {
enum ehca_ext_qp_type ext_type;
enum ib_qp_state state;
struct ipz_queue ipz_squeue;
+ struct ehca_qmap_entry *sq_map;
struct ipz_queue ipz_rqueue;
struct h_galpas galpas;
u32 qkey;
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_qp.c
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -412,6 +412,7 @@ static struct ehca_qp *internal_create_q
struct ehca_shca *shca = container_of(pd->device, struct
ehca_shca, ib_device);
struct ib_ucontext *context = NULL;
+ u32 nr_qes;
u64 h_ret;
int is_llqp = 0, has_srq = 0;
int qp_type, max_send_sge, max_recv_sge, ret;
@@ -715,6 +716,15 @@ static struct ehca_qp *internal_create_q
"and pages ret=%i", ret);
goto create_qp_exit2;
}
+ nr_qes = my_qp->ipz_squeue.queue_length /
+ my_qp->ipz_squeue.qe_size;
+ my_qp->sq_map = vmalloc(nr_qes *
+ sizeof(struct
ehca_qmap_entry));
+ if (!my_qp->sq_map) {
+ ehca_err(pd->device, "Couldn't allocate squeue
"
+ "map ret=%i", ret);
+ goto create_qp_exit3;
+ }
}
if (HAS_RQ(my_qp)) {
@@ -724,7 +734,7 @@ static struct ehca_qp *internal_create_q
if (ret) {
ehca_err(pd->device, "Couldn't initialize
rqueue " "and pages ret=%i", ret);
- goto create_qp_exit3;
+ goto create_qp_exit4;
}
}
@@ -770,7 +780,7 @@ static struct ehca_qp *internal_create_q
if (!my_qp->mod_qp_parm) {
ehca_err(pd->device,
"Could not alloc
mod_qp_parm");
- goto create_qp_exit4;
+ goto create_qp_exit5;
}
}
}
@@ -780,7 +790,7 @@ static struct ehca_qp *internal_create_q
h_ret = ehca_define_sqp(shca, my_qp, init_attr);
if (h_ret != H_SUCCESS) {
ret = ehca2ib_return_code(h_ret);
- goto create_qp_exit5;
+ goto create_qp_exit6;
}
}
@@ -789,7 +799,7 @@ static struct ehca_qp *internal_create_q
if (ret) {
ehca_err(pd->device,
"Couldn't assign qp to send_cq
ret=%i", ret);
- goto create_qp_exit5;
+ goto create_qp_exit6;
}
}
@@ -815,22 +825,26 @@ static struct ehca_qp *internal_create_q
if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
ehca_err(pd->device, "Copy to udata failed");
ret = -EINVAL;
- goto create_qp_exit6;
+ goto create_qp_exit7;
}
}
return my_qp;
-create_qp_exit6:
+create_qp_exit7:
ehca_cq_unassign_qp(my_qp->send_cq, my_qp->real_qp_num);
-create_qp_exit5:
+create_qp_exit6:
kfree(my_qp->mod_qp_parm);
-create_qp_exit4:
+create_qp_exit5:
if (HAS_RQ(my_qp))
ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
+create_qp_exit4:
+ if (HAS_SQ(my_qp))
+ vfree(my_qp->sq_map);
+
create_qp_exit3:
if (HAS_SQ(my_qp))
ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
@@ -1979,8 +1993,10 @@ static int internal_destroy_qp(struct ib
if (HAS_RQ(my_qp))
ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
- if (HAS_SQ(my_qp))
+ if (HAS_SQ(my_qp)) {
ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
+ vfree(my_qp->sq_map);
+ }
kmem_cache_free(qp_cache, my_qp);
atomic_dec(&shca->num_qps);
return 0;
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_qes.h
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_qes.h
@@ -213,6 +213,7 @@ struct ehca_wqe {
#define WC_STATUS_ERROR_BIT 0x80000000
#define WC_STATUS_REMOTE_ERROR_FLAGS 0x0000F800
#define WC_STATUS_PURGE_BIT 0x10
+#define WC_SEND_RECEIVE_BIT 0x80
struct ehca_cqe {
u64 work_request_id;
^ permalink raw reply
* [PATCH 3/5] ib/ehca: repoll on invalid opcode
From: Alexander Schmidt @ 2008-08-12 12:49 UTC (permalink / raw)
To: linuxppc-dev, lkml, of-ewg, of-general, Roland Dreier
Cc: Joachim Fenkes, Stefan Roscher, Christoph Raisch,
Hoang-Nam Nguyen
In-Reply-To: <20080812143542.0cbde755@BL3D1974.boeblingen.de.ibm.com>
When the ehca driver detects an invalid opcode in a CQE, it currently
passes the CQE to the application and returns with success. This patch
changes the CQE handling to discard CQEs with invalid opcodes and to
continue reading the next CQE from the CQ.
Signed-off-by: Alexander Schmidt <alexs@linux.vnet.ibm.com>
---
drivers/infiniband/hw/ehca/ehca_reqs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -667,7 +667,7 @@ repoll:
ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x",
my_cq, my_cq->cq_number);
/* update also queue adder to throw away this entry!!!
*/
- goto poll_cq_one_exit0;
+ goto repoll;
}
/* eval ib_wc_status */
^ permalink raw reply
* [PATCH 4/5] ib/ehca: check idr_find() return value
From: Alexander Schmidt @ 2008-08-12 12:49 UTC (permalink / raw)
To: linuxppc-dev, lkml, of-ewg, of-general, Roland Dreier
Cc: Joachim Fenkes, Stefan Roscher, Christoph Raisch,
Hoang-Nam Nguyen
In-Reply-To: <20080812143542.0cbde755@BL3D1974.boeblingen.de.ibm.com>
The idr_find() function may fail when trying to get the QP that is
associated with a CQE, e.g. when a QP has been destroyed between the
generation of a CQE and the poll request for it. In consequence, the
return value of idr_find() must be checked and the CQE must be
discarded when the QP cannot be found.
Signed-off-by: Alexander Schmidt <alexs@linux.vnet.ibm.com>
---
drivers/infiniband/hw/ehca/ehca_reqs.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -680,8 +680,10 @@ repoll:
read_lock(&ehca_qp_idr_lock);
my_qp = idr_find(&ehca_qp_idr, cqe->qp_token);
- wc->qp = &my_qp->ib_qp;
read_unlock(&ehca_qp_idr_lock);
+ if (!my_qp)
+ goto repoll;
+ wc->qp = &my_qp->ib_qp;
wc->byte_len = cqe->nr_bytes_transferred;
wc->pkey_index = cqe->pkey_index;
^ permalink raw reply
* [PATCH 1/5 try2] ib/ehca: update qp_state on cached modify_qp()
From: Alexander Schmidt @ 2008-08-12 13:46 UTC (permalink / raw)
To: Roland Dreier, of-ewg, of-general, lkml, linuxppc-dev
Cc: Joachim Fenkes, Stefan Roscher, Christoph Raisch
Since the introduction of the port auto-detect mode for ehca, calls to
modify_qp() may be cached in the device driver when the ports are not
activated yet. When a modify_qp() call is cached, the qp state remains
untouched until the port is activated, which will leave the qp in the reset
state. In the reset state, however, it is not allowed to post SQ WQEs,
which confuses applications like ib_mad.
The solution for this problem is to immediately set the qp state as requested
by modify_qp(), even when the call is cached.
Signed-off-by: Alexander Schmidt <alexs@linux.vnet.ibm.com>
---
drivers/infiniband/hw/ehca/ehca_qp.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_qp.c
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -1534,8 +1534,6 @@ static int internal_modify_qp(struct ib_
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);
@@ -1551,6 +1549,8 @@ modify_qp_exit1:
int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
struct ib_udata *udata)
{
+ int ret = 0;
+
struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
ib_device);
struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
@@ -1597,12 +1597,18 @@ int ehca_modify_qp(struct ib_qp *ibqp, s
attr->qp_state, my_qp->init_attr.port_num,
ibqp->qp_type);
spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
- return 0;
+ goto out;
}
spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
}
- return internal_modify_qp(ibqp, attr, attr_mask, 0);
+ ret = internal_modify_qp(ibqp, attr, attr_mask, 0);
+
+out:
+ if ((ret == 0) && (attr_mask & IB_QP_STATE))
+ my_qp->state = attr->qp_state;
+
+ return ret;
}
void ehca_recover_sqp(struct ib_qp *sqp)
^ permalink raw reply
* [PATCH 0/5 try2] ib/ehca: Fix stability issues
From: Alexander Schmidt @ 2008-08-12 13:46 UTC (permalink / raw)
To: Roland Dreier, of-ewg, of-general, lkml, linuxppc-dev
Cc: Joachim Fenkes, Stefan Roscher, Christoph Raisch
Hi Roland,
Sorry, the first set was mangled because of a broken mailer, so here it is
again, double checked...
the following patchset contains four small fixes and one bigger patch
(5/5) for addressing some ehca issues we found during cluster test.
[1/5] update qp_state on cached modify_qp()
[2/5] rename goto label in ehca_poll_cq_one()
[3/5] repoll on invalid opcode instead of returning success
[4/5] check idr_find() return value
[5/5] discard double CQE for one WR
They all apply on top of 2.6.27-rc1. If possible, we would like to get
them into 2.6.27.
Regards,
Alexander Schmidt
^ permalink raw reply
* [PATCH 4/5 try2] ib/ehca: check idr_find() return value
From: Alexander Schmidt @ 2008-08-12 13:46 UTC (permalink / raw)
To: Roland Dreier, of-ewg, of-general, lkml, linuxppc-dev
Cc: Joachim Fenkes, Stefan Roscher, Christoph Raisch
The idr_find() function may fail when trying to get the QP that is associated
with a CQE, e.g. when a QP has been destroyed between the generation of a CQE
and the poll request for it. In consequence, the return value of idr_find()
must be checked and the CQE must be discarded when the QP cannot be found.
Signed-off-by: Alexander Schmidt <alexs@linux.vnet.ibm.com>
---
drivers/infiniband/hw/ehca/ehca_reqs.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -680,8 +680,10 @@ repoll:
read_lock(&ehca_qp_idr_lock);
my_qp = idr_find(&ehca_qp_idr, cqe->qp_token);
- wc->qp = &my_qp->ib_qp;
read_unlock(&ehca_qp_idr_lock);
+ if (!my_qp)
+ goto repoll;
+ wc->qp = &my_qp->ib_qp;
wc->byte_len = cqe->nr_bytes_transferred;
wc->pkey_index = cqe->pkey_index;
^ permalink raw reply
* [PATCH 3/5 try2] ib/ehca: repoll on invalid opcode
From: Alexander Schmidt @ 2008-08-12 13:46 UTC (permalink / raw)
To: Roland Dreier, of-ewg, of-general, lkml, linuxppc-dev
Cc: Joachim Fenkes, Stefan Roscher, Christoph Raisch
When the ehca driver detects an invalid opcode in a CQE, it currently passes
the CQE to the application and returns with success. This patch changes the
CQE handling to discard CQEs with invalid opcodes and to continue reading the
next CQE from the CQ.
Signed-off-by: Alexander Schmidt <alexs@linux.vnet.ibm.com>
---
drivers/infiniband/hw/ehca/ehca_reqs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -667,7 +667,7 @@ repoll:
ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x",
my_cq, my_cq->cq_number);
/* update also queue adder to throw away this entry!!! */
- goto poll_cq_one_exit0;
+ goto repoll;
}
/* eval ib_wc_status */
^ permalink raw reply
* [PATCH 5/5 try2] ib/ehca: discard double CQE for one WR
From: Alexander Schmidt @ 2008-08-12 13:46 UTC (permalink / raw)
To: Roland Dreier, of-ewg, of-general, lkml, linuxppc-dev
Cc: Joachim Fenkes, Stefan Roscher, Christoph Raisch
Under rare circumstances, the ehca hardware might erroneously generate
two CQEs for the same WQE, which is not compliant to the IB spec and will
cause unpredictable errors like memory being freed twice. To avoid this
problem, the driver needs to detect the second CQE and discard it.
For this purpose, introduce an array holding as many elements as the SQ of
the QP, called sq_map. Each sq_map entry stores a "reported" flag for one
WQE in the SQ. When a work request is posted to the SQ, the respective
"reported" flag is set to zero. After the arrival of a CQE, the flag is set
to 1, which allows to detect the occurence of a second CQE.
The mapping between WQE / CQE and the corresponding sq_map element is
implemented by replacing the lowest 16 Bits of the wr_id with the index in
the queue map. The original 16 Bits are stored in the sq_map entry and are
restored when the CQE is passed to the application.
Signed-off-by: Alexander Schmidt <alexs@linux.vnet.ibm.com>
---
drivers/infiniband/hw/ehca/ehca_classes.h | 9 +++++
drivers/infiniband/hw/ehca/ehca_qes.h | 1
drivers/infiniband/hw/ehca/ehca_qp.c | 34 +++++++++++++-----
drivers/infiniband/hw/ehca/ehca_reqs.c | 54 +++++++++++++++++++++++-------
4 files changed, 78 insertions(+), 20 deletions(-)
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -139,6 +139,7 @@ static void trace_send_wr_ud(const struc
static inline int ehca_write_swqe(struct ehca_qp *qp,
struct ehca_wqe *wqe_p,
const struct ib_send_wr *send_wr,
+ u32 sq_map_idx,
int hidden)
{
u32 idx;
@@ -157,7 +158,11 @@ static inline int ehca_write_swqe(struct
/* clear wqe header until sglist */
memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list));
- wqe_p->work_request_id = send_wr->wr_id;
+ wqe_p->work_request_id = send_wr->wr_id & ~QMAP_IDX_MASK;
+ wqe_p->work_request_id |= sq_map_idx & QMAP_IDX_MASK;
+
+ qp->sq_map[sq_map_idx].app_wr_id = send_wr->wr_id & QMAP_IDX_MASK;
+ qp->sq_map[sq_map_idx].reported = 0;
switch (send_wr->opcode) {
case IB_WR_SEND:
@@ -381,6 +386,7 @@ static inline int post_one_send(struct e
{
struct ehca_wqe *wqe_p;
int ret;
+ u32 sq_map_idx;
u64 start_offset = my_qp->ipz_squeue.current_q_offset;
/* get pointer next to free WQE */
@@ -393,8 +399,15 @@ static inline int post_one_send(struct e
"qp_num=%x", my_qp->ib_qp.qp_num);
return -ENOMEM;
}
+
+ /*
+ * Get the index of the WQE in the send queue. The same index is used
+ * for writing into the sq_map.
+ */
+ sq_map_idx = start_offset / my_qp->ipz_squeue.qe_size;
+
/* write a SEND WQE into the QUEUE */
- ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr, hidden);
+ ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr, sq_map_idx, hidden);
/*
* if something failed,
* reset the free entry pointer to the start value
@@ -654,8 +667,34 @@ repoll:
my_cq, my_cq->cq_number);
}
- /* we got a completion! */
- wc->wr_id = cqe->work_request_id;
+ read_lock(&ehca_qp_idr_lock);
+ my_qp = idr_find(&ehca_qp_idr, cqe->qp_token);
+ read_unlock(&ehca_qp_idr_lock);
+ if (!my_qp)
+ goto repoll;
+ wc->qp = &my_qp->ib_qp;
+
+ if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT)) {
+ struct ehca_qmap_entry *qmap_entry;
+ /*
+ * We got a send completion and need to restore the original
+ * wr_id.
+ */
+ qmap_entry = &my_qp->sq_map[cqe->work_request_id &
+ QMAP_IDX_MASK];
+
+ if (qmap_entry->reported) {
+ ehca_warn(cq->device, "Double cqe on qp_num=%#x",
+ my_qp->real_qp_num);
+ /* found a double cqe, discard it and read next one */
+ goto repoll;
+ }
+ wc->wr_id = cqe->work_request_id & ~QMAP_IDX_MASK;
+ wc->wr_id |= qmap_entry->app_wr_id;
+ qmap_entry->reported = 1;
+ } else
+ /* We got a receive completion. */
+ wc->wr_id = cqe->work_request_id;
/* eval ib_wc_opcode */
wc->opcode = ib_wc_opcode[cqe->optype]-1;
@@ -678,13 +717,6 @@ repoll:
} else
wc->status = IB_WC_SUCCESS;
- read_lock(&ehca_qp_idr_lock);
- my_qp = idr_find(&ehca_qp_idr, cqe->qp_token);
- read_unlock(&ehca_qp_idr_lock);
- if (!my_qp)
- goto repoll;
- wc->qp = &my_qp->ib_qp;
-
wc->byte_len = cqe->nr_bytes_transferred;
wc->pkey_index = cqe->pkey_index;
wc->slid = cqe->rlid;
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_classes.h
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -156,6 +156,14 @@ struct ehca_mod_qp_parm {
#define EHCA_MOD_QP_PARM_MAX 4
+#define QMAP_IDX_MASK 0xFFFFULL
+
+/* struct for tracking if cqes have been reported to the application */
+struct ehca_qmap_entry {
+ u16 app_wr_id;
+ u16 reported;
+};
+
struct ehca_qp {
union {
struct ib_qp ib_qp;
@@ -165,6 +173,7 @@ struct ehca_qp {
enum ehca_ext_qp_type ext_type;
enum ib_qp_state state;
struct ipz_queue ipz_squeue;
+ struct ehca_qmap_entry *sq_map;
struct ipz_queue ipz_rqueue;
struct h_galpas galpas;
u32 qkey;
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_qp.c
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -412,6 +412,7 @@ static struct ehca_qp *internal_create_q
struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
ib_device);
struct ib_ucontext *context = NULL;
+ u32 nr_qes;
u64 h_ret;
int is_llqp = 0, has_srq = 0;
int qp_type, max_send_sge, max_recv_sge, ret;
@@ -715,6 +716,15 @@ static struct ehca_qp *internal_create_q
"and pages ret=%i", ret);
goto create_qp_exit2;
}
+ nr_qes = my_qp->ipz_squeue.queue_length /
+ my_qp->ipz_squeue.qe_size;
+ my_qp->sq_map = vmalloc(nr_qes *
+ sizeof(struct ehca_qmap_entry));
+ if (!my_qp->sq_map) {
+ ehca_err(pd->device, "Couldn't allocate squeue "
+ "map ret=%i", ret);
+ goto create_qp_exit3;
+ }
}
if (HAS_RQ(my_qp)) {
@@ -724,7 +734,7 @@ static struct ehca_qp *internal_create_q
if (ret) {
ehca_err(pd->device, "Couldn't initialize rqueue "
"and pages ret=%i", ret);
- goto create_qp_exit3;
+ goto create_qp_exit4;
}
}
@@ -770,7 +780,7 @@ static struct ehca_qp *internal_create_q
if (!my_qp->mod_qp_parm) {
ehca_err(pd->device,
"Could not alloc mod_qp_parm");
- goto create_qp_exit4;
+ goto create_qp_exit5;
}
}
}
@@ -780,7 +790,7 @@ static struct ehca_qp *internal_create_q
h_ret = ehca_define_sqp(shca, my_qp, init_attr);
if (h_ret != H_SUCCESS) {
ret = ehca2ib_return_code(h_ret);
- goto create_qp_exit5;
+ goto create_qp_exit6;
}
}
@@ -789,7 +799,7 @@ static struct ehca_qp *internal_create_q
if (ret) {
ehca_err(pd->device,
"Couldn't assign qp to send_cq ret=%i", ret);
- goto create_qp_exit5;
+ goto create_qp_exit6;
}
}
@@ -815,22 +825,26 @@ static struct ehca_qp *internal_create_q
if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
ehca_err(pd->device, "Copy to udata failed");
ret = -EINVAL;
- goto create_qp_exit6;
+ goto create_qp_exit7;
}
}
return my_qp;
-create_qp_exit6:
+create_qp_exit7:
ehca_cq_unassign_qp(my_qp->send_cq, my_qp->real_qp_num);
-create_qp_exit5:
+create_qp_exit6:
kfree(my_qp->mod_qp_parm);
-create_qp_exit4:
+create_qp_exit5:
if (HAS_RQ(my_qp))
ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
+create_qp_exit4:
+ if (HAS_SQ(my_qp))
+ vfree(my_qp->sq_map);
+
create_qp_exit3:
if (HAS_SQ(my_qp))
ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
@@ -1979,8 +1993,10 @@ static int internal_destroy_qp(struct ib
if (HAS_RQ(my_qp))
ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
- if (HAS_SQ(my_qp))
+ if (HAS_SQ(my_qp)) {
ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
+ vfree(my_qp->sq_map);
+ }
kmem_cache_free(qp_cache, my_qp);
atomic_dec(&shca->num_qps);
return 0;
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_qes.h
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_qes.h
@@ -213,6 +213,7 @@ struct ehca_wqe {
#define WC_STATUS_ERROR_BIT 0x80000000
#define WC_STATUS_REMOTE_ERROR_FLAGS 0x0000F800
#define WC_STATUS_PURGE_BIT 0x10
+#define WC_SEND_RECEIVE_BIT 0x80
struct ehca_cqe {
u64 work_request_id;
^ permalink raw reply
* [PATCH 2/5 try2] ib/ehca: rename goto label
From: Alexander Schmidt @ 2008-08-12 13:46 UTC (permalink / raw)
To: Roland Dreier, of-ewg, of-general, lkml, linuxppc-dev
Cc: Joachim Fenkes, Stefan Roscher, Christoph Raisch
Rename the "poll_cq_one_read_cqe" goto label to what it actually does,
"repoll".
Signed-off-by: Alexander Schmidt <alexs@linux.vnet.ibm.com>
---
drivers/infiniband/hw/ehca/ehca_reqs.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -589,7 +589,7 @@ static inline int ehca_poll_cq_one(struc
struct ehca_qp *my_qp;
int cqe_count = 0, is_error;
-poll_cq_one_read_cqe:
+repoll:
cqe = (struct ehca_cqe *)
ipz_qeit_get_inc_valid(&my_cq->ipz_queue);
if (!cqe) {
@@ -617,7 +617,7 @@ poll_cq_one_read_cqe:
ehca_dmp(cqe, 64, "cq_num=%x qp_num=%x",
my_cq->cq_number, cqe->local_qp_number);
/* ignore this purged cqe */
- goto poll_cq_one_read_cqe;
+ goto repoll;
}
spin_lock_irqsave(&qp->spinlock_s, flags);
purgeflag = qp->sqerr_purgeflag;
@@ -636,7 +636,7 @@ poll_cq_one_read_cqe:
* that caused sqe and turn off purge flag
*/
qp->sqerr_purgeflag = 0;
- goto poll_cq_one_read_cqe;
+ goto repoll;
}
}
^ permalink raw reply
* Re: [PATCH] pata_of_platform: fix no irq handling
From: Steven A. Falco @ 2008-08-12 14:00 UTC (permalink / raw)
To: benh; +Cc: linuxppc-dev, Jeff Garzik, Sparks, Sam, linux-ide
In-Reply-To: <1218492032.8041.11.camel@pasglop>
[-- Attachment #1: Type: text/plain, Size: 2206 bytes --]
Benjamin Herrenschmidt wrote:
>
>> 1. IDE status read does not work. (But am I understand correctly
>> that IDE works well if IRQ is unspecified? Then this is hardly
>> an issue.)
>> 2. IDE interrupt comes when it should not. I'd recommend to use
>> oscilloscope to find out what is happening there, that is, if
>> the drive actually deasserts its irq line after status read.
>> If so, than this could be a PIC problem.
>>
>> What is the platform on which you're observing the issue, btw?
>>
>
> Another possibility is that you got the wrong interrupt number
> in the device-tree...
>
> Ben.
>
The platform is the AMCC Sequoia board. We've built a little adapter to
connect a compact flash card to the processor bus. I believe the
interrupt selection in the device tree is correct, and I've checked over
the u-boot settings for the IRQ line (active high, level sensitive).
I've also tried edge-sensitive but it doesn't make a difference.
When u-boot queries the CF card, we see the IRQ pulse as expected, but
when the kernel runs, we see the IRQ go high and stay there, which the
kernel naturally treats as a stuck interrupt. The other oddity is that
we see a single diagnostic failure on startup:
ata1.00: Drive reports diagnostics failure. This may indicate a drive
ata1.00: fault or invalid emulation. Contact drive vendor for
information.
That is strange, because if we manually do the soft reset from u-boot,
we see the ATA "feature byte" return 0x01, which means success. When
the kernel does the soft reset, we see a 0x00, which means failure. You
would think it is timing related, but a logic analyzer trace shows
reasonable timing. We need to wire up a better test rig, so I don't
want folks on this list to waste any time on it. I'll report back if I
learn anything of general interest.
With the interrupt disabled in the device tree, and ignoring the
diagnostics failure, the drive actually works. I'm able to mount a
filesystem, read files from it, etc. So, the drive is fully functional,
just without using interrupts. Therefore, I believe most everything is
correct - byte lanes, read/write signaling, timing, etc. Curious.
Steve
[-- Attachment #2: Type: text/html, Size: 2699 bytes --]
^ permalink raw reply
* Re: [RFC 1/3] add support for exporting symbols from .S files
From: Arnd Bergmann @ 2008-08-12 13:58 UTC (permalink / raw)
To: Stephen Rothwell
Cc: linux-arch, Matthew Wilcox, Rusty Russell, linux-kernel,
linuxppc-dev, Al Viro, David Woodhouse
In-Reply-To: <20080812164352.ddcf1ef5.sfr@canb.auug.org.au>
This makes it possible to export symbols from assembly files, instead
of having to export them through an extra ksyms.c file.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
On Tuesday 12 August 2008, Stephen Rothwell wrote:
> This won't be portable across architectures as .align is sometimes in
> bytes and sometimes a power of two. You can use .balign or .p2align
> portably on gas, though.
Ok, this version uses the .balign as suggested by rusty, and also
fixes building with modversions turned on, which did not work in the
first version.
Arnd <><
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -1,5 +1,7 @@
#ifndef _LINUX_MODULE_H
#define _LINUX_MODULE_H
+
+#ifndef __ASSEMBLY__
/*
* Dynamic loading of modules into the kernel.
*
@@ -605,4 +607,72 @@ static inline void module_remove_modinfo_attrs(struct module *mod)
#define __MODULE_STRING(x) __stringify(x)
+#else /* __ASSEMBLY__ */
+#include <asm/types.h>
+
+#ifdef CONFIG_MODULES
+.macro __EXPORT_SYMBOL sym section symtab strtab crctab crc
+ .section \section, "a", @progbits
+ .type \symtab, @object
+ .balign BITS_PER_LONG/8
+\symtab:
+ .ifeq BITS_PER_LONG - 32
+ .long \sym
+ .long \strtab
+ .else
+ .quad \sym
+ .quad \strtab
+ .endif
+ .size \symtab, . - \symtab
+ .previous
+
+ .section __ksymtab_strings, "a", @progbits
+ .type \strtab, @object
+\strtab:
+ .string "\sym"
+ .size \strtab, . - \strtab
+ .previous
+
+#ifdef CONFIG_MODVERSIONS
+ /*
+ * Modversions doesn't work with assembly files,
+ * so insert a dummy CRC.
+ */
+ .section __kcrctab, "a", @progbits
+ .balign 4
+ .type \crctab, @object
+\crctab:
+ .long \crc
+ .size \crctab, . - \crctab
+ .set \crc, 0
+ .previous
+#endif
+ .endm
+
+#define EXPORT_SYMBOL(sym) \
+ __EXPORT_SYMBOL sym, __ksymtab, __ksymtab_ ## sym, \
+ __kstrtab_ ## sym, __kcrctab_ ## sym, __crc_ ## sym
+#define EXPORT_SYMBOL_GPL(sym) \
+ __EXPORT_SYMBOL sym, __ksymtab_gpl, __ksymtab_ ## sym, \
+ __kstrtab_ ## sym, __kcrctab_ ## sym, __crc_ ## sym
+#define EXPORT_SYMBOL_GPL_FUTURE(sym) \
+ __EXPORT_SYMBOL sym, __ksymtab_gpl_future, __ksymtab_ ## sym, \
+ __kstrtab_ ## sym, __kcrctab_ ## sym, __crc_ ## sym
+#define EXPORT_UNUSED_SYMBOL(sym) \
+ __EXPORT_SYMBOL sym, __ksymtab_unused, __ksymtab_ ## sym, \
+ __kstrtab_ ## sym, __kcrctab_ ## sym, __crc_ ## sym
+#define EXPORT_UNUSED_SYMBOL_GPL(sym) \
+ __EXPORT_SYMBOL sym, __ksymtab_unused_gpl, __ksymtab_ ## sym, \
+ __kstrtab_ ## sym, __kcrctab_ ## sym, __crc_ ## sym
+
+#else /* CONFIG_MODULES... */
+#define EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_GPL(sym)
+#define EXPORT_SYMBOL_GPL_FUTURE(sym)
+#define EXPORT_UNUSED_SYMBOL(sym)
+#define EXPORT_UNUSED_SYMBOL_GPL(sym)
+#endif /* !CONFIG_MODULES... */
+
+#endif /* __ASSEMBLY__ */
+
#endif /* _LINUX_MODULE_H */
^ permalink raw reply
* Re: [PATCH] pata_of_platform: fix no irq handling
From: Anton Vorontsov @ 2008-08-12 14:04 UTC (permalink / raw)
To: Steven A. Falco; +Cc: linux-ide, Jeff Garzik, Sparks, Sam, linuxppc-dev
In-Reply-To: <48A19788.6050502@harris.com>
On Tue, Aug 12, 2008 at 10:00:40AM -0400, Steven A. Falco wrote:
> Benjamin Herrenschmidt wrote:
> >
> >> 1. IDE status read does not work. (But am I understand correctly
> >> that IDE works well if IRQ is unspecified? Then this is hardly
> >> an issue.)
> >> 2. IDE interrupt comes when it should not. I'd recommend to use
> >> oscilloscope to find out what is happening there, that is, if
> >> the drive actually deasserts its irq line after status read.
> >> If so, than this could be a PIC problem.
> >>
> >> What is the platform on which you're observing the issue, btw?
> >>
> >
> > Another possibility is that you got the wrong interrupt number
> > in the device-tree...
> >
> > Ben.
> >
>
> The platform is the AMCC Sequoia board. We've built a little adapter to
> connect a compact flash card to the processor bus. I believe the
> interrupt selection in the device tree is correct, and I've checked over
> the u-boot settings for the IRQ line (active high, level sensitive).
IDE IRQs are active-low.
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: [PATCH] pata_of_platform: fix no irq handling
From: Stefan Roese @ 2008-08-12 14:18 UTC (permalink / raw)
To: linuxppc-dev, avorontsov; +Cc: linux-ide, Jeff Garzik, Sparks, Sam
In-Reply-To: <20080812140457.GA9103@oksana.dev.rtsoft.ru>
On Tuesday 12 August 2008, Anton Vorontsov wrote:
> > > Another possibility is that you got the wrong interrupt number
> > > in the device-tree...
> > >
> > > Ben.
> >
> > The platform is the AMCC Sequoia board. We've built a little adapter to
> > connect a compact flash card to the processor bus. I believe the
> > interrupt selection in the device tree is correct, and I've checked over
> > the u-boot settings for the IRQ line (active high, level sensitive).
>
> IDE IRQs are active-low.
IIRC, the CompactFlash interrupt is active-high.
Best regards,
Stefan
^ permalink raw reply
* Re: [PATCH] pata_of_platform: fix no irq handling
From: Sergei Shtylyov @ 2008-08-12 14:18 UTC (permalink / raw)
To: avorontsov; +Cc: linux-ide, Jeff Garzik, Sparks, Sam, linuxppc-dev
In-Reply-To: <20080812140457.GA9103@oksana.dev.rtsoft.ru>
Anton Vorontsov wrote:
>>>>1. IDE status read does not work. (But am I understand correctly
>>>> that IDE works well if IRQ is unspecified? Then this is hardly
>>>> an issue.)
>>>>2. IDE interrupt comes when it should not. I'd recommend to use
>>>> oscilloscope to find out what is happening there, that is, if
>>>> the drive actually deasserts its irq line after status read.
>>>> If so, than this could be a PIC problem.
>>>>What is the platform on which you're observing the issue, btw?
>>>Another possibility is that you got the wrong interrupt number
>>>in the device-tree...
>>>Ben.
>>The platform is the AMCC Sequoia board. We've built a little adapter to
>>connect a compact flash card to the processor bus. I believe the
>>interrupt selection in the device tree is correct, and I've checked over
>>the u-boot settings for the IRQ line (active high, level sensitive).
> IDE IRQs are active-low.
Only on the PCI and only in the native mode. Natively, the IDE INTRQ
signal is active-high, rising edge triggering, as on ISA. You seem to have an
invertor somewhere, if it's not a PCI chip...
WBR, Sergei
^ permalink raw reply
* Re: [PATCH] pata_of_platform: fix no irq handling
From: Anton Vorontsov @ 2008-08-12 14:31 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: Sparks, Sam, linuxppc-dev, linux-ide, Stefan Roese, Jeff Garzik
In-Reply-To: <48A19BC2.8060008@ru.mvista.com>
On Tue, Aug 12, 2008 at 06:18:42PM +0400, Sergei Shtylyov wrote:
> Anton Vorontsov wrote:
>
>>>>> 1. IDE status read does not work. (But am I understand correctly
>>>>> that IDE works well if IRQ is unspecified? Then this is hardly
>>>>> an issue.)
>>>>> 2. IDE interrupt comes when it should not. I'd recommend to use
>>>>> oscilloscope to find out what is happening there, that is, if
>>>>> the drive actually deasserts its irq line after status read.
>>>>> If so, than this could be a PIC problem.
>
>>>>> What is the platform on which you're observing the issue, btw?
>
>>>> Another possibility is that you got the wrong interrupt number
>>>> in the device-tree...
>
>>>> Ben.
>
>>> The platform is the AMCC Sequoia board. We've built a little adapter to
>>> connect a compact flash card to the processor bus. I believe the
>>> interrupt selection in the device tree is correct, and I've checked over
>>> the u-boot settings for the IRQ line (active high, level sensitive).
>
>> IDE IRQs are active-low.
>
> Only on the PCI and only in the native mode. Natively, the IDE INTRQ
> signal is active-high, rising edge triggering, as on ISA. You seem to
> have an invertor somewhere, if it's not a PCI chip...
Ugh. Right you are, as always. I've just looked into mpc8349emitx
schematics, there is indeed an inverter on the irq line.
CF in True IDE mode is active-high, sorry.
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* RE: Does Dev Tree WORK with soc@y_xxxx_0000 <#address/size> = <2/1>
From: Morrison, Tom @ 2008-08-12 15:14 UTC (permalink / raw)
To: Becky Bruce; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <0120619E-B530-4605-B550-15085F7009E2@freescale.com>
Thank you Becky (and Kumar) for all the information....and help!
To answer your questions, yes, we are using 4GB++ of memory
(and plan more in the near future). But, for the initial bring
up, I reduced the memory to 2Gig. Further, I have modified u-boot=20
to NOT modify the memory reg properties (see below my snippet)...
Question: what other 'devices' does u-boot put down that I care=20
about I have modified u-boot to put the correct memory structure?=20
Also, are you saying there are additional patches for=20
prom parsing code for this to work right - or are you=20
talking about in general for the 4Gig memory??
Here is a dts snippet with some of the interesting parts:
/{ model =3D "MPC8548_CHEETAH";
compatible =3D "MPC8548_CHEETAH";
#address-cells =3D <2>;
#size-cells =3D <2>;
=20
memory { device_type =3D "memory";
reg =3D <0 00000000 0 80000000>; // 2 GIG @ 0x0
};
soc8548@c6df00000 {
#address-cells =3D <1>;
#size-cells =3D <1>;
#interrupt-cells =3D <2>;
device_type =3D "soc";
ranges =3D <00001000 00000000c 6df00000 000ff000>;
reg =3D <0000000C 6df00000 0 001000>; // CCSRBAR
.........
serial@4500 {
device_type =3D "serial";
compatible =3D "ns16550";
reg =3D <4500 100>; // reg base, size
clock-frequency =3D <0>; // should we fill in in
uboot?
interrupts =3D <2a 2>;
interrupt-parent =3D <&mpic>;
};
serial@4600 {
device_type =3D "serial";
compatible =3D "ns16550";
reg =3D <4600 100>; // reg base, size
clock-frequency =3D <0>; // should we fill in in
uboot?
interrupts =3D <2a 2>;
interrupt-parent =3D <&mpic>;
};
.........
};
Now, it looks like I am successfully parsing and translating the=20
address to the expected address for the default stdout (0xc_6df0_4600)!
FWIW, I have identified that another problem with the code configuring
the CCSRBAR (and am sure I'll figure that one out soon because we have=20
a working solution in the arch/ppc directory).
While I have your expert attention, I'd like to have you comment about
what potentially could be right/wrong with my definitions for the pci
express settings...
a) Do I put those ranges in the ranges for the parent soc device
(also)?
b) Do the below correctly define a 2 Gig PCI memory Window starting=20
at 0xC_6F00_0000 (to 0xC_EF00_0000) and PCI IO 16M Window starting
at 0xC_6E00_0000 (to 0xC_6F00_0000)?
-----
/* PCI Express */
pcie@a000 {
compatible =3D "fsl,mpc8548-pcie";
device_type =3D "pci";
#interrupt-cells =3D <1>;
#size-cells =3D <2>;
#address-cells =3D <3>;
reg =3D <a000 1000>;
bus-range =3D <0 ff>;
ranges =3D <02000000 0 c 6f000000 c 6f000000 0 80000000
01000000 0 00000000 0000000c 6E000000 0 01000000>;
-----
Thank you for all your help/comments...
Sincerely,
Tom Morrison
-----Original Message-----
From: Becky Bruce [mailto:becky.bruce@freescale.com]=20
Sent: Monday, August 11, 2008 6:26 PM
To: Morrison, Tom
Cc: linuxppc-dev@ozlabs.org; Paul Mackerras
Subject: Re: Does Dev Tree WORK with soc@y_xxxx_0000 <#address/size> =3D
<2/1>
On Aug 11, 2008, at 4:37 PM, Morrison, Tom wrote:
> I am sorry, but I've butted my head against a tree for over a
> week and some things just aren't making sense...especially how
> the prom parse code is working to exact / resolve physical
> addresses to then ioremap...
>
> a) Setup, I have a working MPC8548E board using 2.6.23.8 (ARCH=3Dppc)
> with PHYS/PTE_64BIT enabled (with the proper patches)).
So, how much RAM are you trying to use? If it's 4GB+, there are still
patches you need that haven't been released yet but should be out in
the next week or so (I'm in the middle of pulling everything up to
top-of-tree and re-testing).
>
>
> b) Goal: we want to move our board to a generic 2.6.23 version that
> Freescale has produced to support the MPC8572DS (and eventually
> use that kernel to build our BSP for our next board).
>
> c) I have successfully gotten to work a pure '32-bit' dev tree
> (PHYS/PTE_64BIT not defined - and the CCSRBAR @ 0xE000_0000)
> The #address/#size <1/1> is '1' (as well as the #size is '1')
>
> d) I have modified this dev tree to support the 36bit mode addressing
> (with the CCSRBAR and PCIExpress defined to in the last 4Gig =20
> (instead
> of the default first 4Gig - e.g.: 0xC_E000_0000)...
>
> e) I then set the soc to have #address-cells to '2' (#size-cells is =20
> '1')
> (and added the additional values accordingly to the ranges...=09
I'm not sure you've done the right thing here. In many cases, you don't
actually need to modify the size/addr cells in the soc node - those just
impact the children of that node, which are relative to the parent.
You do need to change your high-level platform node at the very top of
the .dts to have the right width - here's a patch snippet from a dts I =20
had
with 2/1 formatting (this is a very old .dts, so it uses the old-style
number formatting before we started using '0x'):
+ model =3D "MPC8641HPCN";
+ compatible =3D "mpc86xx";
+ #address-cells =3D <2>;
+ #size-cells =3D <1>;
and then the soc node itself was: (I located things at 0xf_xxx0_0000)
+ soc8641@ff8000000 {
+ #address-cells =3D <1>;
+ #size-cells =3D <1>;
+ device_type =3D "soc";
+ ranges =3D <00000000 0f f8000000 00100000>;
+ reg =3D <f f8000000 00001000>; // CCSRBAR
The reg and ranges now reflect the wider parent bus address.
>
>
> f) The prom_parse code has a problem with translating these addresses
>
>
> The main question is: has anyone ever tested this with soc #address/=20
> size
> being <2/1> in this fashion?
I did that a while ago with 8641D and it worked fine at that point;
since then I've converted to a 2/2 format (which also works fine).
That, of course, assumes you've modified your bootloader to put the
devices in the right spot. Without that, all bets are off.
Hope that helps.... if you're still confused, post some snippets of =20
your dts and I'll take a look.
Cheers,
B
^ permalink raw reply
* Re: Does Dev Tree WORK with soc@y_xxxx_0000 <#address/size> = <2/1>
From: Becky Bruce @ 2008-08-12 15:56 UTC (permalink / raw)
To: Morrison, Tom; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <BD261180E6D35F4D9D32F3E44FD3D9010DF4EFAF@EMPBEDEX.empirix.com>
On Aug 12, 2008, at 10:14 AM, Morrison, Tom wrote:
> Thank you Becky (and Kumar) for all the information....and help!
>
> To answer your questions, yes, we are using 4GB++ of memory
> (and plan more in the near future). But, for the initial bring
> up, I reduced the memory to 2Gig. Further, I have modified u-boot
> to NOT modify the memory reg properties (see below my snippet)...
>
> Question: what other 'devices' does u-boot put down that I care
> about I have modified u-boot to put the correct memory structure?
If you have 4GB of RAM, you need to move *all* devices in u-boot above
4GB. The config file for your board should have all the information
you need about what's out there.
>
>
> Also, are you saying there are additional patches for
> prom parsing code for this to work right - or are you
> talking about in general for the 4Gig memory??
I was talking about in general for 4GB. The prom parsing code should
work already. The issue with having 4GB is that there are some devices
that only recognize 32 bits of physical address. These devices will
require bounce buffering a la swiotlb in order to do dmas when the dma
buffer is somewhere above about 3.5GB (that number depends on your
board - the reason you can't see the whole 4GB of space is that some
portion of the PCI space is reserved for PCI-IO). I'm currently
working through some issues that popped up when I updated to TOT and
picked up the dma_attrs changes. I expect to have these patches out
within a week or so.
>
>
> Here is a dts snippet with some of the interesting parts:
>
> /{ model = "MPC8548_CHEETAH";
> compatible = "MPC8548_CHEETAH";
> #address-cells = <2>;
> #size-cells = <2>;
>
> memory { device_type = "memory";
> reg = <0 00000000 0 80000000>; // 2 GIG @ 0x0
> };
>
> soc8548@c6df00000 {
> #address-cells = <1>;
> #size-cells = <1>;
> #interrupt-cells = <2>;
> device_type = "soc";
> ranges = <00001000 00000000c 6df00000 000ff000>;
> reg = <0000000C 6df00000 0 001000>; // CCSRBAR
>
>
> .........
> serial@4500 {
> device_type = "serial";
> compatible = "ns16550";
> reg = <4500 100>; // reg base, size
> clock-frequency = <0>; // should we fill in in
> uboot?
> interrupts = <2a 2>;
> interrupt-parent = <&mpic>;
> };
>
> serial@4600 {
> device_type = "serial";
> compatible = "ns16550";
> reg = <4600 100>; // reg base, size
> clock-frequency = <0>; // should we fill in in
> uboot?
> interrupts = <2a 2>;
> interrupt-parent = <&mpic>;
> };
>
> .........
> };
>
> Now, it looks like I am successfully parsing and translating the
> address to the expected address for the default stdout
> (0xc_6df0_4600)!
Yeah, this looks OK (other than the fact that you're using an old .dts
format).
>
>
> FWIW, I have identified that another problem with the code configuring
> the CCSRBAR (and am sure I'll figure that one out soon because we have
> a working solution in the arch/ppc directory).
FWIW, I moved CCSRBAR in u-boot.
>
>
> While I have your expert attention, I'd like to have you comment about
> what potentially could be right/wrong with my definitions for the pci
> express settings...
>
> a) Do I put those ranges in the ranges for the parent soc device
> (also)?
>
> b) Do the below correctly define a 2 Gig PCI memory Window starting
> at 0xC_6F00_0000 (to 0xC_EF00_0000) and PCI IO 16M Window
> starting
> at 0xC_6E00_0000 (to 0xC_6F00_0000)?
>
> -----
> /* PCI Express */
> pcie@a000 {
> compatible = "fsl,mpc8548-pcie";
> device_type = "pci";
> #interrupt-cells = <1>;
> #size-cells = <2>;
> #address-cells = <3>;
> reg = <a000 1000>;
> bus-range = <0 ff>;
> ranges = <02000000 0 c 6f000000 c 6f000000 0 80000000
> 01000000 0 00000000 0000000c 6E000000 0 01000000>;
This doesn't look right to me, assuming your pcie device is at the
same tree level as mine. What's the parent node and what are address-
cells and size-cells in the parent? I'm basically at next-to-top
level, under the platform node.
Here's an example from my working tree:
model = "MPC8641HPCN";
compatible = "mpc86xx";
#address-cells = <2>;
#size-cells = <2>;
.......
pci0: pcie@ff8008000 {
cell-index = <0>;
compatible = "fsl,mpc8641-pcie";
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
reg = <0x0f 0xf8008000 0x0 0x1000>;
bus-range = <0x0 0xff>;
ranges = <0x02000000 0x0 0x80000000 0x0f 0x80000000
0x0 0x20000000
0x01000000 0x0 0x00000000 0x0f 0xe2000000
0x0 0x00100000>;
I believe you should just need to change the parent bus address field
in ranges, and you need to update your "reg" property.
>
>
> -----
>
> Thank you for all your help/comments...
>
Have fun :)
Cheers,
Becky
^ permalink raw reply
* [PATCH 1/2] rtc: rtc-ds1374: fix 'no irq' case handling
From: Anton Vorontsov @ 2008-08-12 16:17 UTC (permalink / raw)
To: Alessandro Zummo, Andrew Morton; +Cc: linuxppc-dev, linux-kernel, rtc-linux
On a PowerPC board with ds1374 RTC I'm getting this error while
RTC tries to probe:
rtc-ds1374 0-0068: unable to request IRQ
This happens because I2C probing code (drivers/of/of_i2c.c) is
specifying IRQ0 for 'no irq' case, which is correct.
The driver handles this incorrectly, though. This patch fixes it.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
drivers/rtc/rtc-ds1374.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index 640acd2..a150418 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -173,7 +173,7 @@ static int ds1374_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
int cr, sr;
int ret = 0;
- if (client->irq < 0)
+ if (client->irq <= 0)
return -EINVAL;
mutex_lock(&ds1374->mutex);
@@ -212,7 +212,7 @@ static int ds1374_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
int cr;
int ret = 0;
- if (client->irq < 0)
+ if (client->irq <= 0)
return -EINVAL;
ret = ds1374_read_time(dev, &now);
@@ -381,7 +381,7 @@ static int ds1374_probe(struct i2c_client *client,
if (ret)
goto out_free;
- if (client->irq >= 0) {
+ if (client->irq > 0) {
ret = request_irq(client->irq, ds1374_irq, 0,
"ds1374", client);
if (ret) {
@@ -401,7 +401,7 @@ static int ds1374_probe(struct i2c_client *client,
return 0;
out_irq:
- if (client->irq >= 0)
+ if (client->irq > 0)
free_irq(client->irq, client);
out_free:
@@ -414,7 +414,7 @@ static int __devexit ds1374_remove(struct i2c_client *client)
{
struct ds1374 *ds1374 = i2c_get_clientdata(client);
- if (client->irq >= 0) {
+ if (client->irq > 0) {
mutex_lock(&ds1374->mutex);
ds1374->exiting = 1;
mutex_unlock(&ds1374->mutex);
--
1.5.6.3
^ permalink raw reply related
* [PATCH 2/2] rtc: bunch of drivers: fix 'no irq' case handing
From: Anton Vorontsov @ 2008-08-12 16:17 UTC (permalink / raw)
To: Alessandro Zummo, Andrew Morton; +Cc: linuxppc-dev, linux-kernel, rtc-linux
This patch fixes bunch of irq checking misuses. Most drivers were
getting irq via platform_get_irq(), which returns -ENXIO or r->start.
Platforms may specify r->start = 0 to emphasize 'no irq' case, and
drivers should handle this correctly.
rtc-cmos.c is special. It is using PNP and platform bindings.
Hopefully nobody is using PNP IRQ 0 for RTC. So the changes should
be safe.
Also, rtc-sh.c was using platform_get_irq, and stored a result into
an unsigned type, then was checking for < 0. This is fixed now.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
Unlike the first patch, this one is untested. Please review carefully.
drivers/rtc/rtc-at32ap700x.c | 2 +-
drivers/rtc/rtc-cmos.c | 4 ++--
drivers/rtc/rtc-ds1511.c | 18 +++++++++---------
drivers/rtc/rtc-ds1553.c | 14 +++++++-------
drivers/rtc/rtc-m48t59.c | 2 +-
drivers/rtc/rtc-sh.c | 10 ++++++----
drivers/rtc/rtc-stk17ta8.c | 14 +++++++-------
drivers/rtc/rtc-vr41xx.c | 4 ++--
8 files changed, 35 insertions(+), 33 deletions(-)
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c
index 90b9a65..e327f6f 100644
--- a/drivers/rtc/rtc-at32ap700x.c
+++ b/drivers/rtc/rtc-at32ap700x.c
@@ -222,7 +222,7 @@ static int __init at32_rtc_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
+ if (irq <= 0) {
dev_dbg(&pdev->dev, "could not get irq\n");
ret = -ENXIO;
goto out;
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 6ea349a..2dea444 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -57,8 +57,8 @@ struct cmos_rtc {
u8 century;
};
-/* both platform and pnp busses use negative numbers for invalid irqs */
-#define is_valid_irq(n) ((n) >= 0)
+/* both platform and pnp busses use positive numbers for valid irqs */
+#define is_valid_irq(n) ((n) > 0)
static const char driver_name[] = "rtc_cmos";
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
index 0f0d27d..434b045 100644
--- a/drivers/rtc/rtc-ds1511.c
+++ b/drivers/rtc/rtc-ds1511.c
@@ -326,9 +326,9 @@ ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0) {
+ if (pdata->irq <= 0)
return -EINVAL;
- }
+
pdata->alrm_mday = alrm->time.tm_mday;
pdata->alrm_hour = alrm->time.tm_hour;
pdata->alrm_min = alrm->time.tm_min;
@@ -346,9 +346,9 @@ ds1511_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0) {
+ if (pdata->irq <= 0)
return -EINVAL;
- }
+
alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday;
alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour;
alrm->time.tm_min = pdata->alrm_min < 0 ? 0 : pdata->alrm_min;
@@ -385,7 +385,7 @@ ds1511_rtc_release(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
pdata->irqen = 0;
ds1511_rtc_update_alarm(pdata);
}
@@ -397,7 +397,7 @@ ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0) {
+ if (pdata->irq <= 0) {
return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */
}
switch (cmd) {
@@ -559,7 +559,7 @@ ds1511_rtc_probe(struct platform_device *pdev)
* if the platform has an interrupt in mind for this device,
* then by all means, set it
*/
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
rtc_read(RTC_CMD1);
if (request_irq(pdata->irq, ds1511_interrupt,
IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) {
@@ -586,7 +586,7 @@ ds1511_rtc_probe(struct platform_device *pdev)
if (pdata->rtc) {
rtc_device_unregister(pdata->rtc);
}
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
free_irq(pdata->irq, pdev);
}
if (ds1511_base) {
@@ -609,7 +609,7 @@ ds1511_rtc_remove(struct platform_device *pdev)
sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr);
rtc_device_unregister(pdata->rtc);
pdata->rtc = NULL;
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
/*
* disable the alarm interrupt
*/
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index a19f114..426048f 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -162,7 +162,7 @@ static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0)
+ if (pdata->irq <= 0)
return -EINVAL;
pdata->alrm_mday = alrm->time.tm_mday;
pdata->alrm_hour = alrm->time.tm_hour;
@@ -179,7 +179,7 @@ static int ds1553_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0)
+ if (pdata->irq <= 0)
return -EINVAL;
alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday;
alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour;
@@ -212,7 +212,7 @@ static void ds1553_rtc_release(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
pdata->irqen = 0;
ds1553_rtc_update_alarm(pdata);
}
@@ -224,7 +224,7 @@ static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd,
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0)
+ if (pdata->irq <= 0)
return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */
switch (cmd) {
case RTC_AIE_OFF:
@@ -339,7 +339,7 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev)
if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF)
dev_warn(&pdev->dev, "voltage-low detected.\n");
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
writeb(0, ioaddr + RTC_INTERRUPTS);
if (request_irq(pdata->irq, ds1553_rtc_interrupt,
IRQF_DISABLED | IRQF_SHARED,
@@ -365,7 +365,7 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev)
out:
if (pdata->rtc)
rtc_device_unregister(pdata->rtc);
- if (pdata->irq >= 0)
+ if (pdata->irq > 0)
free_irq(pdata->irq, pdev);
if (ioaddr)
iounmap(ioaddr);
@@ -381,7 +381,7 @@ static int __devexit ds1553_rtc_remove(struct platform_device *pdev)
sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
rtc_device_unregister(pdata->rtc);
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
free_irq(pdata->irq, pdev);
}
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 013e6c1..827a60b 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -412,7 +412,7 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
* the mode without IRQ.
*/
m48t59->irq = platform_get_irq(pdev, 0);
- if (m48t59->irq < 0)
+ if (m48t59->irq <= 0)
m48t59->irq = NO_IRQ;
if (m48t59->irq != NO_IRQ) {
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 1f88e9e..2ac40cf 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -89,7 +89,9 @@ struct sh_rtc {
void __iomem *regbase;
unsigned long regsize;
struct resource *res;
- unsigned int alarm_irq, periodic_irq, carry_irq;
+ int alarm_irq;
+ int periodic_irq;
+ int carry_irq;
struct rtc_device *rtc_dev;
spinlock_t lock;
unsigned long capabilities; /* See asm-sh/rtc.h for cap bits */
@@ -585,19 +587,19 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
/* get periodic/carry/alarm irqs */
rtc->periodic_irq = platform_get_irq(pdev, 0);
- if (unlikely(rtc->periodic_irq < 0)) {
+ if (unlikely(rtc->periodic_irq <= 0)) {
dev_err(&pdev->dev, "No IRQ for period\n");
goto err_badres;
}
rtc->carry_irq = platform_get_irq(pdev, 1);
- if (unlikely(rtc->carry_irq < 0)) {
+ if (unlikely(rtc->carry_irq <= 0)) {
dev_err(&pdev->dev, "No IRQ for carry\n");
goto err_badres;
}
rtc->alarm_irq = platform_get_irq(pdev, 2);
- if (unlikely(rtc->alarm_irq < 0)) {
+ if (unlikely(rtc->alarm_irq <= 0)) {
dev_err(&pdev->dev, "No IRQ for alarm\n");
goto err_badres;
}
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c
index 31d3c8c..ad1ae47 100644
--- a/drivers/rtc/rtc-stk17ta8.c
+++ b/drivers/rtc/rtc-stk17ta8.c
@@ -170,7 +170,7 @@ static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0)
+ if (pdata->irq <= 0)
return -EINVAL;
pdata->alrm_mday = alrm->time.tm_mday;
pdata->alrm_hour = alrm->time.tm_hour;
@@ -187,7 +187,7 @@ static int stk17ta8_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0)
+ if (pdata->irq <= 0)
return -EINVAL;
alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday;
alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour;
@@ -220,7 +220,7 @@ static void stk17ta8_rtc_release(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
pdata->irqen = 0;
stk17ta8_rtc_update_alarm(pdata);
}
@@ -232,7 +232,7 @@ static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd,
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0)
+ if (pdata->irq <= 0)
return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */
switch (cmd) {
case RTC_AIE_OFF:
@@ -342,7 +342,7 @@ static int __init stk17ta8_rtc_probe(struct platform_device *pdev)
if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_PF)
dev_warn(&pdev->dev, "voltage-low detected.\n");
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
writeb(0, ioaddr + RTC_INTERRUPTS);
if (request_irq(pdata->irq, stk17ta8_rtc_interrupt,
IRQF_DISABLED | IRQF_SHARED,
@@ -368,7 +368,7 @@ static int __init stk17ta8_rtc_probe(struct platform_device *pdev)
out:
if (pdata->rtc)
rtc_device_unregister(pdata->rtc);
- if (pdata->irq >= 0)
+ if (pdata->irq > 0)
free_irq(pdata->irq, pdev);
if (ioaddr)
iounmap(ioaddr);
@@ -384,7 +384,7 @@ static int __devexit stk17ta8_rtc_remove(struct platform_device *pdev)
sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr);
rtc_device_unregister(pdata->rtc);
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
free_irq(pdata->irq, pdev);
}
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index 884b635..e441c9e 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -360,7 +360,7 @@ static int __devinit rtc_probe(struct platform_device *pdev)
spin_unlock_irq(&rtc_lock);
aie_irq = platform_get_irq(pdev, 0);
- if (aie_irq < 0 || aie_irq >= NR_IRQS) {
+ if (aie_irq <= 0 || aie_irq >= NR_IRQS) {
retval = -EBUSY;
goto err_device_unregister;
}
@@ -371,7 +371,7 @@ static int __devinit rtc_probe(struct platform_device *pdev)
goto err_device_unregister;
pie_irq = platform_get_irq(pdev, 1);
- if (pie_irq < 0 || pie_irq >= NR_IRQS)
+ if (pie_irq <= 0 || pie_irq >= NR_IRQS)
goto err_free_irq;
retval = request_irq(pie_irq, rtclong1_interrupt, IRQF_DISABLED,
--
1.5.6.3
^ permalink raw reply related
* RE: [PATCH]: [MPC5200] Add ATA DMA support
From: Daniel Schnell @ 2008-08-12 17:30 UTC (permalink / raw)
To: Tim Yamin; +Cc: linuxppc-dev
In-Reply-To: <792f5f410808120830v311e0446kc8fddfb97d0b9ea6@mail.gmail.com>
Hi Tim,
Continuing the discussion on the mailing list ...
Looking at the original patch I don't undestand why you had to duplicate
the bestcomm data structures and functions. The only apparent difference
is that you have a minimal data length of 2 bytes instead of 1. Does
this make any difference as the bd_size will be filled with the correct
length value anyway ?
Moreover what is the difference between bcom_submit_next_buffer() and
bcom_submit_next_buffer2() ? The same with bcom_retrieve_buffer() and
bcom_retrieve_buffer2(). Why are these functions implemented unequally ?
Best regards,
Daniel Schnell.
^ permalink raw reply
* Re: Mounting PRAMFS support
From: Wolfgang Denk @ 2008-08-12 18:11 UTC (permalink / raw)
To: Pieter; +Cc: linuxppc-embedded
In-Reply-To: <48A15FC3.3060008@vastech.co.za>
Dear Pieter,
In message <48A15FC3.3060008@vastech.co.za> you wrote:
>
> Im using a ppc85xx processor with Denx ELDK (4.1) The board has 512MB
> DDR2 and the board config reserves 64M for pram. during bootup the
> mem=$mem argument is passed to the linux kernel command line and linux
> boots successfully.
So what are the exact boot messages of your kernel?
> I am unable to mount the PRAMFS - all documentation leads me to use
>
> mount -t pramfs -o physaddr=0x1c000000,init=0x4000000 none /mnt
-------------------------------------------------------------^^^^
> witch fails with the message:
> mounting none on /mtd failed: no such devise
-------------------^^^^
/mnt != /mtd
There is something worng, probably your description. It would be
better if you showed the precise commands and outpout from your
target system.
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
"Open the pod bay doors, HAL." - Dave Bowman, 2001
^ permalink raw reply
* Re: [PATCH 5/5 try2] ib/ehca: discard double CQE for one WR
From: Roland Dreier @ 2008-08-12 18:35 UTC (permalink / raw)
To: Alexander Schmidt
Cc: Joachim Fenkes, of-ewg, lkml, linuxppc-dev, Christoph Raisch,
of-general, Stefan Roscher
In-Reply-To: <200808121546.31057.alexs@linux.vnet.ibm.com>
thanks, applied all 5.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox