17
17
#define UVERBS_MODULE_NAME mlx5_ib
18
18
#include <rdma/uverbs_named_ioctl.h>
19
19
20
+ enum devx_obj_flags {
21
+ DEVX_OBJ_FLAGS_INDIRECT_MKEY = 1 << 0 ,
22
+ };
23
+
20
24
#define MLX5_MAX_DESTROY_INBOX_SIZE_DW MLX5_ST_SZ_DW(delete_fte_in)
21
25
struct devx_obj {
22
26
struct mlx5_core_dev * mdev ;
23
27
u64 obj_id ;
24
28
u32 dinlen ; /* destroy inbox length */
25
29
u32 dinbox [MLX5_MAX_DESTROY_INBOX_SIZE_DW ];
30
+ u32 flags ;
31
+ struct mlx5_ib_devx_mr devx_mr ;
26
32
};
27
33
28
34
struct devx_umem {
@@ -1011,6 +1017,36 @@ static void devx_obj_build_destroy_cmd(void *in, void *out, void *din,
1011
1017
}
1012
1018
}
1013
1019
1020
+ static int devx_handle_mkey_indirect (struct devx_obj * obj ,
1021
+ struct mlx5_ib_dev * dev ,
1022
+ void * in , void * out )
1023
+ {
1024
+ struct mlx5_mkey_table * table = & dev -> mdev -> priv .mkey_table ;
1025
+ struct mlx5_ib_devx_mr * devx_mr = & obj -> devx_mr ;
1026
+ unsigned long flags ;
1027
+ struct mlx5_core_mkey * mkey ;
1028
+ void * mkc ;
1029
+ u8 key ;
1030
+ int err ;
1031
+
1032
+ mkey = & devx_mr -> mmkey ;
1033
+ mkc = MLX5_ADDR_OF (create_mkey_in , in , memory_key_mkey_entry );
1034
+ key = MLX5_GET (mkc , mkc , mkey_7_0 );
1035
+ mkey -> key = mlx5_idx_to_mkey (
1036
+ MLX5_GET (create_mkey_out , out , mkey_index )) | key ;
1037
+ mkey -> type = MLX5_MKEY_INDIRECT_DEVX ;
1038
+ mkey -> iova = MLX5_GET64 (mkc , mkc , start_addr );
1039
+ mkey -> size = MLX5_GET64 (mkc , mkc , len );
1040
+ mkey -> pd = MLX5_GET (mkc , mkc , pd );
1041
+ devx_mr -> ndescs = MLX5_GET (mkc , mkc , translations_octword_size );
1042
+
1043
+ write_lock_irqsave (& table -> lock , flags );
1044
+ err = radix_tree_insert (& table -> tree , mlx5_base_mkey (mkey -> key ),
1045
+ mkey );
1046
+ write_unlock_irqrestore (& table -> lock , flags );
1047
+ return err ;
1048
+ }
1049
+
1014
1050
static int devx_handle_mkey_create (struct mlx5_ib_dev * dev ,
1015
1051
struct devx_obj * obj ,
1016
1052
void * in , int in_len )
@@ -1030,24 +1066,67 @@ static int devx_handle_mkey_create(struct mlx5_ib_dev *dev,
1030
1066
access_mode |= MLX5_GET (mkc , mkc , access_mode_4_2 ) << 2 ;
1031
1067
1032
1068
if (access_mode == MLX5_MKC_ACCESS_MODE_KLMS ||
1033
- access_mode == MLX5_MKC_ACCESS_MODE_KSM )
1069
+ access_mode == MLX5_MKC_ACCESS_MODE_KSM ) {
1070
+ if (IS_ENABLED (CONFIG_INFINIBAND_ON_DEMAND_PAGING ))
1071
+ obj -> flags |= DEVX_OBJ_FLAGS_INDIRECT_MKEY ;
1034
1072
return 0 ;
1073
+ }
1035
1074
1036
1075
MLX5_SET (create_mkey_in , in , mkey_umem_valid , 1 );
1037
1076
return 0 ;
1038
1077
}
1039
1078
1079
+ static void devx_free_indirect_mkey (struct rcu_head * rcu )
1080
+ {
1081
+ kfree (container_of (rcu , struct devx_obj , devx_mr .rcu ));
1082
+ }
1083
+
1084
+ /* This function to delete from the radix tree needs to be called before
1085
+ * destroying the underlying mkey. Otherwise a race might occur in case that
1086
+ * other thread will get the same mkey before this one will be deleted,
1087
+ * in that case it will fail via inserting to the tree its own data.
1088
+ *
1089
+ * Note:
1090
+ * An error in the destroy is not expected unless there is some other indirect
1091
+ * mkey which points to this one. In a kernel cleanup flow it will be just
1092
+ * destroyed in the iterative destruction call. In a user flow, in case
1093
+ * the application didn't close in the expected order it's its own problem,
1094
+ * the mkey won't be part of the tree, in both cases the kernel is safe.
1095
+ */
1096
+ static void devx_cleanup_mkey (struct devx_obj * obj )
1097
+ {
1098
+ struct mlx5_mkey_table * table = & obj -> mdev -> priv .mkey_table ;
1099
+ struct mlx5_core_mkey * del_mkey ;
1100
+ unsigned long flags ;
1101
+
1102
+ write_lock_irqsave (& table -> lock , flags );
1103
+ del_mkey = radix_tree_delete (& table -> tree ,
1104
+ mlx5_base_mkey (obj -> devx_mr .mmkey .key ));
1105
+ write_unlock_irqrestore (& table -> lock , flags );
1106
+ }
1107
+
1040
1108
static int devx_obj_cleanup (struct ib_uobject * uobject ,
1041
1109
enum rdma_remove_reason why )
1042
1110
{
1043
1111
u32 out [MLX5_ST_SZ_DW (general_obj_out_cmd_hdr )];
1044
1112
struct devx_obj * obj = uobject -> object ;
1045
1113
int ret ;
1046
1114
1115
+ if (obj -> flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY )
1116
+ devx_cleanup_mkey (obj );
1117
+
1047
1118
ret = mlx5_cmd_exec (obj -> mdev , obj -> dinbox , obj -> dinlen , out , sizeof (out ));
1048
1119
if (ib_is_destroy_retryable (ret , why , uobject ))
1049
1120
return ret ;
1050
1121
1122
+ if (obj -> flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY ) {
1123
+ struct mlx5_ib_dev * dev = to_mdev (uobject -> context -> device );
1124
+
1125
+ call_srcu (& dev -> mr_srcu , & obj -> devx_mr .rcu ,
1126
+ devx_free_indirect_mkey );
1127
+ return ret ;
1128
+ }
1129
+
1051
1130
kfree (obj );
1052
1131
return ret ;
1053
1132
}
@@ -1108,6 +1187,12 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
1108
1187
& obj_id );
1109
1188
WARN_ON (obj -> dinlen > MLX5_MAX_DESTROY_INBOX_SIZE_DW * sizeof (u32 ));
1110
1189
1190
+ if (obj -> flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY ) {
1191
+ err = devx_handle_mkey_indirect (obj , dev , cmd_in , cmd_out );
1192
+ if (err )
1193
+ goto obj_destroy ;
1194
+ }
1195
+
1111
1196
err = uverbs_copy_to (attrs , MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT , cmd_out , cmd_out_len );
1112
1197
if (err )
1113
1198
goto obj_destroy ;
@@ -1116,6 +1201,8 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
1116
1201
return 0 ;
1117
1202
1118
1203
obj_destroy :
1204
+ if (obj -> flags & DEVX_OBJ_FLAGS_INDIRECT_MKEY )
1205
+ devx_cleanup_mkey (obj );
1119
1206
mlx5_cmd_exec (obj -> mdev , obj -> dinbox , obj -> dinlen , out , sizeof (out ));
1120
1207
obj_free :
1121
1208
kfree (obj );
0 commit comments