|
@@ -521,12 +521,13 @@ frwr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct list_head *mws)
|
|
|
* unless ri_id->qp is a valid pointer.
|
|
|
*/
|
|
|
r_xprt->rx_stats.local_inv_needed++;
|
|
|
+ bad_wr = NULL;
|
|
|
rc = ib_post_send(ia->ri_id->qp, first, &bad_wr);
|
|
|
+ if (bad_wr != first)
|
|
|
+ wait_for_completion(&f->fr_linv_done);
|
|
|
if (rc)
|
|
|
goto reset_mrs;
|
|
|
|
|
|
- wait_for_completion(&f->fr_linv_done);
|
|
|
-
|
|
|
/* ORDER: Now DMA unmap all of the MRs, and return
|
|
|
* them to the free MW list.
|
|
|
*/
|
|
@@ -543,17 +544,19 @@ unmap:
|
|
|
|
|
|
reset_mrs:
|
|
|
pr_err("rpcrdma: FRMR invalidate ib_post_send returned %i\n", rc);
|
|
|
- rdma_disconnect(ia->ri_id);
|
|
|
|
|
|
/* Find and reset the MRs in the LOCAL_INV WRs that did not
|
|
|
- * get posted. This is synchronous, and slow.
|
|
|
+ * get posted.
|
|
|
*/
|
|
|
- list_for_each_entry(mw, mws, mw_list) {
|
|
|
- f = &mw->frmr;
|
|
|
- if (mw->mw_handle == bad_wr->ex.invalidate_rkey) {
|
|
|
- __frwr_reset_mr(ia, mw);
|
|
|
- bad_wr = bad_wr->next;
|
|
|
- }
|
|
|
+ rpcrdma_init_cqcount(&r_xprt->rx_ep, -count);
|
|
|
+ while (bad_wr) {
|
|
|
+ f = container_of(bad_wr, struct rpcrdma_frmr,
|
|
|
+ fr_invwr);
|
|
|
+ mw = container_of(f, struct rpcrdma_mw, frmr);
|
|
|
+
|
|
|
+ __frwr_reset_mr(ia, mw);
|
|
|
+
|
|
|
+ bad_wr = bad_wr->next;
|
|
|
}
|
|
|
goto unmap;
|
|
|
}
|