]> git.droids-corp.org - dpdk.git/commitdiff
common/mlx5: add DevX virtq commands
authorMatan Azrad <matan@mellanox.com>
Wed, 29 Jan 2020 12:38:40 +0000 (12:38 +0000)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 5 Feb 2020 08:51:20 +0000 (09:51 +0100)
Virtio emulation offload allows SW to offload the I/O operations of a
virtio virtqueue, using the device, allowing an improved performance
for its users.
While supplying all the relevant Virtqueue information (type, size,
memory location, doorbell information, etc.). The device can then
offload the I/O operation of this queue, according to its device type
characteristics.

Some of the virtio features can be supported according to the device
capability, for example, TSO and checksum.

Add virtio queue create, modify and query DevX commands.

Signed-off-by: Matan Azrad <matan@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
drivers/common/mlx5/mlx5_devx_cmds.c
drivers/common/mlx5/mlx5_devx_cmds.h
drivers/common/mlx5/mlx5_prm.h
drivers/common/mlx5/rte_common_mlx5_version.map

index cdc041b6e4f1fa850ec275b447c18bbd0c44dada..24255130a3f33574709d1b7c5c50fd199ed9eec2 100644 (file)
@@ -377,24 +377,18 @@ mlx5_devx_cmd_query_hca_vdpa_attr(struct ibv_context *ctx,
                vdpa_attr->max_num_virtio_queues =
                        MLX5_GET(virtio_emulation_cap, hcattr,
                                 max_num_virtio_queues);
-               vdpa_attr->umem_1_buffer_param_a =
-                       MLX5_GET(virtio_emulation_cap, hcattr,
-                                umem_1_buffer_param_a);
-               vdpa_attr->umem_1_buffer_param_b =
-                       MLX5_GET(virtio_emulation_cap, hcattr,
-                                umem_1_buffer_param_b);
-               vdpa_attr->umem_2_buffer_param_a =
-                       MLX5_GET(virtio_emulation_cap, hcattr,
-                                umem_2_buffer_param_a);
-               vdpa_attr->umem_2_buffer_param_b =
-                       MLX5_GET(virtio_emulation_cap, hcattr,
-                                umem_2_buffer_param_a);
-               vdpa_attr->umem_3_buffer_param_a =
-                       MLX5_GET(virtio_emulation_cap, hcattr,
-                                umem_3_buffer_param_a);
-               vdpa_attr->umem_3_buffer_param_b =
-                       MLX5_GET(virtio_emulation_cap, hcattr,
-                                umem_3_buffer_param_b);
+               vdpa_attr->umems[0].a = MLX5_GET(virtio_emulation_cap, hcattr,
+                                                umem_1_buffer_param_a);
+               vdpa_attr->umems[0].b = MLX5_GET(virtio_emulation_cap, hcattr,
+                                                umem_1_buffer_param_b);
+               vdpa_attr->umems[1].a = MLX5_GET(virtio_emulation_cap, hcattr,
+                                                umem_2_buffer_param_a);
+               vdpa_attr->umems[1].b = MLX5_GET(virtio_emulation_cap, hcattr,
+                                                umem_2_buffer_param_b);
+               vdpa_attr->umems[2].a = MLX5_GET(virtio_emulation_cap, hcattr,
+                                                umem_3_buffer_param_a);
+               vdpa_attr->umems[2].b = MLX5_GET(virtio_emulation_cap, hcattr,
+                                                umem_3_buffer_param_b);
        }
 }
 
@@ -1150,3 +1144,172 @@ mlx5_devx_cmd_create_cq(struct ibv_context *ctx, struct mlx5_devx_cq_attr *attr)
        cq_obj->id = MLX5_GET(create_cq_out, out, cqn);
        return cq_obj;
 }
