RDMA/efa: Introduce SRD QP state machine
authorGal Pressman <galpress@amazon.com>
Fri, 31 Jul 2020 06:04:19 +0000 (09:04 +0300)
committerJason Gunthorpe <jgg@nvidia.com>
Tue, 18 Aug 2020 17:52:45 +0000 (14:52 -0300)
This precursory patch adds the SRD QP type state machine, which is
currently identical to the one of UD QP type.  A following patch is going
to change the SRD QP state machine to support RNR retry modifications.

Link: https://lore.kernel.org/r/20200731060420.17053-4-galpress@amazon.com
Reviewed-by: Firas JahJah <firasj@amazon.com>
Reviewed-by: Yossi Leybovich <sleybo@amazon.com>
Signed-off-by: Gal Pressman <galpress@amazon.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/hw/efa/efa_verbs.c

index 64e8771db4e2d5544761cf295109f98c2c644b3e..289ecdeb9a7b5fb2966d6225f762bd39a7ff05d5 100644 (file)
@@ -740,11 +740,120 @@ err_out:
        return ERR_PTR(err);
 }
 
+static const struct {
+       int                     valid;
+       enum ib_qp_attr_mask    req_param;
+       enum ib_qp_attr_mask    opt_param;
+} srd_qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
+       [IB_QPS_RESET] = {
+               [IB_QPS_RESET] = { .valid = 1 },
+               [IB_QPS_INIT]  = {
+                       .valid = 1,
+                       .req_param = IB_QP_PKEY_INDEX |
+                                    IB_QP_PORT |
+                                    IB_QP_QKEY,
+               },
+       },
+       [IB_QPS_INIT] = {
+               [IB_QPS_RESET] = { .valid = 1 },
+               [IB_QPS_ERR]   = { .valid = 1 },
+               [IB_QPS_INIT]  = {
+                       .valid = 1,
+                       .opt_param = IB_QP_PKEY_INDEX |
+                                    IB_QP_PORT |
+                                    IB_QP_QKEY,
+               },
+               [IB_QPS_RTR]   = {
+                       .valid = 1,
+                       .opt_param = IB_QP_PKEY_INDEX |
+                                    IB_QP_QKEY,
+               },
+       },
+       [IB_QPS_RTR] = {
+               [IB_QPS_RESET] = { .valid = 1 },
+               [IB_QPS_ERR]   = { .valid = 1 },
+               [IB_QPS_RTS]   = {
+                       .valid = 1,
+                       .req_param = IB_QP_SQ_PSN,
+                       .opt_param = IB_QP_CUR_STATE |
+                                    IB_QP_QKEY,
+               }
+       },
+       [IB_QPS_RTS] = {
+               [IB_QPS_RESET] = { .valid = 1 },
+               [IB_QPS_ERR]   = { .valid = 1 },
+               [IB_QPS_RTS]   = {
+                       .valid = 1,
+                       .opt_param = IB_QP_CUR_STATE |
+                                    IB_QP_QKEY,
+               },
+               [IB_QPS_SQD] = {
+                       .valid = 1,
+                       .opt_param = IB_QP_EN_SQD_ASYNC_NOTIFY,
+               },
+       },
+       [IB_QPS_SQD] = {
+               [IB_QPS_RESET] = { .valid = 1 },
+               [IB_QPS_ERR]   = { .valid = 1 },
+               [IB_QPS_RTS]   = {
+                       .valid = 1,
+                       .opt_param = IB_QP_CUR_STATE |
+                                    IB_QP_QKEY,
+               },
+               [IB_QPS_SQD] = {
+                       .valid = 1,
+                       .opt_param = IB_QP_PKEY_INDEX |
+                                    IB_QP_QKEY,
+               }
+       },
+       [IB_QPS_SQE] = {
+               [IB_QPS_RESET] = { .valid = 1 },
+               [IB_QPS_ERR]   = { .valid = 1 },
+               [IB_QPS_RTS]   = {
+                       .valid = 1,
+                       .opt_param = IB_QP_CUR_STATE |
+                                    IB_QP_QKEY,
+               }
+       },
+       [IB_QPS_ERR] = {
+               [IB_QPS_RESET] = { .valid = 1 },
+               [IB_QPS_ERR]   = { .valid = 1 },
+       }
+};
+
+static bool efa_modify_srd_qp_is_ok(enum ib_qp_state cur_state,
+                                   enum ib_qp_state next_state,
+                                   enum ib_qp_attr_mask mask)
+{
+       enum ib_qp_attr_mask req_param, opt_param;
+
+       if (mask & IB_QP_CUR_STATE  &&
+           cur_state != IB_QPS_RTR && cur_state != IB_QPS_RTS &&
+           cur_state != IB_QPS_SQD && cur_state != IB_QPS_SQE)
+               return false;
+
+       if (!srd_qp_state_table[cur_state][next_state].valid)
+               return false;
+
+       req_param = srd_qp_state_table[cur_state][next_state].req_param;
+       opt_param = srd_qp_state_table[cur_state][next_state].opt_param;
+
+       if ((mask & req_param) != req_param)
+               return false;
+
+       if (mask & ~(req_param | opt_param | IB_QP_STATE))
+               return false;
+
+       return true;
+}
+
 static int efa_modify_qp_validate(struct efa_dev *dev, struct efa_qp *qp,
                                  struct ib_qp_attr *qp_attr, int qp_attr_mask,
                                  enum ib_qp_state cur_state,
                                  enum ib_qp_state new_state)
 {
+       int err;
+
 #define EFA_MODIFY_QP_SUPP_MASK \
        (IB_QP_STATE | IB_QP_CUR_STATE | IB_QP_EN_SQD_ASYNC_NOTIFY | \
         IB_QP_PKEY_INDEX | IB_QP_PORT | IB_QP_QKEY | IB_QP_SQ_PSN)
@@ -756,8 +865,14 @@ static int efa_modify_qp_validate(struct efa_dev *dev, struct efa_qp *qp,
                return -EOPNOTSUPP;
        }
 
-       if (!ib_modify_qp_is_ok(cur_state, new_state, IB_QPT_UD,
-                               qp_attr_mask)) {
+       if (qp->ibqp.qp_type == IB_QPT_DRIVER)
+               err = !efa_modify_srd_qp_is_ok(cur_state, new_state,
+                                              qp_attr_mask);
+       else
+               err = !ib_modify_qp_is_ok(cur_state, new_state, IB_QPT_UD,
+                                         qp_attr_mask);
+
+       if (err) {
                ibdev_dbg(&dev->ibdev, "Invalid modify QP parameters\n");
                return -EINVAL;
        }