Merge tag 'v5.18' into rdma.git for-next
[platform/kernel/linux-starfive.git] / drivers / infiniband / sw / rxe / rxe_resp.c
index d995ddb..f4f6ee5 100644 (file)
@@ -678,6 +678,11 @@ static struct resp_res *rxe_prepare_read_res(struct rxe_qp *qp,
  * It is assumed that the access permissions if originally good
  * are OK and the mappings to be unchanged.
  *
+ * TODO: If someone reregisters an MR to change its size or
+ * access permissions during the processing of an RDMA read
+ * we should kill the responder resource and complete the
+ * operation with an error.
+ *
  * Return: mr on success else NULL
  */
 static struct rxe_mr *rxe_recheck_mr(struct rxe_qp *qp, u32 rkey)
@@ -688,23 +693,27 @@ static struct rxe_mr *rxe_recheck_mr(struct rxe_qp *qp, u32 rkey)
 
        if (rkey_is_mw(rkey)) {
                mw = rxe_pool_get_index(&rxe->mw_pool, rkey >> 8);
-               if (!mw || mw->rkey != rkey)
+               if (!mw)
                        return NULL;
 
-               if (mw->state != RXE_MW_STATE_VALID) {
+               mr = mw->mr;
+               if (mw->rkey != rkey || mw->state != RXE_MW_STATE_VALID ||
+                   !mr || mr->state != RXE_MR_STATE_VALID) {
                        rxe_put(mw);
                        return NULL;
                }
 
-               mr = mw->mr;
+               rxe_get(mr);
                rxe_put(mw);
-       } else {
-               mr = rxe_pool_get_index(&rxe->mr_pool, rkey >> 8);
-               if (!mr || mr->rkey != rkey)
-                       return NULL;
+
+               return mr;
        }
 
-       if (mr->state != RXE_MR_STATE_VALID) {
+       mr = rxe_pool_get_index(&rxe->mr_pool, rkey >> 8);
+       if (!mr)
+               return NULL;
+
+       if (mr->rkey != rkey || mr->state != RXE_MR_STATE_VALID) {
                rxe_put(mr);
                return NULL;
        }
@@ -734,8 +743,14 @@ static enum resp_states read_reply(struct rxe_qp *qp,
        }
 
        if (res->state == rdatm_res_state_new) {
-               mr = qp->resp.mr;
-               qp->resp.mr = NULL;
+               if (!res->replay) {
+                       mr = qp->resp.mr;
+                       qp->resp.mr = NULL;
+               } else {
+                       mr = rxe_recheck_mr(qp, res->read.rkey);
+                       if (!mr)
+                               return RESPST_ERR_RKEY_VIOLATION;
+               }
 
                if (res->read.resid <= mtu)
                        opcode = IB_OPCODE_RC_RDMA_READ_RESPONSE_ONLY;