+
+/**
+ * Create VIRTQ using DevX API.
+ *
+ * @param[in] ctx
+ *   ibv_context returned from mlx5dv_open_device.
+ * @param [in] attr
+ *   Pointer to VIRTQ attributes structure.
+ *
+ * @return
+ *   The DevX object created, NULL otherwise and rte_errno is set.
+ */
+struct mlx5_devx_obj *
+mlx5_devx_cmd_create_virtq(struct ibv_context *ctx,
+                          struct mlx5_devx_virtq_attr *attr)
+{
+       uint32_t in[MLX5_ST_SZ_DW(create_virtq_in)] = {0};
+       uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
+       struct mlx5_devx_obj *virtq_obj = rte_zmalloc(__func__,
+                                                    sizeof(*virtq_obj), 0);
+       void *virtq = MLX5_ADDR_OF(create_virtq_in, in, virtq);
+       void *hdr = MLX5_ADDR_OF(create_virtq_in, in, hdr);
+       void *virtctx = MLX5_ADDR_OF(virtio_net_q, virtq, virtio_q_context);
+
+       if (!virtq_obj) {
+               DRV_LOG(ERR, "Failed to allocate virtq data.");
+               rte_errno = ENOMEM;
+               return NULL;
+       }
+       MLX5_SET(general_obj_in_cmd_hdr, hdr, opcode,
+                MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
+       MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_type,
+                MLX5_GENERAL_OBJ_TYPE_VIRTQ);
+       MLX5_SET16(virtio_net_q, virtq, hw_available_index,
+                  attr->hw_available_index);
+       MLX5_SET16(virtio_net_q, virtq, hw_used_index, attr->hw_used_index);
+       MLX5_SET16(virtio_net_q, virtq, tso_ipv4, attr->tso_ipv4);
+       MLX5_SET16(virtio_net_q, virtq, tso_ipv6, attr->tso_ipv6);
+       MLX5_SET16(virtio_net_q, virtq, tx_csum, attr->tx_csum);
+       MLX5_SET16(virtio_net_q, virtq, rx_csum, attr->rx_csum);
+       MLX5_SET16(virtio_q, virtctx, virtio_version_1_0,
+                  attr->virtio_version_1_0);
+       MLX5_SET16(virtio_q, virtctx, event_mode, attr->event_mode);
+       MLX5_SET(virtio_q, virtctx, event_qpn_or_msix, attr->qp_id);
+       MLX5_SET64(virtio_q, virtctx, desc_addr, attr->desc_addr);
+       MLX5_SET64(virtio_q, virtctx, used_addr, attr->used_addr);
+       MLX5_SET64(virtio_q, virtctx, available_addr, attr->available_addr);
+       MLX5_SET16(virtio_q, virtctx, queue_index, attr->queue_index);
+       MLX5_SET16(virtio_q, virtctx, queue_size, attr->q_size);
+       MLX5_SET(virtio_q, virtctx, virtio_q_mkey, attr->mkey);
+       MLX5_SET(virtio_q, virtctx, umem_1_id, attr->umems[0].id);
+       MLX5_SET(virtio_q, virtctx, umem_1_size, attr->umems[0].size);
+       MLX5_SET64(virtio_q, virtctx, umem_1_offset, attr->umems[0].offset);
+       MLX5_SET(virtio_q, virtctx, umem_2_id, attr->umems[1].id);
+       MLX5_SET(virtio_q, virtctx, umem_2_size, attr->umems[1].size);
+       MLX5_SET64(virtio_q, virtctx, umem_2_offset, attr->umems[1].offset);
+       MLX5_SET(virtio_q, virtctx, umem_3_id, attr->umems[2].id);
+       MLX5_SET(virtio_q, virtctx, umem_3_size, attr->umems[2].size);
+       MLX5_SET64(virtio_q, virtctx, umem_3_offset, attr->umems[2].offset);
+       MLX5_SET(virtio_net_q, virtq, tisn_or_qpn, attr->tis_id);
+       virtq_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out,
+                                                   sizeof(out));
+       if (!virtq_obj->obj) {
+               rte_errno = errno;
+               DRV_LOG(ERR, "Failed to create VIRTQ Obj using DevX.");
+               rte_free(virtq_obj);
+               return NULL;
+       }
+       virtq_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
+       return virtq_obj;
+}
+
+/**
+ * Modify VIRTQ using DevX API.
+ *
+ * @param[in] virtq_obj
+ *   Pointer to virtq object structure.
+ * @param [in] attr
+ *   Pointer to modify virtq attributes structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_devx_cmd_modify_virtq(struct mlx5_devx_obj *virtq_obj,
+                          struct mlx5_devx_virtq_attr *attr)
+{
+       uint32_t in[MLX5_ST_SZ_DW(create_virtq_in)] = {0};
+       uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
+       void *virtq = MLX5_ADDR_OF(create_virtq_in, in, virtq);
+       void *hdr = MLX5_ADDR_OF(create_virtq_in, in, hdr);
+       void *virtctx = MLX5_ADDR_OF(virtio_net_q, virtq, virtio_q_context);
+       int ret;
+
+       MLX5_SET(general_obj_in_cmd_hdr, hdr, opcode,
+                MLX5_CMD_OP_MODIFY_GENERAL_OBJECT);
+       MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_type,
+                MLX5_GENERAL_OBJ_TYPE_VIRTQ);
+       MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_id, virtq_obj->id);
+       MLX5_SET64(virtio_net_q, virtq, modify_field_select, attr->type);
+       MLX5_SET16(virtio_q, virtctx, queue_index, attr->queue_index);
+       switch (attr->type) {
+       case MLX5_VIRTQ_MODIFY_TYPE_STATE:
+               MLX5_SET16(virtio_net_q, virtq, state, attr->state);
+               break;
+       case MLX5_VIRTQ_MODIFY_TYPE_DIRTY_BITMAP_PARAMS:
+               MLX5_SET(virtio_net_q, virtq, dirty_bitmap_mkey,
+                        attr->dirty_bitmap_mkey);
+               MLX5_SET64(virtio_net_q, virtq, dirty_bitmap_addr,
+                        attr->dirty_bitmap_addr);
+               MLX5_SET(virtio_net_q, virtq, dirty_bitmap_size,
+                        attr->dirty_bitmap_size);
+               break;
+       case MLX5_VIRTQ_MODIFY_TYPE_DIRTY_BITMAP_DUMP_ENABLE:
+               MLX5_SET(virtio_net_q, virtq, dirty_bitmap_dump_enable,
+                        attr->dirty_bitmap_dump_enable);
+               break;
+       default:
+               rte_errno = EINVAL;
+               return -rte_errno;
+       }
+       ret = mlx5_glue->devx_obj_modify(virtq_obj->obj, in, sizeof(in),
+                                        out, sizeof(out));
+       if (ret) {
+               DRV_LOG(ERR, "Failed to modify VIRTQ using DevX.");
+               rte_errno = errno;
+               return -errno;
+       }
+       return ret;
+}
+
+/**
+ * Query VIRTQ using DevX API.
+ *
+ * @param[in] virtq_obj
+ *   Pointer to virtq object structure.
+ * @param [in/out] attr
+ *   Pointer to virtq attributes structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_devx_cmd_query_virtq(struct mlx5_devx_obj *virtq_obj,
+                          struct mlx5_devx_virtq_attr *attr)
+{
+       uint32_t in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {0};
+       uint32_t out[MLX5_ST_SZ_DW(query_virtq_out)] = {0};
+       void *hdr = MLX5_ADDR_OF(query_virtq_out, in, hdr);
+       void *virtq = MLX5_ADDR_OF(query_virtq_out, out, virtq);
+       int ret;
+
+       MLX5_SET(general_obj_in_cmd_hdr, hdr, opcode,
+                MLX5_CMD_OP_QUERY_GENERAL_OBJECT);
+       MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_type,
+                MLX5_GENERAL_OBJ_TYPE_VIRTQ);
+       MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_id, virtq_obj->id);
+       ret = mlx5_glue->devx_obj_query(virtq_obj->obj, in, sizeof(in),
+                                        out, sizeof(out));
+       if (ret) {
+               DRV_LOG(ERR, "Failed to modify VIRTQ using DevX.");
+               rte_errno = errno;
+               return -errno;
+       }
+       attr->hw_available_index = MLX5_GET16(virtio_net_q, virtq,
+                                             hw_available_index);
+       attr->hw_used_index = MLX5_GET16(virtio_net_q, virtq, hw_used_index);
+       return ret;
+}
index 581658b73ae754c26412f9e4edf5f4cd9240daa0..1631c08aeea6d9644dc84d41aef2d7dd28843840 100644 (file)
@@ -64,12 +64,10 @@ struct mlx5_hca_vdpa_attr {
        uint32_t log_doorbell_stride:5;
        uint32_t log_doorbell_bar_size:5;
        uint32_t max_num_virtio_queues;
-       uint32_t umem_1_buffer_param_a;
-       uint32_t umem_1_buffer_param_b;
-       uint32_t umem_2_buffer_param_a;
-       uint32_t umem_2_buffer_param_b;
-       uint32_t umem_3_buffer_param_a;
-       uint32_t umem_3_buffer_param_b;
+       struct {
+               uint32_t a;
+               uint32_t b;
+       } umems[3];
        uint64_t doorbell_bar_offset;
 };
 
@@ -250,6 +248,37 @@ struct mlx5_devx_cq_attr {
        uint64_t db_addr;
 };
 
+/* Virtq attributes structure, used by VIRTQ operations. */
+struct mlx5_devx_virtq_attr {
+       uint16_t hw_available_index;
+       uint16_t hw_used_index;
+       uint16_t q_size;
+       uint32_t virtio_version_1_0:1;
+       uint32_t tso_ipv4:1;
+       uint32_t tso_ipv6:1;
+       uint32_t tx_csum:1;
+       uint32_t rx_csum:1;
+       uint32_t event_mode:3;
+       uint32_t state:4;
+       uint32_t dirty_bitmap_dump_enable:1;
+       uint32_t dirty_bitmap_mkey;
+       uint32_t dirty_bitmap_size;
+       uint32_t mkey;
+       uint32_t qp_id;
+       uint32_t queue_index;
+       uint32_t tis_id;
+       uint64_t dirty_bitmap_addr;
+       uint64_t type;
+       uint64_t desc_addr;
+       uint64_t used_addr;
+       uint64_t available_addr;
+       struct {
+               uint32_t id;
+               uint32_t size;
+               uint64_t offset;
+       } umems[3];
+};
+
 /* mlx5_devx_cmds.c */
 
 struct mlx5_devx_obj *mlx5_devx_cmd_flow_counter_alloc(struct ibv_context *ctx,
@@ -288,4 +317,11 @@ int mlx5_devx_cmd_flow_dump(void *fdb_domain, void *rx_domain, void *tx_domain,
                            FILE *file);
 struct mlx5_devx_obj *mlx5_devx_cmd_create_cq(struct ibv_context *ctx,
                                              struct mlx5_devx_cq_attr *attr);
+struct mlx5_devx_obj *mlx5_devx_cmd_create_virtq(struct ibv_context *ctx,
+                                            struct mlx5_devx_virtq_attr *attr);
+int mlx5_devx_cmd_modify_virtq(struct mlx5_devx_obj *virtq_obj,
+                              struct mlx5_devx_virtq_attr *attr);
+int mlx5_devx_cmd_query_virtq(struct mlx5_devx_obj *virtq_obj,
+                             struct mlx5_devx_virtq_attr *attr);
+
 #endif /* RTE_PMD_MLX5_DEVX_CMDS_H_ */
index a4082b91a12facf172dc7781ff02b96c7eec0a7b..4b8a34c707767057b118a2143f9daa655f7f6033 100644 (file)
@@ -527,6 +527,8 @@ typedef uint8_t u8;
 #define __mlx5_16_bit_off(typ, fld) (16 - __mlx5_bit_sz(typ, fld) - \
                                    (__mlx5_bit_off(typ, fld) & 0xf))
 #define __mlx5_mask16(typ, fld) ((u16)((1ull << __mlx5_bit_sz(typ, fld)) - 1))
