diff options
author | Sagi Grimberg <sagig@mellanox.com> | 2014-02-23 07:19:06 -0500 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2014-03-07 14:26:49 -0500 |
commit | 3121e3c441b5eccdd15e6c320ec32215b334b9ec (patch) | |
tree | caee56913d52fd2019ff11fcb7ce3af2d765eb36 | |
parent | 1b01d33560e78417334c2dc673bbfac6c644424c (diff) |
mlx5: Implement create_mr and destroy_mr
Support create_mr and destroy_mr verbs. Creating ib_mr may be done
for either ib_mr that will register regular page lists like
alloc_fast_reg_mr routine, or indirect ib_mrs that can register other
(pre-registered) ib_mrs in an indirect manner.
In addition user may request signature enable, that will mean that the
created ib_mr may be attached with signature attributes (BSF, PSVs).
Currently we only allow direct/indirect registration modes.
Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r-- | drivers/infiniband/hw/mlx5/main.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx5/mlx5_ib.h | 4 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx5/mr.c | 111 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/mr.c | 61 | ||||
-rw-r--r-- | include/linux/mlx5/device.h | 25 | ||||
-rw-r--r-- | include/linux/mlx5/driver.h | 19 |
6 files changed, 222 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index aa03e732b6a8..7260a299c6db 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c | |||
@@ -1423,9 +1423,11 @@ static int init_one(struct pci_dev *pdev, | |||
1423 | dev->ib_dev.get_dma_mr = mlx5_ib_get_dma_mr; | 1423 | dev->ib_dev.get_dma_mr = mlx5_ib_get_dma_mr; |
1424 | dev->ib_dev.reg_user_mr = mlx5_ib_reg_user_mr; | 1424 | dev->ib_dev.reg_user_mr = mlx5_ib_reg_user_mr; |
1425 | dev->ib_dev.dereg_mr = mlx5_ib_dereg_mr; | 1425 | dev->ib_dev.dereg_mr = mlx5_ib_dereg_mr; |
1426 | dev->ib_dev.destroy_mr = mlx5_ib_destroy_mr; | ||
1426 | dev->ib_dev.attach_mcast = mlx5_ib_mcg_attach; | 1427 | dev->ib_dev.attach_mcast = mlx5_ib_mcg_attach; |
1427 | dev->ib_dev.detach_mcast = mlx5_ib_mcg_detach; | 1428 | dev->ib_dev.detach_mcast = mlx5_ib_mcg_detach; |
1428 | dev->ib_dev.process_mad = mlx5_ib_process_mad; | 1429 | dev->ib_dev.process_mad = mlx5_ib_process_mad; |
1430 | dev->ib_dev.create_mr = mlx5_ib_create_mr; | ||
1429 | dev->ib_dev.alloc_fast_reg_mr = mlx5_ib_alloc_fast_reg_mr; | 1431 | dev->ib_dev.alloc_fast_reg_mr = mlx5_ib_alloc_fast_reg_mr; |
1430 | dev->ib_dev.alloc_fast_reg_page_list = mlx5_ib_alloc_fast_reg_page_list; | 1432 | dev->ib_dev.alloc_fast_reg_page_list = mlx5_ib_alloc_fast_reg_page_list; |
1431 | dev->ib_dev.free_fast_reg_page_list = mlx5_ib_free_fast_reg_page_list; | 1433 | dev->ib_dev.free_fast_reg_page_list = mlx5_ib_free_fast_reg_page_list; |
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index 389e31965773..79c4f14c4d3e 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h | |||
@@ -265,6 +265,7 @@ struct mlx5_ib_mr { | |||
265 | enum ib_wc_status status; | 265 | enum ib_wc_status status; |
266 | struct mlx5_ib_dev *dev; | 266 | struct mlx5_ib_dev *dev; |
267 | struct mlx5_create_mkey_mbox_out out; | 267 | struct mlx5_create_mkey_mbox_out out; |
268 | struct mlx5_core_sig_ctx *sig; | ||
268 | }; | 269 | }; |
269 | 270 | ||
270 | struct mlx5_ib_fast_reg_page_list { | 271 | struct mlx5_ib_fast_reg_page_list { |
@@ -495,6 +496,9 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, | |||
495 | u64 virt_addr, int access_flags, | 496 | u64 virt_addr, int access_flags, |
496 | struct ib_udata *udata); | 497 | struct ib_udata *udata); |
497 | int mlx5_ib_dereg_mr(struct ib_mr *ibmr); | 498 | int mlx5_ib_dereg_mr(struct ib_mr *ibmr); |
499 | int mlx5_ib_destroy_mr(struct ib_mr *ibmr); | ||
500 | struct ib_mr *mlx5_ib_create_mr(struct ib_pd *pd, | ||
501 | struct ib_mr_init_attr *mr_init_attr); | ||
498 | struct ib_mr *mlx5_ib_alloc_fast_reg_mr(struct ib_pd *pd, | 502 | struct ib_mr *mlx5_ib_alloc_fast_reg_mr(struct ib_pd *pd, |
499 | int max_page_list_len); | 503 | int max_page_list_len); |
500 | struct ib_fast_reg_page_list *mlx5_ib_alloc_fast_reg_page_list(struct ib_device *ibdev, | 504 | struct ib_fast_reg_page_list *mlx5_ib_alloc_fast_reg_page_list(struct ib_device *ibdev, |
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c index 7c95ca1f0c25..032445c47608 100644 --- a/drivers/infiniband/hw/mlx5/mr.c +++ b/drivers/infiniband/hw/mlx5/mr.c | |||
@@ -992,6 +992,117 @@ int mlx5_ib_dereg_mr(struct ib_mr *ibmr) | |||
992 | return 0; | 992 | return 0; |
993 | } | 993 | } |
994 | 994 | ||
995 | struct ib_mr *mlx5_ib_create_mr(struct ib_pd *pd, | ||
996 | struct ib_mr_init_attr *mr_init_attr) | ||
997 | { | ||
998 | struct mlx5_ib_dev *dev = to_mdev(pd->device); | ||
999 | struct mlx5_create_mkey_mbox_in *in; | ||
1000 | struct mlx5_ib_mr *mr; | ||
1001 | int access_mode, err; | ||
1002 | int ndescs = roundup(mr_init_attr->max_reg_descriptors, 4); | ||
1003 | |||
1004 | mr = kzalloc(sizeof(*mr), GFP_KERNEL); | ||
1005 | if (!mr) | ||
1006 | return ERR_PTR(-ENOMEM); | ||
1007 | |||
1008 | in = kzalloc(sizeof(*in), GFP_KERNEL); | ||
1009 | if (!in) { | ||
1010 | err = -ENOMEM; | ||
1011 | goto err_free; | ||
1012 | } | ||
1013 | |||
1014 | in->seg.status = 1 << 6; /* free */ | ||
1015 | in->seg.xlt_oct_size = cpu_to_be32(ndescs); | ||
1016 | in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); | ||
1017 | in->seg.flags_pd = cpu_to_be32(to_mpd(pd)->pdn); | ||
1018 | access_mode = MLX5_ACCESS_MODE_MTT; | ||
1019 | |||
1020 | if (mr_init_attr->flags & IB_MR_SIGNATURE_EN) { | ||
1021 | u32 psv_index[2]; | ||
1022 | |||
1023 | in->seg.flags_pd = cpu_to_be32(be32_to_cpu(in->seg.flags_pd) | | ||
1024 | MLX5_MKEY_BSF_EN); | ||
1025 | in->seg.bsfs_octo_size = cpu_to_be32(MLX5_MKEY_BSF_OCTO_SIZE); | ||
1026 | mr->sig = kzalloc(sizeof(*mr->sig), GFP_KERNEL); | ||
1027 | if (!mr->sig) { | ||
1028 | err = -ENOMEM; | ||
1029 | goto err_free_in; | ||
1030 | } | ||
1031 | |||
1032 | /* create mem & wire PSVs */ | ||
1033 | err = mlx5_core_create_psv(&dev->mdev, to_mpd(pd)->pdn, | ||
1034 | 2, psv_index); | ||
1035 | if (err) | ||
1036 | goto err_free_sig; | ||
1037 | |||
1038 | access_mode = MLX5_ACCESS_MODE_KLM; | ||
1039 | mr->sig->psv_memory.psv_idx = psv_index[0]; | ||
1040 | mr->sig->psv_wire.psv_idx = psv_index[1]; | ||
1041 | } | ||
1042 | |||
1043 | in->seg.flags = MLX5_PERM_UMR_EN | access_mode; | ||
1044 | err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in, sizeof(*in), | ||
1045 | NULL, NULL, NULL); | ||
1046 | if (err) | ||
1047 | goto err_destroy_psv; | ||
1048 | |||
1049 | mr->ibmr.lkey = mr->mmr.key; | ||
1050 | mr->ibmr.rkey = mr->mmr.key; | ||
1051 | mr->umem = NULL; | ||
1052 | kfree(in); | ||
1053 | |||
1054 | return &mr->ibmr; | ||
1055 | |||
1056 | err_destroy_psv: | ||
1057 | if (mr->sig) { | ||
1058 | if (mlx5_core_destroy_psv(&dev->mdev, | ||
1059 | mr->sig->psv_memory.psv_idx)) | ||
1060 | mlx5_ib_warn(dev, "failed to destroy mem psv %d\n", | ||
1061 | mr->sig->psv_memory.psv_idx); | ||
1062 | if (mlx5_core_destroy_psv(&dev->mdev, | ||
1063 | mr->sig->psv_wire.psv_idx)) | ||
1064 | mlx5_ib_warn(dev, "failed to destroy wire psv %d\n", | ||
1065 | mr->sig->psv_wire.psv_idx); | ||
1066 | } | ||
1067 | err_free_sig: | ||
1068 | kfree(mr->sig); | ||
1069 | err_free_in: | ||
1070 | kfree(in); | ||
1071 | err_free: | ||
1072 | kfree(mr); | ||
1073 | return ERR_PTR(err); | ||
1074 | } | ||
1075 | |||
1076 | int mlx5_ib_destroy_mr(struct ib_mr *ibmr) | ||
1077 | { | ||
1078 | struct mlx5_ib_dev *dev = to_mdev(ibmr->device); | ||
1079 | struct mlx5_ib_mr *mr = to_mmr(ibmr); | ||
1080 | int err; | ||
1081 | |||
1082 | if (mr->sig) { | ||
1083 | if (mlx5_core_destroy_psv(&dev->mdev, | ||
1084 | mr->sig->psv_memory.psv_idx)) | ||
1085 | mlx5_ib_warn(dev, "failed to destroy mem psv %d\n", | ||
1086 | mr->sig->psv_memory.psv_idx); | ||
1087 | if (mlx5_core_destroy_psv(&dev->mdev, | ||
1088 | mr->sig->psv_wire.psv_idx)) | ||
1089 | mlx5_ib_warn(dev, "failed to destroy wire psv %d\n", | ||
1090 | mr->sig->psv_wire.psv_idx); | ||
1091 | kfree(mr->sig); | ||
1092 | } | ||
1093 | |||
1094 | err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr); | ||
1095 | if (err) { | ||
1096 | mlx5_ib_warn(dev, "failed to destroy mkey 0x%x (%d)\n", | ||
1097 | mr->mmr.key, err); | ||
1098 | return err; | ||
1099 | } | ||
1100 | |||
1101 | kfree(mr); | ||
1102 | |||
1103 | return err; | ||
1104 | } | ||
1105 | |||
995 | struct ib_mr *mlx5_ib_alloc_fast_reg_mr(struct ib_pd *pd, | 1106 | struct ib_mr *mlx5_ib_alloc_fast_reg_mr(struct ib_pd *pd, |
996 | int max_page_list_len) | 1107 | int max_page_list_len) |
997 | { | 1108 | { |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mr.c b/drivers/net/ethernet/mellanox/mlx5/core/mr.c index 35e514dc7b7d..bb746bbe73c6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mr.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/mr.c | |||
@@ -144,3 +144,64 @@ int mlx5_core_dump_fill_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr, | |||
144 | return err; | 144 | return err; |
145 | } | 145 | } |
146 | EXPORT_SYMBOL(mlx5_core_dump_fill_mkey); | 146 | EXPORT_SYMBOL(mlx5_core_dump_fill_mkey); |
147 | |||
148 | int mlx5_core_create_psv(struct mlx5_core_dev *dev, u32 pdn, | ||
149 | int npsvs, u32 *sig_index) | ||
150 | { | ||
151 | struct mlx5_allocate_psv_in in; | ||
152 | struct mlx5_allocate_psv_out out; | ||
153 | int i, err; | ||
154 | |||
155 | if (npsvs > MLX5_MAX_PSVS) | ||
156 | return -EINVAL; | ||
157 | |||
158 | memset(&in, 0, sizeof(in)); | ||
159 | memset(&out, 0, sizeof(out)); | ||
160 | |||
161 | in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_CREATE_PSV); | ||
162 | in.npsv_pd = cpu_to_be32((npsvs << 28) | pdn); | ||
163 | err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); | ||
164 | if (err) { | ||
165 | mlx5_core_err(dev, "cmd exec failed %d\n", err); | ||
166 | return err; | ||
167 | } | ||
168 | |||
169 | if (out.hdr.status) { | ||
170 | mlx5_core_err(dev, "create_psv bad status %d\n", out.hdr.status); | ||
171 | return mlx5_cmd_status_to_err(&out.hdr); | ||
172 | } | ||
173 | |||
174 | for (i = 0; i < npsvs; i++) | ||
175 | sig_index[i] = be32_to_cpu(out.psv_idx[i]) & 0xffffff; | ||
176 | |||
177 | return err; | ||
178 | } | ||
179 | EXPORT_SYMBOL(mlx5_core_create_psv); | ||
180 | |||
181 | int mlx5_core_destroy_psv(struct mlx5_core_dev *dev, int psv_num) | ||
182 | { | ||
183 | struct mlx5_destroy_psv_in in; | ||
184 | struct mlx5_destroy_psv_out out; | ||
185 | int err; | ||
186 | |||
187 | memset(&in, 0, sizeof(in)); | ||
188 | memset(&out, 0, sizeof(out)); | ||
189 | |||
190 | in.psv_number = cpu_to_be32(psv_num); | ||
191 | in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_PSV); | ||
192 | err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); | ||
193 | if (err) { | ||
194 | mlx5_core_err(dev, "destroy_psv cmd exec failed %d\n", err); | ||
195 | goto out; | ||
196 | } | ||
197 | |||
198 | if (out.hdr.status) { | ||
199 | mlx5_core_err(dev, "destroy_psv bad status %d\n", out.hdr.status); | ||
200 | err = mlx5_cmd_status_to_err(&out.hdr); | ||
201 | goto out; | ||
202 | } | ||
203 | |||
204 | out: | ||
205 | return err; | ||
206 | } | ||
207 | EXPORT_SYMBOL(mlx5_core_destroy_psv); | ||
diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index 817a6fae6d2c..f714fc427765 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h | |||
@@ -48,6 +48,8 @@ enum { | |||
48 | MLX5_MAX_COMMANDS = 32, | 48 | MLX5_MAX_COMMANDS = 32, |
49 | MLX5_CMD_DATA_BLOCK_SIZE = 512, | 49 | MLX5_CMD_DATA_BLOCK_SIZE = 512, |
50 | MLX5_PCI_CMD_XPORT = 7, | 50 | MLX5_PCI_CMD_XPORT = 7, |
51 | MLX5_MKEY_BSF_OCTO_SIZE = 4, | ||
52 | MLX5_MAX_PSVS = 4, | ||
51 | }; | 53 | }; |
52 | 54 | ||
53 | enum { | 55 | enum { |
@@ -936,4 +938,27 @@ enum { | |||
936 | MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO = 1 << 0 | 938 | MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO = 1 << 0 |
937 | }; | 939 | }; |
938 | 940 | ||
941 | struct mlx5_allocate_psv_in { | ||
942 | struct mlx5_inbox_hdr hdr; | ||
943 | __be32 npsv_pd; | ||
944 | __be32 rsvd_psv0; | ||
945 | }; | ||
946 | |||
947 | struct mlx5_allocate_psv_out { | ||
948 | struct mlx5_outbox_hdr hdr; | ||
949 | u8 rsvd[8]; | ||
950 | __be32 psv_idx[4]; | ||
951 | }; | ||
952 | |||
953 | struct mlx5_destroy_psv_in { | ||
954 | struct mlx5_inbox_hdr hdr; | ||
955 | __be32 psv_number; | ||
956 | u8 rsvd[4]; | ||
957 | }; | ||
958 | |||
959 | struct mlx5_destroy_psv_out { | ||
960 | struct mlx5_outbox_hdr hdr; | ||
961 | u8 rsvd[8]; | ||
962 | }; | ||
963 | |||
939 | #endif /* MLX5_DEVICE_H */ | 964 | #endif /* MLX5_DEVICE_H */ |
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 130bc8d77fa5..e1cb657ccade 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h | |||
@@ -401,6 +401,22 @@ struct mlx5_eq { | |||
401 | struct mlx5_rsc_debug *dbg; | 401 | struct mlx5_rsc_debug *dbg; |
402 | }; | 402 | }; |
403 | 403 | ||
404 | struct mlx5_core_psv { | ||
405 | u32 psv_idx; | ||
406 | struct psv_layout { | ||
407 | u32 pd; | ||
408 | u16 syndrome; | ||
409 | u16 reserved; | ||
410 | u16 bg; | ||
411 | u16 app_tag; | ||
412 | u32 ref_tag; | ||
413 | } psv; | ||
414 | }; | ||
415 | |||
416 | struct mlx5_core_sig_ctx { | ||
417 | struct mlx5_core_psv psv_memory; | ||
418 | struct mlx5_core_psv psv_wire; | ||
419 | }; | ||
404 | 420 | ||
405 | struct mlx5_core_mr { | 421 | struct mlx5_core_mr { |
406 | u64 iova; | 422 | u64 iova; |
@@ -746,6 +762,9 @@ void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db); | |||
746 | const char *mlx5_command_str(int command); | 762 | const char *mlx5_command_str(int command); |
747 | int mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev); | 763 | int mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev); |
748 | void mlx5_cmdif_debugfs_cleanup(struct mlx5_core_dev *dev); | 764 | void mlx5_cmdif_debugfs_cleanup(struct mlx5_core_dev *dev); |
765 | int mlx5_core_create_psv(struct mlx5_core_dev *dev, u32 pdn, | ||
766 | int npsvs, u32 *sig_index); | ||
767 | int mlx5_core_destroy_psv(struct mlx5_core_dev *dev, int psv_num); | ||
749 | 768 | ||
750 | static inline u32 mlx5_mkey_to_idx(u32 mkey) | 769 | static inline u32 mlx5_mkey_to_idx(u32 mkey) |
751 | { | 770 | { |