Re: [PATCH] ib/ehca: add flush CQE generation

2008-09-16 Thread Roland Dreier
thanks, queued for 2.6.28.
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] ib/ehca: add flush CQE generation

2008-09-10 Thread Alexander Schmidt
When a QP goes into error state, it is required that flush CQEs are
delivered to the application for any outstanding work requests. eHCA does not
do this in hardware, so this patch adds software flush CQE generation to the
ehca driver.

Whenever a QP gets into error state, it is added to the QP error list of its
respective CQ. If the error QP list of a CQ is not empty, poll_cq()
generates flush CQEs before polling the actual CQ.

Signed-off-by: Alexander Schmidt <[EMAIL PROTECTED]>
---
Applies on top of 2.6.27-rc3, please consider this for 2.6.28.

 drivers/infiniband/hw/ehca/ehca_classes.h |   14 +
 drivers/infiniband/hw/ehca/ehca_cq.c  |3 
 drivers/infiniband/hw/ehca/ehca_iverbs.h  |2 
 drivers/infiniband/hw/ehca/ehca_qp.c  |  225 --
 drivers/infiniband/hw/ehca/ehca_reqs.c|  211 
 5 files changed, 412 insertions(+), 43 deletions(-)

--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_classes.h
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -164,6 +164,13 @@ struct ehca_qmap_entry {
u16 reported;
 };
 
+struct ehca_queue_map {
+   struct ehca_qmap_entry *map;
+   unsigned int entries;
+   unsigned int tail;
+   unsigned int left_to_poll;
+};
+
 struct ehca_qp {
union {
struct ib_qp ib_qp;
@@ -173,8 +180,9 @@ 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 ehca_queue_map sq_map;
struct ipz_queue ipz_rqueue;
+   struct ehca_queue_map rq_map;
struct h_galpas galpas;
u32 qkey;
u32 real_qp_num;
@@ -204,6 +212,8 @@ struct ehca_qp {
atomic_t nr_events; /* events seen */
wait_queue_head_t wait_completion;
int mig_armed;
+   struct list_head sq_err_node;
+   struct list_head rq_err_node;
 };
 
 #define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
@@ -233,6 +243,8 @@ struct ehca_cq {
/* mmap counter for resources mapped into user space */
u32 mm_count_queue;
u32 mm_count_galpa;
+   struct list_head sqp_err_list;
+   struct list_head rqp_err_list;
 };
 
 enum ehca_mr_flag {
--- infiniband.git.orig/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ infiniband.git/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -53,9 +53,25 @@
 /* in RC traffic, insert an empty RDMA READ every this many packets */
 #define ACK_CIRC_THRESHOLD 200
 
+static u64 replace_wr_id(u64 wr_id, u16 idx)
+{
+   u64 ret;
+
+   ret = wr_id & ~QMAP_IDX_MASK;
+   ret |= idx & QMAP_IDX_MASK;
+
+   return ret;
+}
+
+static u16 get_app_wr_id(u64 wr_id)
+{
+   return wr_id & QMAP_IDX_MASK;
+}
+
 static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
  struct ehca_wqe *wqe_p,
- struct ib_recv_wr *recv_wr)
+ struct ib_recv_wr *recv_wr,
+ u32 rq_map_idx)
 {
u8 cnt_ds;
if (unlikely((recv_wr->num_sge < 0) ||
@@ -69,7 +85,7 @@ static inline int ehca_write_rwqe(struct
/* clear wqe header until sglist */
memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list));
 
-   wqe_p->work_request_id = recv_wr->wr_id;
+   wqe_p->work_request_id = replace_wr_id(recv_wr->wr_id, rq_map_idx);
wqe_p->nr_of_data_seg = recv_wr->num_sge;
 
for (cnt_ds = 0; cnt_ds < recv_wr->num_sge; cnt_ds++) {
@@ -146,6 +162,7 @@ static inline int ehca_write_swqe(struct
u64 dma_length;
struct ehca_av *my_av;
u32 remote_qkey = send_wr->wr.ud.remote_qkey;
+   struct ehca_qmap_entry *qmap_entry = &qp->sq_map.map[sq_map_idx];
 
if (unlikely((send_wr->num_sge < 0) ||
 (send_wr->num_sge > qp->ipz_squeue.act_nr_of_sg))) {
@@ -158,11 +175,10 @@ 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 & ~QMAP_IDX_MASK;
-   wqe_p->work_request_id |= sq_map_idx & QMAP_IDX_MASK;
+   wqe_p->work_request_id = replace_wr_id(send_wr->wr_id, sq_map_idx);
 
-   qp->sq_map[sq_map_idx].app_wr_id = send_wr->wr_id & QMAP_IDX_MASK;
-   qp->sq_map[sq_map_idx].reported = 0;
+   qmap_entry->app_wr_id = get_app_wr_id(send_wr->wr_id);
+   qmap_entry->reported = 0;
 
switch (send_wr->opcode) {
case IB_WR_SEND:
@@ -496,7 +512,9 @@ static int internal_post_recv(struct ehc
struct ehca_wqe *wqe_p;
int wqe_cnt = 0;
int ret = 0;
+   u32 rq_map_idx;
unsigned long flags;
+   struct ehca_qmap_entry *qmap_entry;
 
if (unlikely(!HAS_RQ(my_qp))) {
ehca_err(dev, "QP has no RQ  ehca_qp=%p qp_num=%x ext_type=%d",
@@ -524,8 +542,15 @@ static int internal_post_recv(struct