diff options
author | Mike Marciniszyn <mike.marciniszyn@intel.com> | 2016-02-14 12:45:53 -0800 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-03-10 20:38:14 -0500 |
commit | a545f5308b6cf476def8a9326f7e82f89623bb03 (patch) | |
tree | b89b9c1f95d75f69178dc3cdc9bcbe042f71622f /drivers/staging/rdma/hfi1/iowait.h | |
parent | IB/qib, staging/rdma/hfi1, IB/rdmavt: progress selection changes (diff) | |
download | linux-dev-a545f5308b6cf476def8a9326f7e82f89623bb03.tar.xz linux-dev-a545f5308b6cf476def8a9326f7e82f89623bb03.zip |
staging/rdma/hfi: fix CQ completion order issue
The current implementation of the sdma_wait variable
has a timing hole that can cause a completion Q entry
to be returned from a pio send prior to an older
sdma packets completion queue entry.
The sdma_wait variable used to be decremented prior to
calling the packet complete routine. The hole is between decrement
and the verbs completion where send engine using pio could return
a out of order completion in that window.
This patch closes the hole by allowing an API option to
specify an sdma_drained callback. The atomic dec
is positioned after the complete callback to avoid the
window as long as the pio path doesn't execute when
there is a non-zero sdma count.
Reviewed-by: Jubin John <jubin.john@intel.com>
Signed-off-by: Dean Luick <dean.luick@intel.com>
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
Diffstat (limited to 'drivers/staging/rdma/hfi1/iowait.h')
-rw-r--r-- | drivers/staging/rdma/hfi1/iowait.h | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/staging/rdma/hfi1/iowait.h b/drivers/staging/rdma/hfi1/iowait.h index b5eb1e0a5aa2..2cb3f0422752 100644 --- a/drivers/staging/rdma/hfi1/iowait.h +++ b/drivers/staging/rdma/hfi1/iowait.h @@ -69,7 +69,8 @@ struct sdma_engine; * @list: used to add/insert into QP/PQ wait lists * @tx_head: overflow list of sdma_txreq's * @sleep: no space callback - * @wakeup: space callback + * @wakeup: space callback wakeup + * @sdma_drained: sdma count drained * @iowork: workqueue overhead * @wait_dma: wait for sdma_busy == 0 * @wait_pio: wait for pio_busy == 0 @@ -104,6 +105,7 @@ struct iowait { struct sdma_txreq *tx, unsigned seq); void (*wakeup)(struct iowait *wait, int reason); + void (*sdma_drained)(struct iowait *wait); struct work_struct iowork; wait_queue_head_t wait_dma; wait_queue_head_t wait_pio; @@ -122,7 +124,7 @@ struct iowait { * @tx_limit: limit for overflow queuing * @func: restart function for workqueue * @sleep: sleep function for no space - * @wakeup: wakeup function for no space + * @resume: wakeup function for no space * * This function initializes the iowait * structure embedded in the QP or PQ. @@ -138,7 +140,8 @@ static inline void iowait_init( struct iowait *wait, struct sdma_txreq *tx, unsigned seq), - void (*wakeup)(struct iowait *wait, int reason)) + void (*wakeup)(struct iowait *wait, int reason), + void (*sdma_drained)(struct iowait *wait)) { wait->count = 0; INIT_LIST_HEAD(&wait->list); @@ -151,6 +154,7 @@ static inline void iowait_init( wait->tx_limit = tx_limit; wait->sleep = sleep; wait->wakeup = wakeup; + wait->sdma_drained = sdma_drained; } /** @@ -273,6 +277,8 @@ static inline void iowait_drain_wakeup(struct iowait *wait) { wake_up(&wait->wait_dma); wake_up(&wait->wait_pio); + if (wait->sdma_drained) + wait->sdma_drained(wait); } /** |