+#define __mlx5_16_mask(typ, fld) (__mlx5_mask16(typ, fld) << \
+                                 __mlx5_16_bit_off(typ, fld))
 #define MLX5_ST_SZ_BYTES(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 8)
 #define MLX5_ST_SZ_DW(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 32)
 #define MLX5_BYTE_OFF(typ, fld) (__mlx5_bit_off(typ, fld) / 8)
@@ -551,6 +553,17 @@ typedef uint8_t u8;
                        rte_cpu_to_be_64(v); \
        } while (0)
 
+#define MLX5_SET16(typ, p, fld, v) \
+       do { \
+               u16 _v = v; \
+               *((__be16 *)(p) + __mlx5_16_off(typ, fld)) = \
+               rte_cpu_to_be_16((rte_be_to_cpu_16(*((__be16 *)(p) + \
+                                 __mlx5_16_off(typ, fld))) & \
+                                 (~__mlx5_16_mask(typ, fld))) | \
+                                (((_v) & __mlx5_mask16(typ, fld)) << \
+                                 __mlx5_16_bit_off(typ, fld))); \
+       } while (0)
+
 #define MLX5_GET(typ, p, fld) \
        ((rte_be_to_cpu_32(*((__be32 *)(p) +\
        __mlx5_dw_off(typ, fld))) >> __mlx5_dw_bit_off(typ, fld)) & \
@@ -723,6 +736,9 @@ enum {
        MLX5_CMD_OP_CREATE_RQT = 0x916,
        MLX5_CMD_OP_ALLOC_FLOW_COUNTER = 0x939,
        MLX5_CMD_OP_QUERY_FLOW_COUNTER = 0x93b,
+       MLX5_CMD_OP_CREATE_GENERAL_OBJECT = 0xa00,
+       MLX5_CMD_OP_MODIFY_GENERAL_OBJECT = 0xa01,
+       MLX5_CMD_OP_QUERY_GENERAL_OBJECT = 0xa02,
 };
 
 enum {
@@ -1691,6 +1707,11 @@ struct mlx5_ifc_create_tir_in_bits {
        struct mlx5_ifc_tirc_bits ctx;
 };
 
+enum {
+       MLX5_INLINE_Q_TYPE_RQ = 0x0,
+       MLX5_INLINE_Q_TYPE_VIRTQ = 0x1,
+};
+
 struct mlx5_ifc_rq_num_bits {
        u8 reserved_at_0[0x8];
        u8 rq_num[0x18];
@@ -1917,6 +1938,102 @@ struct mlx5_ifc_create_cq_in_bits {
        u8 pas[];
 };
 
+enum {
+       MLX5_GENERAL_OBJ_TYPE_VIRTQ = 0x000d,
+};
+
+struct mlx5_ifc_general_obj_in_cmd_hdr_bits {
+       u8 opcode[0x10];
+       u8 reserved_at_10[0x20];
+       u8 obj_type[0x10];
+       u8 obj_id[0x20];
+       u8 reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_general_obj_out_cmd_hdr_bits {
+       u8 status[0x8];
+       u8 reserved_at_8[0x18];
+       u8 syndrome[0x20];
+       u8 obj_id[0x20];
+       u8 reserved_at_60[0x20];
+};
+
+enum {
+       MLX5_VIRTQ_STATE_INIT = 0,
+       MLX5_VIRTQ_STATE_RDY = 1,
+       MLX5_VIRTQ_STATE_SUSPEND = 2,
+       MLX5_VIRTQ_STATE_ERROR = 3,
+};
+
+enum {
+       MLX5_VIRTQ_MODIFY_TYPE_STATE = (1UL << 0),
+       MLX5_VIRTQ_MODIFY_TYPE_DIRTY_BITMAP_PARAMS = (1UL << 3),
+       MLX5_VIRTQ_MODIFY_TYPE_DIRTY_BITMAP_DUMP_ENABLE = (1UL << 4),
+};
+
+struct mlx5_ifc_virtio_q_bits {
+       u8 virtio_q_type[0x8];
+       u8 reserved_at_8[0x5];
+       u8 event_mode[0x3];
+       u8 queue_index[0x10];
+       u8 full_emulation[0x1];
+       u8 virtio_version_1_0[0x1];
+       u8 reserved_at_22[0x2];
+       u8 offload_type[0x4];
+       u8 event_qpn_or_msix[0x18];
+       u8 doorbell_stride_idx[0x10];
+       u8 queue_size[0x10];
+       u8 device_emulation_id[0x20];
+       u8 desc_addr[0x40];
+       u8 used_addr[0x40];
+       u8 available_addr[0x40];
+       u8 virtio_q_mkey[0x20];
+       u8 reserved_at_160[0x20];
+       u8 umem_1_id[0x20];
+       u8 umem_1_size[0x20];
+       u8 umem_1_offset[0x40];
+       u8 umem_2_id[0x20];
+       u8 umem_2_size[0x20];
+       u8 umem_2_offset[0x40];
+       u8 umem_3_id[0x20];
+       u8 umem_3_size[0x20];
+       u8 umem_3_offset[0x40];
+       u8 reserved_at_300[0x100];
+};
+
+struct mlx5_ifc_virtio_net_q_bits {
+       u8 modify_field_select[0x40];
+       u8 reserved_at_40[0x40];
+       u8 tso_ipv4[0x1];
+       u8 tso_ipv6[0x1];
+       u8 tx_csum[0x1];
+       u8 rx_csum[0x1];
+       u8 reserved_at_84[0x6];
+       u8 dirty_bitmap_dump_enable[0x1];
+       u8 vhost_log_page[0x5];
+       u8 reserved_at_90[0xc];
+       u8 state[0x4];
+       u8 error_type[0x8];
+       u8 tisn_or_qpn[0x18];
+       u8 dirty_bitmap_mkey[0x20];
+       u8 dirty_bitmap_size[0x20];
+       u8 dirty_bitmap_addr[0x40];
+       u8 hw_available_index[0x10];
+       u8 hw_used_index[0x10];
+       u8 reserved_at_160[0xa0];
+       struct mlx5_ifc_virtio_q_bits virtio_q_context;
+};
+
+struct mlx5_ifc_create_virtq_in_bits {
+       struct mlx5_ifc_general_obj_in_cmd_hdr_bits hdr;
+       struct mlx5_ifc_virtio_net_q_bits virtq;
+};
+
+struct mlx5_ifc_query_virtq_out_bits {
+       struct mlx5_ifc_general_obj_in_cmd_hdr_bits hdr;
+       struct mlx5_ifc_virtio_net_q_bits virtq;
+};
+
 /* CQE format mask. */
 #define MLX5E_CQE_FORMAT_MASK 0xc
 
index c6a203d36dc882433b6bfedad9a6ae970d9c50f9..f3082ce23d16c2037e19f9ad4c234e26b708b16f 100644 (file)
@@ -8,6 +8,7 @@ DPDK_20.02 {
        mlx5_devx_cmd_create_tir;
        mlx5_devx_cmd_create_td;
        mlx5_devx_cmd_create_tis;
+       mlx5_devx_cmd_create_virtq;
        mlx5_devx_cmd_destroy;
        mlx5_devx_cmd_flow_counter_alloc;
        mlx5_devx_cmd_flow_counter_query;
@@ -15,8 +16,10 @@ DPDK_20.02 {
        mlx5_devx_cmd_mkey_create;
        mlx5_devx_cmd_modify_rq;
        mlx5_devx_cmd_modify_sq;
+       mlx5_devx_cmd_modify_virtq;
        mlx5_devx_cmd_qp_query_tis_td;
        mlx5_devx_cmd_query_hca_attr;
+       mlx5_devx_cmd_query_virtq;
        mlx5_devx_get_out_command_status;
 
        mlx5_dev_to_pci_addr;