diff options
author | Yonatan Cohen <yonatanc@mellanox.com> | 2016-11-16 03:39:17 -0500 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-11-16 20:03:44 -0500 |
commit | aa75b07b478a774b1432e2df1be5cd8ae834de0f (patch) | |
tree | 61258e0d529054999d30e085d1609ed4f4c5e0ba | |
parent | 002e062e13db10973adb8302f231e48b477c7ccf (diff) |
IB/rxe: Clear queue buffer when modifying QP to reset
RXE resets the send-q only once in rxe_qp_init_req() when
QP is created, but when the QP is reused after QP reset, the send-q
holds previous garbage data.
This garbage data wrongly fails CQEs that otherwise
should have completed successfully.
Fixes: 8700e3e7c485 ("Soft RoCE driver")
Signed-off-by: Yonatan Cohen <yonatanc@mellanox.com>
Reviewed-by: Moni Shoua <monis@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r-- | drivers/infiniband/sw/rxe/rxe_qp.c | 1 | ||||
-rw-r--r-- | drivers/infiniband/sw/rxe/rxe_queue.c | 9 | ||||
-rw-r--r-- | drivers/infiniband/sw/rxe/rxe_queue.h | 2 |
3 files changed, 12 insertions, 0 deletions
diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c index b8036cfbce04..95aaaa282a04 100644 --- a/drivers/infiniband/sw/rxe/rxe_qp.c +++ b/drivers/infiniband/sw/rxe/rxe_qp.c | |||
@@ -522,6 +522,7 @@ static void rxe_qp_reset(struct rxe_qp *qp) | |||
522 | if (qp->sq.queue) { | 522 | if (qp->sq.queue) { |
523 | __rxe_do_task(&qp->comp.task); | 523 | __rxe_do_task(&qp->comp.task); |
524 | __rxe_do_task(&qp->req.task); | 524 | __rxe_do_task(&qp->req.task); |
525 | rxe_queue_reset(qp->sq.queue); | ||
525 | } | 526 | } |
526 | 527 | ||
527 | /* cleanup attributes */ | 528 | /* cleanup attributes */ |
diff --git a/drivers/infiniband/sw/rxe/rxe_queue.c b/drivers/infiniband/sw/rxe/rxe_queue.c index 08274254eb88..d14bf496d62d 100644 --- a/drivers/infiniband/sw/rxe/rxe_queue.c +++ b/drivers/infiniband/sw/rxe/rxe_queue.c | |||
@@ -84,6 +84,15 @@ err1: | |||
84 | return -EINVAL; | 84 | return -EINVAL; |
85 | } | 85 | } |
86 | 86 | ||
87 | inline void rxe_queue_reset(struct rxe_queue *q) | ||
88 | { | ||
89 | /* queue is comprised from header and the memory | ||
90 | * of the actual queue. See "struct rxe_queue_buf" in rxe_queue.h | ||
91 | * reset only the queue itself and not the management header | ||
92 | */ | ||
93 | memset(q->buf->data, 0, q->buf_size - sizeof(struct rxe_queue_buf)); | ||
94 | } | ||
95 | |||
87 | struct rxe_queue *rxe_queue_init(struct rxe_dev *rxe, | 96 | struct rxe_queue *rxe_queue_init(struct rxe_dev *rxe, |
88 | int *num_elem, | 97 | int *num_elem, |
89 | unsigned int elem_size) | 98 | unsigned int elem_size) |
diff --git a/drivers/infiniband/sw/rxe/rxe_queue.h b/drivers/infiniband/sw/rxe/rxe_queue.h index 239fd609c31e..8c8641c87817 100644 --- a/drivers/infiniband/sw/rxe/rxe_queue.h +++ b/drivers/infiniband/sw/rxe/rxe_queue.h | |||
@@ -84,6 +84,8 @@ int do_mmap_info(struct rxe_dev *rxe, | |||
84 | size_t buf_size, | 84 | size_t buf_size, |
85 | struct rxe_mmap_info **ip_p); | 85 | struct rxe_mmap_info **ip_p); |
86 | 86 | ||
87 | void rxe_queue_reset(struct rxe_queue *q); | ||
88 | |||
87 | struct rxe_queue *rxe_queue_init(struct rxe_dev *rxe, | 89 | struct rxe_queue *rxe_queue_init(struct rxe_dev *rxe, |
88 | int *num_elem, | 90 | int *num_elem, |
89 | unsigned int elem_size); | 91 | unsigned int elem_size); |