History

IB/mlx5: Add DEVX support for memory registration

Add support to register a memory with the firmware via the DEVX interface. The driver translates a given user address to ib_umem then it will register the physical addresses with the firmware and get a unique id for this registration to be used for this virtual address.

Yishai Hadas committed 8 years ago

Commit aeae9451 parent 7c043e93 files · +217 −1Browse files

Unified · Split

3 files
  1. drivers/infiniband/hw/mlx5/devx.c +198 −1
  2. include/linux/mlx5/mlx5_ifc.h +1 −0
  3. include/uapi/rdma/mlx5_user_ioctl_cmds.h +18 −0
drivers/infiniband/hw/mlx5/devx.c+198−1
@@ -24,6 +24,22 @@ struct devx_obj { · 23 unmodified lines
2424 u32 dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW];
2525 };
2626
27+struct devx_umem {
28+ struct mlx5_core_dev *mdev;
29+ struct ib_umem *umem;
30+ u32 page_offset;
31+ int page_shift;
32+ int ncont;
33+ u32 dinlen;
34+ u32 dinbox[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)];
35+};
36+
37+struct devx_umem_reg_cmd {
38+ void *in;
39+ u32 inlen;
40+ u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
41+};
42+
2743 static struct mlx5_ib_ucontext *devx_ufile2uctx(struct ib_uverbs_file *file)
2844 {
2945 return to_mucontext(ib_uverbs_get_ucontext(file));
@@ -788,6 +804,181 @@ other_cmd_free: · 758 unmodified lines
788804 return err;
789805 }
790806
807+static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext,
808+ struct uverbs_attr_bundle *attrs,
809+ struct devx_umem *obj)
810+{
811+ u64 addr;
812+ size_t size;
813+ int access;
814+ int npages;
815+ int err;
816+ u32 page_mask;
817+
818+ if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) ||
819+ uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN) ||
820+ uverbs_copy_from(&access, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS))
821+ return -EFAULT;
822+
823+ err = ib_check_mr_access(access);
824+ if (err)
825+ return err;
826+
827+ obj->umem = ib_umem_get(ucontext, addr, size, access, 0);
828+ if (IS_ERR(obj->umem))
829+ return PTR_ERR(obj->umem);
830+
831+ mlx5_ib_cont_pages(obj->umem, obj->umem->address,
832+ MLX5_MKEY_PAGE_SHIFT_MASK, &npages,
833+ &obj->page_shift, &obj->ncont, NULL);
834+
835+ if (!npages) {
836+ ib_umem_release(obj->umem);
837+ return -EINVAL;
838+ }
839+
840+ page_mask = (1 << obj->page_shift) - 1;
841+ obj->page_offset = obj->umem->address & page_mask;
842+
843+ return 0;
844+}
845+
846+static int devx_umem_reg_cmd_alloc(struct devx_umem *obj,
847+ struct devx_umem_reg_cmd *cmd)
848+{
849+ cmd->inlen = MLX5_ST_SZ_BYTES(create_umem_in) +
850+ (MLX5_ST_SZ_BYTES(mtt) * obj->ncont);
851+ cmd->in = kvzalloc(cmd->inlen, GFP_KERNEL);
852+ return cmd->in ? 0 : -ENOMEM;
853+}
854+
855+static void devx_umem_reg_cmd_free(struct devx_umem_reg_cmd *cmd)
856+{
857+ kvfree(cmd->in);
858+}
859+
860+static void devx_umem_reg_cmd_build(struct mlx5_ib_dev *dev,
861+ struct devx_umem *obj,
862+ struct devx_umem_reg_cmd *cmd)
863+{
864+ void *umem;
865+ __be64 *mtt;
866+
867+ umem = MLX5_ADDR_OF(create_umem_in, cmd->in, umem);
868+ mtt = (__be64 *)MLX5_ADDR_OF(umem, umem, mtt);
869+
870+ MLX5_SET(general_obj_in_cmd_hdr, cmd->in, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
871+ MLX5_SET(general_obj_in_cmd_hdr, cmd->in, obj_type, MLX5_OBJ_TYPE_UMEM);
872+ MLX5_SET64(umem, umem, num_of_mtt, obj->ncont);
873+ MLX5_SET(umem, umem, log_page_size, obj->page_shift -
874+ MLX5_ADAPTER_PAGE_SHIFT);
875+ MLX5_SET(umem, umem, page_offset, obj->page_offset);
876+ mlx5_ib_populate_pas(dev, obj->umem, obj->page_shift, mtt,
877+ (obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) |
878+ MLX5_IB_MTT_READ);
879+}
880+
881+static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)(struct ib_device *ib_dev,
882+ struct ib_uverbs_file *file,
883+ struct uverbs_attr_bundle *attrs)
884+{
885+ struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
886+ struct mlx5_ib_dev *dev = to_mdev(ib_dev);
887+ struct devx_umem_reg_cmd cmd;
888+ struct devx_umem *obj;
889+ struct ib_uobject *uobj;
890+ u32 obj_id;
891+ int err;
892+
893+ if (!c->devx_uid)
894+ return -EPERM;
895+
896+ uobj = uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE);
897+ obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL);
898+ if (!obj)
899+ return -ENOMEM;
900+
901+ err = devx_umem_get(dev, &c->ibucontext, attrs, obj);
902+ if (err)
903+ goto err_obj_free;
904+
905+ err = devx_umem_reg_cmd_alloc(obj, &cmd);
906+ if (err)
907+ goto err_umem_release;
908+
909+ devx_umem_reg_cmd_build(dev, obj, &cmd);
910+
911+ MLX5_SET(general_obj_in_cmd_hdr, cmd.in, uid, c->devx_uid);
912+ err = mlx5_cmd_exec(dev->mdev, cmd.in, cmd.inlen, cmd.out,
913+ sizeof(cmd.out));
914+ if (err)
915+ goto err_umem_reg_cmd_free;
916+
917+ obj->mdev = dev->mdev;
918+ uobj->object = obj;
919+ devx_obj_build_destroy_cmd(cmd.in, cmd.out, obj->dinbox, &obj->dinlen, &obj_id);
920+ err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, &obj_id, sizeof(obj_id));
921+ if (err)
922+ goto err_umem_destroy;
923+
924+ devx_umem_reg_cmd_free(&cmd);
925+
926+ return 0;
927+
928+err_umem_destroy:
929+ mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, cmd.out, sizeof(cmd.out));
930+err_umem_reg_cmd_free:
931+ devx_umem_reg_cmd_free(&cmd);
932+err_umem_release:
933+ ib_umem_release(obj->umem);
934+err_obj_free:
935+ kfree(obj);
936+ return err;
937+}
938+
939+static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_DEREG)(struct ib_device *ib_dev,
940+ struct ib_uverbs_file *file,
941+ struct uverbs_attr_bundle *attrs)
942+{
943+ return 0;
944+}
945+
946+static int devx_umem_cleanup(struct ib_uobject *uobject,
947+ enum rdma_remove_reason why)
948+{
949+ struct devx_umem *obj = uobject->object;
950+ u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
951+ int err;
952+
953+ err = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
954+ if (err && why == RDMA_REMOVE_DESTROY)
955+ return err;
956+
957+ ib_umem_release(obj->umem);
958+ kfree(obj);
959+ return 0;
960+}
961+
962+static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG,
963+ &UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE,
964+ MLX5_IB_OBJECT_DEVX_UMEM,
965+ UVERBS_ACCESS_NEW,
966+ UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
967+ &UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR, UVERBS_ATTR_TYPE(u64),
968+ UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
969+ &UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN, UVERBS_ATTR_TYPE(u64),
970+ UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
971+ &UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS, UVERBS_ATTR_TYPE(u32),
972+ UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
973+ &UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, UVERBS_ATTR_TYPE(u32),
974+ UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
975+
976+static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG,
977+ &UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE,
978+ MLX5_IB_OBJECT_DEVX_UMEM,
979+ UVERBS_ACCESS_DESTROY,
980+ UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
981+
791982 static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR,
792983 &UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX, UVERBS_ATTR_TYPE(u32),
793984 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
@@ -868,6 +1059,12 @@ static DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ, · 74 unmodified lines
8681059 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY),
8691060 &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY));
8701061
1062+static DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM,
1063+ &UVERBS_TYPE_ALLOC_IDR(0, devx_umem_cleanup),
1064+ &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG),
1065+ &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG));
1066+
8711067 static DECLARE_UVERBS_OBJECT_TREE(devx_objects,
8721068 &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX),
873− &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ));
1069+ &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ),
1070+ &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM));
include/linux/mlx5/mlx5_ifc.h+1−0
@@ -82,6 +82,7 @@ enum { · 81 unmodified lines
8282
8383 enum {
8484 MLX5_OBJ_TYPE_UCTX = 0x0004,
85+ MLX5_OBJ_TYPE_UMEM = 0x0005,
8586 };
8687
8788 enum {
include/uapi/rdma/mlx5_user_ioctl_cmds.h+18−0
@@ -89,9 +89,27 @@ enum mlx5_ib_devx_obj_methods { · 88 unmodified lines
8989 MLX5_IB_METHOD_DEVX_OBJ_QUERY,
9090 };
9191
92+enum mlx5_ib_devx_umem_reg_attrs {
93+ MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
94+ MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR,
95+ MLX5_IB_ATTR_DEVX_UMEM_REG_LEN,
96+ MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
97+ MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID,
98+};
99+
100+enum mlx5_ib_devx_umem_dereg_attrs {
101+ MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
102+};
103+
104+enum mlx5_ib_devx_umem_methods {
105+ MLX5_IB_METHOD_DEVX_UMEM_REG = (1U << UVERBS_ID_NS_SHIFT),
106+ MLX5_IB_METHOD_DEVX_UMEM_DEREG,
107+};
108+
92109 enum mlx5_ib_devx_objects {
93110 MLX5_IB_OBJECT_DEVX = (1U << UVERBS_ID_NS_SHIFT),
94111 MLX5_IB_OBJECT_DEVX_OBJ,
112+ MLX5_IB_OBJECT_DEVX_UMEM,
95113 };
96114
97115 #endif

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t