net/mlx5: Add DCT command interface
authorMoni Shoua <monis@mellanox.com>
Tue, 2 Jan 2018 14:19:28 +0000 (16:19 +0200)
committerJason Gunthorpe <jgg@mellanox.com>
Mon, 8 Jan 2018 18:38:49 +0000 (11:38 -0700)
Add a missing command interface to work with a DCT. It includes: creating,
destroying and get events for.

Signed-off-by: Moni Shoua <monis@mellanox.com>
Reviewed-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/eq.c
drivers/net/ethernet/mellanox/mlx5/core/qp.c
include/linux/mlx5/device.h
include/linux/mlx5/driver.h
include/linux/mlx5/qp.h

index 6077186..7d3d503 100644 (file)
@@ -417,7 +417,11 @@ static irqreturn_t mlx5_eq_int(int irq, void *eq_ptr)
                        cqn = be32_to_cpu(eqe->data.comp.cqn) & 0xffffff;
                        mlx5_cq_completion(dev, cqn);
                        break;
-
+               case MLX5_EVENT_TYPE_DCT_DRAINED:
+                       rsn = be32_to_cpu(eqe->data.dct.dctn) & 0xffffff;
+                       rsn |= (MLX5_RES_DCT << MLX5_USER_INDEX_LEN);
+                       mlx5_rsc_event(dev, rsn, eqe->type);
+                       break;
                case MLX5_EVENT_TYPE_PATH_MIG:
                case MLX5_EVENT_TYPE_COMM_EST:
                case MLX5_EVENT_TYPE_SQ_DRAINED:
@@ -715,6 +719,9 @@ int mlx5_start_eqs(struct mlx5_core_dev *dev)
 
        if (MLX5_CAP_GEN(dev, fpga))
                async_event_mask |= (1ull << MLX5_EVENT_TYPE_FPGA_ERROR);
+       if (MLX5_CAP_GEN_MAX(dev, dct))
+               async_event_mask |= (1ull << MLX5_EVENT_TYPE_DCT_DRAINED);
+
 
        err = mlx5_create_map_eq(dev, &table->cmd_eq, MLX5_EQ_VEC_CMD,
                                 MLX5_NUM_CMD_EQE, 1ull << MLX5_EVENT_TYPE_CMD,
index db9e665..0f5ddd2 100644 (file)
@@ -98,6 +98,11 @@ static u64 sq_allowed_event_types(void)
        return BIT(MLX5_EVENT_TYPE_WQ_CATAS_ERROR);
 }
 
