@@ -266,6 +266,122 @@ static int UVERBS_HANDLER(UVERBS_METHOD_REG_DMABUF_MR)(
266266 return ret ;
267267}
268268
269+ static int UVERBS_HANDLER (UVERBS_METHOD_REG_MR )(
270+ struct uverbs_attr_bundle * attrs )
271+ {
272+ struct ib_uobject * uobj =
273+ uverbs_attr_get_uobject (attrs , UVERBS_ATTR_REG_MR_HANDLE );
274+ struct ib_pd * pd =
275+ uverbs_attr_get_obj (attrs , UVERBS_ATTR_REG_MR_PD_HANDLE );
276+ u32 valid_access_flags = IB_ACCESS_SUPPORTED ;
277+ u64 length , iova , fd_offset = 0 , addr = 0 ;
278+ struct ib_device * ib_dev = pd -> device ;
279+ bool has_fd_offset = false;
280+ bool has_addr = false;
281+ bool has_fd = false;
282+ u32 access_flags ;
283+ struct ib_mr * mr ;
284+ int fd ;
285+ int ret ;
286+
287+ ret = uverbs_copy_from (& iova , attrs , UVERBS_ATTR_REG_MR_IOVA );
288+ if (ret )
289+ return ret ;
290+
291+ ret = uverbs_copy_from (& length , attrs , UVERBS_ATTR_REG_MR_LENGTH );
292+ if (ret )
293+ return ret ;
294+
295+ if (uverbs_attr_is_valid (attrs , UVERBS_ATTR_REG_MR_ADDR )) {
296+ ret = uverbs_copy_from (& addr , attrs ,
297+ UVERBS_ATTR_REG_MR_ADDR );
298+ if (ret )
299+ return ret ;
300+ has_addr = true;
301+ }
302+
303+ if (uverbs_attr_is_valid (attrs , UVERBS_ATTR_REG_MR_FD_OFFSET )) {
304+ ret = uverbs_copy_from (& fd_offset , attrs ,
305+ UVERBS_ATTR_REG_MR_FD_OFFSET );
306+ if (ret )
307+ return ret ;
308+ has_fd_offset = true;
309+ }
310+
311+ if (uverbs_attr_is_valid (attrs , UVERBS_ATTR_REG_MR_FD )) {
312+ ret = uverbs_get_raw_fd (& fd , attrs ,
313+ UVERBS_ATTR_REG_MR_FD );
314+ if (ret )
315+ return ret ;
316+ has_fd = true;
317+ }
318+
319+ if (has_fd ) {
320+ if (!ib_dev -> ops .reg_user_mr_dmabuf )
321+ return - EOPNOTSUPP ;
322+
323+ /* FD requires offset and can't come with addr */
324+ if (!has_fd_offset || has_addr )
325+ return - EINVAL ;
326+
327+ if ((fd_offset & ~PAGE_MASK ) != (iova & ~PAGE_MASK ))
328+ return - EINVAL ;
329+
330+ valid_access_flags = IB_ACCESS_LOCAL_WRITE |
331+ IB_ACCESS_REMOTE_READ |
332+ IB_ACCESS_REMOTE_WRITE |
333+ IB_ACCESS_REMOTE_ATOMIC |
334+ IB_ACCESS_RELAXED_ORDERING ;
335+ } else {
336+ if (!has_addr || has_fd_offset )
337+ return - EINVAL ;
338+
339+ if ((addr & ~PAGE_MASK ) != (iova & ~PAGE_MASK ))
340+ return - EINVAL ;
341+ }
342+
343+ ret = uverbs_get_flags32 (& access_flags , attrs ,
344+ UVERBS_ATTR_REG_MR_ACCESS_FLAGS ,
345+ valid_access_flags );
346+ if (ret )
347+ return ret ;
348+
349+ ret = ib_check_mr_access (ib_dev , access_flags );
350+ if (ret )
351+ return ret ;
352+
353+ if (has_fd )
354+ mr = pd -> device -> ops .reg_user_mr_dmabuf (pd , fd_offset , length , iova ,
355+ fd , access_flags , attrs );
356+ else
357+ mr = pd -> device -> ops .reg_user_mr (pd , addr , length ,
358+ iova , access_flags , NULL );
359+
360+ if (IS_ERR (mr ))
361+ return PTR_ERR (mr );
362+
363+ mr -> device = pd -> device ;
364+ mr -> pd = pd ;
365+ mr -> type = IB_MR_TYPE_USER ;
366+ mr -> uobject = uobj ;
367+ atomic_inc (& pd -> usecnt );
368+ rdma_restrack_new (& mr -> res , RDMA_RESTRACK_MR );
369+ rdma_restrack_set_name (& mr -> res , NULL );
370+ rdma_restrack_add (& mr -> res );
371+ uobj -> object = mr ;
372+
373+ uverbs_finalize_uobj_create (attrs , UVERBS_ATTR_REG_MR_HANDLE );
374+
375+ ret = uverbs_copy_to (attrs , UVERBS_ATTR_REG_MR_RESP_LKEY ,
376+ & mr -> lkey , sizeof (mr -> lkey ));
377+ if (ret )
378+ return ret ;
379+
380+ ret = uverbs_copy_to (attrs , UVERBS_ATTR_REG_MR_RESP_RKEY ,
381+ & mr -> rkey , sizeof (mr -> rkey ));
382+ return ret ;
383+ }
384+
269385DECLARE_UVERBS_NAMED_METHOD (
270386 UVERBS_METHOD_ADVISE_MR ,
271387 UVERBS_ATTR_IDR (UVERBS_ATTR_ADVISE_MR_PD_HANDLE ,
@@ -362,6 +478,40 @@ DECLARE_UVERBS_NAMED_METHOD(
362478 UVERBS_ATTR_TYPE (u32 ),
363479 UA_MANDATORY ));
364480
481+ DECLARE_UVERBS_NAMED_METHOD (
482+ UVERBS_METHOD_REG_MR ,
483+ UVERBS_ATTR_IDR (UVERBS_ATTR_REG_MR_HANDLE ,
484+ UVERBS_OBJECT_MR ,
485+ UVERBS_ACCESS_NEW ,
486+ UA_MANDATORY ),
487+ UVERBS_ATTR_IDR (UVERBS_ATTR_REG_MR_PD_HANDLE ,
488+ UVERBS_OBJECT_PD ,
489+ UVERBS_ACCESS_READ ,
490+ UA_MANDATORY ),
491+ UVERBS_ATTR_PTR_IN (UVERBS_ATTR_REG_MR_IOVA ,
492+ UVERBS_ATTR_TYPE (u64 ),
493+ UA_MANDATORY ),
494+ UVERBS_ATTR_PTR_IN (UVERBS_ATTR_REG_MR_LENGTH ,
495+ UVERBS_ATTR_TYPE (u64 ),
496+ UA_MANDATORY ),
497+ UVERBS_ATTR_FLAGS_IN (UVERBS_ATTR_REG_MR_ACCESS_FLAGS ,
498+ enum ib_access_flags ,
499+ UA_MANDATORY ),
500+ UVERBS_ATTR_PTR_IN (UVERBS_ATTR_REG_MR_ADDR ,
501+ UVERBS_ATTR_TYPE (u64 ),
502+ UA_OPTIONAL ),
503+ UVERBS_ATTR_PTR_IN (UVERBS_ATTR_REG_MR_FD_OFFSET ,
504+ UVERBS_ATTR_TYPE (u64 ),
505+ UA_OPTIONAL ),
506+ UVERBS_ATTR_RAW_FD (UVERBS_ATTR_REG_MR_FD ,
507+ UA_OPTIONAL ),
508+ UVERBS_ATTR_PTR_OUT (UVERBS_ATTR_REG_MR_RESP_LKEY ,
509+ UVERBS_ATTR_TYPE (u32 ),
510+ UA_MANDATORY ),
511+ UVERBS_ATTR_PTR_OUT (UVERBS_ATTR_REG_MR_RESP_RKEY ,
512+ UVERBS_ATTR_TYPE (u32 ),
513+ UA_MANDATORY ));
514+
365515DECLARE_UVERBS_NAMED_METHOD_DESTROY (
366516 UVERBS_METHOD_MR_DESTROY ,
367517 UVERBS_ATTR_IDR (UVERBS_ATTR_DESTROY_MR_HANDLE ,
@@ -376,7 +526,8 @@ DECLARE_UVERBS_NAMED_OBJECT(
376526 & UVERBS_METHOD (UVERBS_METHOD_DM_MR_REG ),
377527 & UVERBS_METHOD (UVERBS_METHOD_MR_DESTROY ),
378528 & UVERBS_METHOD (UVERBS_METHOD_QUERY_MR ),
379- & UVERBS_METHOD (UVERBS_METHOD_REG_DMABUF_MR ));
529+ & UVERBS_METHOD (UVERBS_METHOD_REG_DMABUF_MR ),
530+ & UVERBS_METHOD (UVERBS_METHOD_REG_MR ));
380531
381532const struct uapi_definition uverbs_def_obj_mr [] = {
382533 UAPI_DEF_CHAIN_OBJ_TREE_NAMED (UVERBS_OBJECT_MR ,
0 commit comments