IB/ehca: fix problem with flush work completions
PATCH 1/1 IB/ehca: fix problem with flush work completions
This fix enables ehca device driver to generate flush workcompletions even if the application don't request work completions for all work requests. The current implementation of ehca will generate flush work completions for the wrong work requests if an application uses non signaled work completions.
Signed-off-by root <[email protected]>
---
The patch will cleanly apply on top of 2.6.28-rc6. Roland, please apply this for 2.6.28 if possible. regards Stefan
drivers/infiniband/hw/ehca/ehca_classes.h | 4 ++- drivers/infiniband/hw/ehca/ehca_qp.c | 26 +++++++++++--- drivers/infiniband/hw/ehca/ehca_reqs.c | 51 +++++++++++++++++------------ 3 files changed, 53 insertions(+), 28 deletions(-)
drivers/infiniband/hw/ehca/ehca_classes.h +3 -1
@@ -163,7 +163,8 @@ struct ehca_mod_qp_parm {/* struct for tracking if cqes have been reported to the application */ struct ehca_qmap_entry {u16 app_wr_id; -u16 reported; +u8 reported; +u8 cqe_req; };struct ehca_queue_map {
@@ -171,6 +172,7 @@ struct ehca_queue_map {unsigned int entries;unsigned int tail;unsigned int left_to_poll; +unsigned int next_wqe_idx;/* Idx to first wqe to be flushed */ };struct ehca_qp {
drivers/infiniband/hw/ehca/ehca_qp.c +20 -6
@@ -435,9 +435,13 @@ static void reset_queue_map(struct ehca_queue_map *qmap) {int i; - qmap->tail =0 ; -for (i =0 ; i < qmap->entries; i++) + qmap->tail = qmap->entries -1 ; + qmap->left_to_poll =0 ; + qmap->next_wqe_idx =0 ; +for (i =0 ; i < qmap->entries; i++) { qmap->map[i].reported =1 ; + qmap->map[i].cqe_req =0 ; + } }/*
@@ -1121,6 +1125,7 @@ static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue,void *wqe_v;u64 q_ofs;u32 wqe_idx; +unsigned int tail_idx;/* convert real to abs address */ wqe_p = wqe_p & (~(1UL <<63 ));
@@ -1133,12 +1138,17 @@ static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue,return -EFAULT ; } + tail_idx = (qmap->tail +1 ) % qmap->entries; wqe_idx = q_ofs / ipz_queue->qe_size; -if (wqe_idx < qmap->tail) - qmap->left_to_poll = (qmap->entries - qmap->tail) + wqe_idx; -else - qmap->left_to_poll = wqe_idx - qmap->tail; +/* check all processed wqes, whether a cqe is requested or not */ +while (tail_idx != wqe_idx) { +if (qmap->map[tail_idx].cqe_req) + qmap->left_to_poll++; + tail_idx = (tail_idx +1 ) % qmap->entries; + } +/* save index in queue, where we have to start flushing */ + qmap->next_wqe_idx = wqe_idx;return 0 ; }
@@ -1185,10 +1195,14 @@ static int check_for_left_cqes(struct ehca_qp *my_qp, struct ehca_shca *shca) }else {spin_lock_irqsave (&my_qp->send_cq->spinlock, flags); my_qp->sq_map.left_to_poll =0 ; + my_qp->sq_map.next_wqe_idx = (my_qp->sq_map.tail +1 ) % + my_qp->sq_map.entries;spin_unlock_irqrestore (&my_qp->send_cq->spinlock, flags);spin_lock_irqsave (&my_qp->recv_cq->spinlock, flags); my_qp->rq_map.left_to_poll =0 ; + my_qp->rq_map.next_wqe_idx = (my_qp->rq_map.tail +1 ) % + my_qp->rq_map.entries;spin_unlock_irqrestore (&my_qp->recv_cq->spinlock, flags); }
drivers/infiniband/hw/ehca/ehca_reqs.c +30 -21
111 lines not on this page · raw message
Signature · 1 line
1.5.5