+static u64 dct_allowed_event_types(void)
+{
+       return BIT(MLX5_EVENT_TYPE_DCT_DRAINED);
+}
+
 static bool is_event_type_allowed(int rsc_type, int event_type)
 {
        switch (rsc_type) {
@@ -107,6 +112,8 @@ static bool is_event_type_allowed(int rsc_type, int event_type)
                return BIT(event_type) & rq_allowed_event_types();
        case MLX5_EVENT_QUEUE_TYPE_SQ:
                return BIT(event_type) & sq_allowed_event_types();
+       case MLX5_EVENT_QUEUE_TYPE_DCT:
+               return BIT(event_type) & dct_allowed_event_types();
        default:
                WARN(1, "Event arrived for unknown resource type");
                return false;
@@ -116,6 +123,7 @@ static bool is_event_type_allowed(int rsc_type, int event_type)
 void mlx5_rsc_event(struct mlx5_core_dev *dev, u32 rsn, int event_type)
 {
        struct mlx5_core_rsc_common *common = mlx5_get_rsc(dev, rsn);
+       struct mlx5_core_dct *dct;
        struct mlx5_core_qp *qp;
 
        if (!common)
@@ -134,7 +142,11 @@ void mlx5_rsc_event(struct mlx5_core_dev *dev, u32 rsn, int event_type)
                qp = (struct mlx5_core_qp *)common;
                qp->event(qp, event_type);
                break;
-
+       case MLX5_RES_DCT:
+               dct = (struct mlx5_core_dct *)common;
+               if (event_type == MLX5_EVENT_TYPE_DCT_DRAINED)
+                       complete(&dct->drained);
+               break;
        default:
                mlx5_core_warn(dev, "invalid resource type for 0x%x\n", rsn);
        }
@@ -142,9 +154,9 @@ void mlx5_rsc_event(struct mlx5_core_dev *dev, u32 rsn, int event_type)
        mlx5_core_put_rsc(common);
 }
 
-static int create_qprqsq_common(struct mlx5_core_dev *dev,
-                               struct mlx5_core_qp *qp,
-                               int rsc_type)
+static int create_resource_common(struct mlx5_core_dev *dev,
+                                 struct mlx5_core_qp *qp,
+                                 int rsc_type)
 {
        struct mlx5_qp_table *table = &dev->priv.qp_table;
        int err;
@@ -165,8 +177,8 @@ static int create_qprqsq_common(struct mlx5_core_dev *dev,
        return 0;
 }
 
-static void destroy_qprqsq_common(struct mlx5_core_dev *dev,
-                                 struct mlx5_core_qp *qp)
+static void destroy_resource_common(struct mlx5_core_dev *dev,
+                                   struct mlx5_core_qp *qp)
 {
        struct mlx5_qp_table *table = &dev->priv.qp_table;
        unsigned long flags;
@@ -179,6 +191,40 @@ static void destroy_qprqsq_common(struct mlx5_core_dev *dev,
        wait_for_completion(&qp->common.free);
 }
 
+int mlx5_core_create_dct(struct mlx5_core_dev *dev,
+                        struct mlx5_core_dct *dct,
+                        u32 *in, int inlen)
+{
+       u32 out[MLX5_ST_SZ_DW(create_dct_out)]   = {0};
+       u32 din[MLX5_ST_SZ_DW(destroy_dct_in)]   = {0};
+       u32 dout[MLX5_ST_SZ_DW(destroy_dct_out)] = {0};
+       struct mlx5_core_qp *qp = &dct->mqp;
+       int err;
+
+       init_completion(&dct->drained);
+       MLX5_SET(create_dct_in, in, opcode, MLX5_CMD_OP_CREATE_DCT);
+
+       err = mlx5_cmd_exec(dev, in, inlen, &out, sizeof(out));
+       if (err) {
+               mlx5_core_warn(dev, "create DCT failed, ret %d\n", err);
+               return err;
+       }
+
+       qp->qpn = MLX5_GET(create_dct_out, out, dctn);
+       err = create_resource_common(dev, qp, MLX5_RES_DCT);
+       if (err)
+               goto err_cmd;
+
+       return 0;
+err_cmd:
+       MLX5_SET(destroy_dct_in, din, opcode, MLX5_CMD_OP_DESTROY_DCT);
+       MLX5_SET(destroy_dct_in, din, dctn, qp->qpn);
+       mlx5_cmd_exec(dev, (void *)&in, sizeof(din),
+                     (void *)&out, sizeof(dout));
+       return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_core_create_dct);
+
 int mlx5_core_create_qp(struct mlx5_core_dev *dev,
                        struct mlx5_core_qp *qp,
                        u32 *in, int inlen)
@@ -197,7 +243,7 @@ int mlx5_core_create_qp(struct mlx5_core_dev *dev,
        qp->qpn = MLX5_GET(create_qp_out, out, qpn);
        mlx5_core_dbg(dev, "qpn = 0x%x\n", qp->qpn);
 
-       err = create_qprqsq_common(dev, qp, MLX5_RES_QP);
+       err = create_resource_common(dev, qp, MLX5_RES_QP);
        if (err)
                goto err_cmd;
 
@@ -220,6 +266,47 @@ err_cmd:
 }
 EXPORT_SYMBOL_GPL(mlx5_core_create_qp);
 
+static int mlx5_core_drain_dct(struct mlx5_core_dev *dev,
+                              struct mlx5_core_dct *dct)
+{
+       u32 out[MLX5_ST_SZ_DW(drain_dct_out)] = {0};
+       u32 in[MLX5_ST_SZ_DW(drain_dct_in)]   = {0};
+       struct mlx5_core_qp *qp = &dct->mqp;
+
+       MLX5_SET(drain_dct_in, in, opcode, MLX5_CMD_OP_DRAIN_DCT);
+       MLX5_SET(drain_dct_in, in, dctn, qp->qpn);
+       return mlx5_cmd_exec(dev, (void *)&in, sizeof(in),
+                            (void *)&out, sizeof(out));
+}
+
+int mlx5_core_destroy_dct(struct mlx5_core_dev *dev,
+                         struct mlx5_core_dct *dct)
+{
+       u32 out[MLX5_ST_SZ_DW(destroy_dct_out)] = {0};
+       u32 in[MLX5_ST_SZ_DW(destroy_dct_in)]   = {0};
+       struct mlx5_core_qp *qp = &dct->mqp;
+       int err;
+
+       err = mlx5_core_drain_dct(dev, dct);
+       if (err) {
+               if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+                       goto destroy;
+               } else {
+                       mlx5_core_warn(dev, "failed drain DCT 0x%x with error 0x%x\n", qp->qpn, err);
+                       return err;
+               }
+       }
+       wait_for_completion(&dct->drained);
+destroy:
+       destroy_resource_common(dev, &dct->mqp);
+       MLX5_SET(destroy_dct_in, in, opcode, MLX5_CMD_OP_DESTROY_DCT);
+       MLX5_SET(destroy_dct_in, in, dctn, qp->qpn);
+       err = mlx5_cmd_exec(dev, (void *)&in, sizeof(in),
+                           (void *)&out, sizeof(out));
+       return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_core_destroy_dct);
+
 int mlx5_core_destroy_qp(struct mlx5_core_dev *dev,
                         struct mlx5_core_qp *qp)
 {
@@ -229,7 +316,7 @@ int mlx5_core_destroy_qp(struct mlx5_core_dev *dev,
 
        mlx5_debug_qp_remove(dev, qp);
 
-       destroy_qprqsq_common(dev, qp);
+       destroy_resource_common(dev, qp);
 
        MLX5_SET(destroy_qp_in, in, opcode, MLX5_CMD_OP_DESTROY_QP);
        MLX5_SET(destroy_qp_in, in, qpn, qp->qpn);
@@ -405,6 +492,20 @@ int mlx5_core_qp_query(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp,
 }
 EXPORT_SYMBOL_GPL(mlx5_core_qp_query);
 
+int mlx5_core_dct_query(struct mlx5_core_dev *dev, struct mlx5_core_dct *dct,
+                       u32 *out, int outlen)
+{
+       u32 in[MLX5_ST_SZ_DW(query_dct_in)] = {0};
+       struct mlx5_core_qp *qp = &dct->mqp;
+
+       MLX5_SET(query_dct_in, in, opcode, MLX5_CMD_OP_QUERY_DCT);
+       MLX5_SET(query_dct_in, in, dctn, qp->qpn);
+
+       return mlx5_cmd_exec(dev, (void *)&in, sizeof(in),
+                            (void *)out, outlen);
+}
+EXPORT_SYMBOL_GPL(mlx5_core_dct_query);
+
 int mlx5_core_xrcd_alloc(struct mlx5_core_dev *dev, u32 *xrcdn)
 {
        u32 out[MLX5_ST_SZ_DW(alloc_xrcd_out)] = {0};
@@ -441,7 +542,7 @@ int mlx5_core_create_rq_tracked(struct mlx5_core_dev *dev, u32 *in, int inlen,
                return err;
 
        rq->qpn = rqn;
-       err = create_qprqsq_common(dev, rq, MLX5_RES_RQ);
+       err = create_resource_common(dev, rq, MLX5_RES_RQ);
        if (err)
                goto err_destroy_rq;
 
@@ -457,7 +558,7 @@ EXPORT_SYMBOL(mlx5_core_create_rq_tracked);
 void mlx5_core_destroy_rq_tracked(struct mlx5_core_dev *dev,
                                  struct mlx5_core_qp *rq)
 {
-       destroy_qprqsq_common(dev, rq);
+       destroy_resource_common(dev, rq);
        mlx5_core_destroy_rq(dev, rq->qpn);
 }
 EXPORT_SYMBOL(mlx5_core_destroy_rq_tracked);
@@ -473,7 +574,7 @@ int mlx5_core_create_sq_tracked(struct mlx5_core_dev *dev, u32 *in, int inlen,
                return err;
 
        sq->qpn = sqn;
-       err = create_qprqsq_common(dev, sq, MLX5_RES_SQ);
+       err = create_resource_common(dev, sq, MLX5_RES_SQ);
        if (err)
                goto err_destroy_sq;
 
@@ -489,7 +590,7 @@ EXPORT_SYMBOL(mlx5_core_create_sq_tracked);
 void mlx5_core_destroy_sq_tracked(struct mlx5_core_dev *dev,
                                  struct mlx5_core_qp *sq)
 {
-       destroy_qprqsq_common(dev, sq);
+       destroy_resource_common(dev, sq);
        mlx5_core_destroy_sq(dev, sq->qpn);
 }
 EXPORT_SYMBOL(mlx5_core_destroy_sq_tracked);
index 52b8ea4..9aee835 100644 (file)
@@ -286,6 +286,7 @@ enum {
        MLX5_EVENT_QUEUE_TYPE_QP = 0,
        MLX5_EVENT_QUEUE_TYPE_RQ = 1,
        MLX5_EVENT_QUEUE_TYPE_SQ = 2,
+       MLX5_EVENT_QUEUE_TYPE_DCT = 6,
 };
 
 enum mlx5_event {
@@ -321,6 +322,8 @@ enum mlx5_event {
        MLX5_EVENT_TYPE_PAGE_FAULT         = 0xc,
        MLX5_EVENT_TYPE_NIC_VPORT_CHANGE   = 0xd,
 
+       MLX5_EVENT_TYPE_DCT_DRAINED        = 0x1c,
+
        MLX5_EVENT_TYPE_FPGA_ERROR         = 0x20,
 };
 
@@ -613,6 +616,11 @@ struct mlx5_eqe_pps {
        u8              rsvd2[12];
 } __packed;
 
+struct mlx5_eqe_dct {
+       __be32  reserved[6];
+       __be32  dctn;
+};
+
 union ev_data {
        __be32                          raw[7];
        struct mlx5_eqe_cmd             cmd;
@@ -628,6 +636,7 @@ union ev_data {
        struct mlx5_eqe_vport_change    vport_change;
        struct mlx5_eqe_port_module     port_module;
        struct mlx5_eqe_pps             pps;
+       struct mlx5_eqe_dct             dct;
 } __packed;
 
 struct mlx5_eqe {
index 2fe263f..0776554 100644 (file)
@@ -154,6 +154,13 @@ enum mlx5_dcbx_oper_mode {
        MLX5E_DCBX_PARAM_VER_OPER_AUTO  = 0x3,
 };
 
+enum mlx5_dct_atomic_mode {
+       MLX5_ATOMIC_MODE_DCT_OFF        = 20,
+       MLX5_ATOMIC_MODE_DCT_NONE       = 0 << MLX5_ATOMIC_MODE_DCT_OFF,
+       MLX5_ATOMIC_MODE_DCT_IB_COMP    = 1 << MLX5_ATOMIC_MODE_DCT_OFF,
+       MLX5_ATOMIC_MODE_DCT_CX         = 2 << MLX5_ATOMIC_MODE_DCT_OFF,
+};
+
 enum {
        MLX5_ATOMIC_OPS_CMP_SWAP        = 1 << 0,
        MLX5_ATOMIC_OPS_FETCH_ADD       = 1 << 1,
@@ -432,6 +439,7 @@ enum mlx5_res_type {
        MLX5_RES_SRQ    = 3,
        MLX5_RES_XSRQ   = 4,
        MLX5_RES_XRQ    = 5,
+       MLX5_RES_DCT    = MLX5_EVENT_QUEUE_TYPE_DCT,
 };
 
 struct mlx5_core_rsc_common {
index 62af751..4778d41 100644 (file)
@@ -473,6 +473,11 @@ struct mlx5_core_qp {
        int                     pid;
 };
 
+struct mlx5_core_dct {
+       struct mlx5_core_qp     mqp;
+       struct completion       drained;
+};
+
 struct mlx5_qp_path {
        u8                      fl_free_ar;
        u8                      rsvd3;
@@ -549,6 +554,9 @@ static inline struct mlx5_core_mkey *__mlx5_mr_lookup(struct mlx5_core_dev *dev,
        return radix_tree_lookup(&dev->priv.mkey_table.tree, key);
 }
 
+int mlx5_core_create_dct(struct mlx5_core_dev *dev,
+                        struct mlx5_core_dct *qp,
+                        u32 *in, int inlen);
 int mlx5_core_create_qp(struct mlx5_core_dev *dev,
                        struct mlx5_core_qp *qp,
                        u32 *in,
@@ -558,8 +566,12 @@ int mlx5_core_qp_modify(struct mlx5_core_dev *dev, u16 opcode,
                        struct mlx5_core_qp *qp);
 int mlx5_core_destroy_qp(struct mlx5_core_dev *dev,
                         struct mlx5_core_qp *qp);
+int mlx5_core_destroy_dct(struct mlx5_core_dev *dev,
+                         struct mlx5_core_dct *dct);
 int mlx5_core_qp_query(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp,
                       u32 *out, int outlen);
+int mlx5_core_dct_query(struct mlx5_core_dev *dev, struct mlx5_core_dct *dct,
+                       u32 *out, int outlen);
 
 int mlx5_core_set_delay_drop(struct mlx5_core_dev *dev,
                             u32 timeout_usec);