diff options
| -rw-r--r-- | net/sunrpc/xprtrdma/frwr_ops.c | 37 | ||||
| -rw-r--r-- | net/sunrpc/xprtrdma/xprt_rdma.h | 3 |
2 files changed, 24 insertions, 16 deletions
diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c index 210949562786..26b26beef2d4 100644 --- a/net/sunrpc/xprtrdma/frwr_ops.c +++ b/net/sunrpc/xprtrdma/frwr_ops.c | |||
| @@ -44,18 +44,20 @@ | |||
| 44 | * being done. | 44 | * being done. |
| 45 | * | 45 | * |
| 46 | * When the underlying transport disconnects, MRs are left in one of | 46 | * When the underlying transport disconnects, MRs are left in one of |
| 47 | * three states: | 47 | * four states: |
| 48 | * | 48 | * |
| 49 | * INVALID: The MR was not in use before the QP entered ERROR state. | 49 | * INVALID: The MR was not in use before the QP entered ERROR state. |
| 50 | * (Or, the LOCAL_INV WR has not completed or flushed yet). | ||
| 51 | * | ||
| 52 | * STALE: The MR was being registered or unregistered when the QP | ||
| 53 | * entered ERROR state, and the pending WR was flushed. | ||
| 54 | * | 50 | * |
| 55 | * VALID: The MR was registered before the QP entered ERROR state. | 51 | * VALID: The MR was registered before the QP entered ERROR state. |
| 56 | * | 52 | * |
| 57 | * When frwr_op_map encounters STALE and VALID MRs, they are recovered | 53 | * FLUSHED_FR: The MR was being registered when the QP entered ERROR |
| 58 | * with ib_dereg_mr and then are re-initialized. Beause MR recovery | 54 | * state, and the pending WR was flushed. |
| 55 | * | ||
| 56 | * FLUSHED_LI: The MR was being invalidated when the QP entered ERROR | ||
| 57 | * state, and the pending WR was flushed. | ||
| 58 | * | ||
| 59 | * When frwr_op_map encounters FLUSHED and VALID MRs, they are recovered | ||
| 60 | * with ib_dereg_mr and then are re-initialized. Because MR recovery | ||
| 59 | * allocates fresh resources, it is deferred to a workqueue, and the | 61 | * allocates fresh resources, it is deferred to a workqueue, and the |
| 60 | * recovered MRs are placed back on the rb_mws list when recovery is | 62 | * recovered MRs are placed back on the rb_mws list when recovery is |
| 61 | * complete. frwr_op_map allocates another MR for the current RPC while | 63 | * complete. frwr_op_map allocates another MR for the current RPC while |
| @@ -177,12 +179,15 @@ __frwr_reset_mr(struct rpcrdma_ia *ia, struct rpcrdma_mw *r) | |||
| 177 | static void | 179 | static void |
| 178 | frwr_op_recover_mr(struct rpcrdma_mw *mw) | 180 | frwr_op_recover_mr(struct rpcrdma_mw *mw) |
| 179 | { | 181 | { |
| 182 | enum rpcrdma_frmr_state state = mw->frmr.fr_state; | ||
| 180 | struct rpcrdma_xprt *r_xprt = mw->mw_xprt; | 183 | struct rpcrdma_xprt *r_xprt = mw->mw_xprt; |
| 181 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; | 184 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; |
| 182 | int rc; | 185 | int rc; |
| 183 | 186 | ||
| 184 | rc = __frwr_reset_mr(ia, mw); | 187 | rc = __frwr_reset_mr(ia, mw); |
| 185 | ib_dma_unmap_sg(ia->ri_device, mw->mw_sg, mw->mw_nents, mw->mw_dir); | 188 | if (state != FRMR_FLUSHED_LI) |
| 189 | ib_dma_unmap_sg(ia->ri_device, | ||
| 190 | mw->mw_sg, mw->mw_nents, mw->mw_dir); | ||
| 186 | if (rc) | 191 | if (rc) |
| 187 | goto out_release; | 192 | goto out_release; |
| 188 | 193 | ||
| @@ -262,10 +267,8 @@ frwr_op_maxpages(struct rpcrdma_xprt *r_xprt) | |||
| 262 | } | 267 | } |
| 263 | 268 | ||
| 264 | static void | 269 | static void |
| 265 | __frwr_sendcompletion_flush(struct ib_wc *wc, struct rpcrdma_frmr *frmr, | 270 | __frwr_sendcompletion_flush(struct ib_wc *wc, const char *wr) |
| 266 | const char *wr) | ||
| 267 | { | 271 | { |
| 268 | frmr->fr_state = FRMR_IS_STALE; | ||
| 269 | if (wc->status != IB_WC_WR_FLUSH_ERR) | 272 | if (wc->status != IB_WC_WR_FLUSH_ERR) |
| 270 | pr_err("rpcrdma: %s: %s (%u/0x%x)\n", | 273 | pr_err("rpcrdma: %s: %s (%u/0x%x)\n", |
| 271 | wr, ib_wc_status_msg(wc->status), | 274 | wr, ib_wc_status_msg(wc->status), |
| @@ -288,7 +291,8 @@ frwr_wc_fastreg(struct ib_cq *cq, struct ib_wc *wc) | |||
| 288 | if (wc->status != IB_WC_SUCCESS) { | 291 | if (wc->status != IB_WC_SUCCESS) { |
| 289 | cqe = wc->wr_cqe; | 292 | cqe = wc->wr_cqe; |
| 290 | frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); | 293 | frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); |
| 291 | __frwr_sendcompletion_flush(wc, frmr, "fastreg"); | 294 | frmr->fr_state = FRMR_FLUSHED_FR; |
| 295 | __frwr_sendcompletion_flush(wc, "fastreg"); | ||
| 292 | } | 296 | } |
| 293 | } | 297 | } |
| 294 | 298 | ||
| @@ -308,7 +312,8 @@ frwr_wc_localinv(struct ib_cq *cq, struct ib_wc *wc) | |||
| 308 | if (wc->status != IB_WC_SUCCESS) { | 312 | if (wc->status != IB_WC_SUCCESS) { |
| 309 | cqe = wc->wr_cqe; | 313 | cqe = wc->wr_cqe; |
| 310 | frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); | 314 | frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); |
| 311 | __frwr_sendcompletion_flush(wc, frmr, "localinv"); | 315 | frmr->fr_state = FRMR_FLUSHED_LI; |
| 316 | __frwr_sendcompletion_flush(wc, "localinv"); | ||
| 312 | } | 317 | } |
| 313 | } | 318 | } |
| 314 | 319 | ||
| @@ -328,8 +333,10 @@ frwr_wc_localinv_wake(struct ib_cq *cq, struct ib_wc *wc) | |||
| 328 | /* WARNING: Only wr_cqe and status are reliable at this point */ | 333 | /* WARNING: Only wr_cqe and status are reliable at this point */ |
| 329 | cqe = wc->wr_cqe; | 334 | cqe = wc->wr_cqe; |
| 330 | frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); | 335 | frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); |
| 331 | if (wc->status != IB_WC_SUCCESS) | 336 | if (wc->status != IB_WC_SUCCESS) { |
| 332 | __frwr_sendcompletion_flush(wc, frmr, "localinv"); | 337 | frmr->fr_state = FRMR_FLUSHED_LI; |
| 338 | __frwr_sendcompletion_flush(wc, "localinv"); | ||
| 339 | } | ||
| 333 | complete(&frmr->fr_linv_done); | 340 | complete(&frmr->fr_linv_done); |
| 334 | } | 341 | } |
| 335 | 342 | ||
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 0d35b761c883..6e1bba358203 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h | |||
| @@ -216,7 +216,8 @@ struct rpcrdma_rep { | |||
| 216 | enum rpcrdma_frmr_state { | 216 | enum rpcrdma_frmr_state { |
| 217 | FRMR_IS_INVALID, /* ready to be used */ | 217 | FRMR_IS_INVALID, /* ready to be used */ |
| 218 | FRMR_IS_VALID, /* in use */ | 218 | FRMR_IS_VALID, /* in use */ |
| 219 | FRMR_IS_STALE, /* failed completion */ | 219 | FRMR_FLUSHED_FR, /* flushed FASTREG WR */ |
| 220 | FRMR_FLUSHED_LI, /* flushed LOCALINV WR */ | ||
| 220 | }; | 221 | }; |
| 221 | 222 | ||
| 222 | struct rpcrdma_frmr { | 223 | struct rpcrdma_frmr { |
