@@ -649,6 +649,71 @@ static int mlx5_ib_umem_get(struct mlx5_ib_dev *dev,
649
649
return err ;
650
650
}
651
651
652
+ static void destroy_user_rq (struct ib_pd * pd , struct mlx5_ib_rwq * rwq )
653
+ {
654
+ struct mlx5_ib_ucontext * context ;
655
+
656
+ context = to_mucontext (pd -> uobject -> context );
657
+ mlx5_ib_db_unmap_user (context , & rwq -> db );
658
+ if (rwq -> umem )
659
+ ib_umem_release (rwq -> umem );
660
+ }
661
+
662
+ static int create_user_rq (struct mlx5_ib_dev * dev , struct ib_pd * pd ,
663
+ struct mlx5_ib_rwq * rwq ,
664
+ struct mlx5_ib_create_wq * ucmd )
665
+ {
666
+ struct mlx5_ib_ucontext * context ;
667
+ int page_shift = 0 ;
668
+ int npages ;
669
+ u32 offset = 0 ;
670
+ int ncont = 0 ;
671
+ int err ;
672
+
673
+ if (!ucmd -> buf_addr )
674
+ return - EINVAL ;
675
+
676
+ context = to_mucontext (pd -> uobject -> context );
677
+ rwq -> umem = ib_umem_get (pd -> uobject -> context , ucmd -> buf_addr ,
678
+ rwq -> buf_size , 0 , 0 );
679
+ if (IS_ERR (rwq -> umem )) {
680
+ mlx5_ib_dbg (dev , "umem_get failed\n" );
681
+ err = PTR_ERR (rwq -> umem );
682
+ return err ;
683
+ }
684
+
685
+ mlx5_ib_cont_pages (rwq -> umem , ucmd -> buf_addr , & npages , & page_shift ,
686
+ & ncont , NULL );
687
+ err = mlx5_ib_get_buf_offset (ucmd -> buf_addr , page_shift ,
688
+ & rwq -> rq_page_offset );
689
+ if (err ) {
690
+ mlx5_ib_warn (dev , "bad offset\n" );
691
+ goto err_umem ;
692
+ }
693
+
694
+ rwq -> rq_num_pas = ncont ;
695
+ rwq -> page_shift = page_shift ;
696
+ rwq -> log_page_size = page_shift - MLX5_ADAPTER_PAGE_SHIFT ;
697
+ rwq -> wq_sig = !!(ucmd -> flags & MLX5_WQ_FLAG_SIGNATURE );
698
+
699
+ mlx5_ib_dbg (dev , "addr 0x%llx, size %zd, npages %d, page_shift %d, ncont %d, offset %d\n" ,
700
+ (unsigned long long )ucmd -> buf_addr , rwq -> buf_size ,
701
+ npages , page_shift , ncont , offset );
702
+
703
+ err = mlx5_ib_db_map_user (context , ucmd -> db_addr , & rwq -> db );
704
+ if (err ) {
705
+ mlx5_ib_dbg (dev , "map failed\n" );
706
+ goto err_umem ;
707
+ }
708
+
709
+ rwq -> create_type = MLX5_WQ_USER ;
710
+ return 0 ;
711
+
712
+ err_umem :
713
+ ib_umem_release (rwq -> umem );
714
+ return err ;
715
+ }
716
+
652
717
static int create_user_qp (struct mlx5_ib_dev * dev , struct ib_pd * pd ,
653
718
struct mlx5_ib_qp * qp , struct ib_udata * udata ,
654
719
struct ib_qp_init_attr * attr ,
@@ -4163,3 +4228,244 @@ int mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd)
4163
4228
4164
4229
return 0 ;
4165
4230
}
4231
+
4232
+ static int create_rq (struct mlx5_ib_rwq * rwq , struct ib_pd * pd ,
4233
+ struct ib_wq_init_attr * init_attr )
4234
+ {
4235
+ struct mlx5_ib_dev * dev ;
4236
+ __be64 * rq_pas0 ;
4237
+ void * in ;
4238
+ void * rqc ;
4239
+ void * wq ;
4240
+ int inlen ;
4241
+ int err ;
4242
+
4243
+ dev = to_mdev (pd -> device );
4244
+
4245
+ inlen = MLX5_ST_SZ_BYTES (create_rq_in ) + sizeof (u64 ) * rwq -> rq_num_pas ;
4246
+ in = mlx5_vzalloc (inlen );
4247
+ if (!in )
4248
+ return - ENOMEM ;
4249
+
4250
+ rqc = MLX5_ADDR_OF (create_rq_in , in , ctx );
4251
+ MLX5_SET (rqc , rqc , mem_rq_type ,
4252
+ MLX5_RQC_MEM_RQ_TYPE_MEMORY_RQ_INLINE );
4253
+ MLX5_SET (rqc , rqc , user_index , rwq -> user_index );
4254
+ MLX5_SET (rqc , rqc , cqn , to_mcq (init_attr -> cq )-> mcq .cqn );
4255
+ MLX5_SET (rqc , rqc , state , MLX5_RQC_STATE_RST );
4256
+ MLX5_SET (rqc , rqc , flush_in_error_en , 1 );
4257
+ wq = MLX5_ADDR_OF (rqc , rqc , wq );
4258
+ MLX5_SET (wq , wq , wq_type , MLX5_WQ_TYPE_CYCLIC );
4259
+ MLX5_SET (wq , wq , end_padding_mode , MLX5_WQ_END_PAD_MODE_ALIGN );
4260
+ MLX5_SET (wq , wq , log_wq_stride , rwq -> log_rq_stride );
4261
+ MLX5_SET (wq , wq , log_wq_sz , rwq -> log_rq_size );
4262
+ MLX5_SET (wq , wq , pd , to_mpd (pd )-> pdn );
4263
+ MLX5_SET (wq , wq , page_offset , rwq -> rq_page_offset );
4264
+ MLX5_SET (wq , wq , log_wq_pg_sz , rwq -> log_page_size );
4265
+ MLX5_SET (wq , wq , wq_signature , rwq -> wq_sig );
4266
+ MLX5_SET64 (wq , wq , dbr_addr , rwq -> db .dma );
4267
+ rq_pas0 = (__be64 * )MLX5_ADDR_OF (wq , wq , pas );
4268
+ mlx5_ib_populate_pas (dev , rwq -> umem , rwq -> page_shift , rq_pas0 , 0 );
4269
+ err = mlx5_core_create_rq (dev -> mdev , in , inlen , & rwq -> rqn );
4270
+ kvfree (in );
4271
+ return err ;
4272
+ }
4273
+
4274
+ static int set_user_rq_size (struct mlx5_ib_dev * dev ,
4275
+ struct ib_wq_init_attr * wq_init_attr ,
4276
+ struct mlx5_ib_create_wq * ucmd ,
4277
+ struct mlx5_ib_rwq * rwq )
4278
+ {
4279
+ /* Sanity check RQ size before proceeding */
4280
+ if (wq_init_attr -> max_wr > (1 << MLX5_CAP_GEN (dev -> mdev , log_max_wq_sz )))
4281
+ return - EINVAL ;
4282
+
4283
+ if (!ucmd -> rq_wqe_count )
4284
+ return - EINVAL ;
4285
+
4286
+ rwq -> wqe_count = ucmd -> rq_wqe_count ;
4287
+ rwq -> wqe_shift = ucmd -> rq_wqe_shift ;
4288
+ rwq -> buf_size = (rwq -> wqe_count << rwq -> wqe_shift );
4289
+ rwq -> log_rq_stride = rwq -> wqe_shift ;
4290
+ rwq -> log_rq_size = ilog2 (rwq -> wqe_count );
4291
+ return 0 ;
4292
+ }
4293
+
4294
+ static int prepare_user_rq (struct ib_pd * pd ,
4295
+ struct ib_wq_init_attr * init_attr ,
4296
+ struct ib_udata * udata ,
4297
+ struct mlx5_ib_rwq * rwq )
4298
+ {
4299
+ struct mlx5_ib_dev * dev = to_mdev (pd -> device );
4300
+ struct mlx5_ib_create_wq ucmd = {};
4301
+ int err ;
4302
+ size_t required_cmd_sz ;
4303
+
4304
+ required_cmd_sz = offsetof(typeof (ucmd ), reserved ) + sizeof (ucmd .reserved );
4305
+ if (udata -> inlen < required_cmd_sz ) {
4306
+ mlx5_ib_dbg (dev , "invalid inlen\n" );
4307
+ return - EINVAL ;
4308
+ }
4309
+
4310
+ if (udata -> inlen > sizeof (ucmd ) &&
4311
+ !ib_is_udata_cleared (udata , sizeof (ucmd ),
4312
+ udata -> inlen - sizeof (ucmd ))) {
4313
+ mlx5_ib_dbg (dev , "inlen is not supported\n" );
4314
+ return - EOPNOTSUPP ;
4315
+ }
4316
+
4317
+ if (ib_copy_from_udata (& ucmd , udata , min (sizeof (ucmd ), udata -> inlen ))) {
4318
+ mlx5_ib_dbg (dev , "copy failed\n" );
4319
+ return - EFAULT ;
4320
+ }
4321
+
4322
+ if (ucmd .comp_mask ) {
4323
+ mlx5_ib_dbg (dev , "invalid comp mask\n" );
4324
+ return - EOPNOTSUPP ;
4325
+ }
4326
+
4327
+ if (ucmd .reserved ) {
4328
+ mlx5_ib_dbg (dev , "invalid reserved\n" );
4329
+ return - EOPNOTSUPP ;
4330
+ }
4331
+
4332
+ err = set_user_rq_size (dev , init_attr , & ucmd , rwq );
4333
+ if (err ) {
4334
+ mlx5_ib_dbg (dev , "err %d\n" , err );
4335
+ return err ;
4336
+ }
4337
+
4338
+ err = create_user_rq (dev , pd , rwq , & ucmd );
4339
+ if (err ) {
4340
+ mlx5_ib_dbg (dev , "err %d\n" , err );
4341
+ if (err )
4342
+ return err ;
4343
+ }
4344
+
4345
+ rwq -> user_index = ucmd .user_index ;
4346
+ return 0 ;
4347
+ }
4348
+
4349
+ struct ib_wq * mlx5_ib_create_wq (struct ib_pd * pd ,
4350
+ struct ib_wq_init_attr * init_attr ,
4351
+ struct ib_udata * udata )
4352
+ {
4353
+ struct mlx5_ib_dev * dev ;
4354
+ struct mlx5_ib_rwq * rwq ;
4355
+ struct mlx5_ib_create_wq_resp resp = {};
4356
+ size_t min_resp_len ;
4357
+ int err ;
4358
+
4359
+ if (!udata )
4360
+ return ERR_PTR (- ENOSYS );
4361
+
4362
+ min_resp_len = offsetof(typeof (resp ), reserved ) + sizeof (resp .reserved );
4363
+ if (udata -> outlen && udata -> outlen < min_resp_len )
4364
+ return ERR_PTR (- EINVAL );
4365
+
4366
+ dev = to_mdev (pd -> device );
4367
+ switch (init_attr -> wq_type ) {
4368
+ case IB_WQT_RQ :
4369
+ rwq = kzalloc (sizeof (* rwq ), GFP_KERNEL );
4370
+ if (!rwq )
4371
+ return ERR_PTR (- ENOMEM );
4372
+ err = prepare_user_rq (pd , init_attr , udata , rwq );
4373
+ if (err )
4374
+ goto err ;
4375
+ err = create_rq (rwq , pd , init_attr );
4376
+ if (err )
4377
+ goto err_user_rq ;
4378
+ break ;
4379
+ default :
4380
+ mlx5_ib_dbg (dev , "unsupported wq type %d\n" ,
4381
+ init_attr -> wq_type );
4382
+ return ERR_PTR (- EINVAL );
4383
+ }
4384
+
4385
+ rwq -> ibwq .wq_num = rwq -> rqn ;
4386
+ rwq -> ibwq .state = IB_WQS_RESET ;
4387
+ if (udata -> outlen ) {
4388
+ resp .response_length = offsetof(typeof (resp ), response_length ) +
4389
+ sizeof (resp .response_length );
4390
+ err = ib_copy_to_udata (udata , & resp , resp .response_length );
4391
+ if (err )
4392
+ goto err_copy ;
4393
+ }
4394
+
4395
+ return & rwq -> ibwq ;
4396
+
4397
+ err_copy :
4398
+ mlx5_core_destroy_rq (dev -> mdev , rwq -> rqn );
4399
+ err_user_rq :
4400
+ destroy_user_rq (pd , rwq );
4401
+ err :
4402
+ kfree (rwq );
4403
+ return ERR_PTR (err );
4404
+ }
4405
+
4406
+ int mlx5_ib_destroy_wq (struct ib_wq * wq )
4407
+ {
4408
+ struct mlx5_ib_dev * dev = to_mdev (wq -> device );
4409
+ struct mlx5_ib_rwq * rwq = to_mrwq (wq );
4410
+
4411
+ mlx5_core_destroy_rq (dev -> mdev , rwq -> rqn );
4412
+ destroy_user_rq (wq -> pd , rwq );
4413
+ kfree (rwq );
4414
+
4415
+ return 0 ;
4416
+ }
4417
+
4418
+ int mlx5_ib_modify_wq (struct ib_wq * wq , struct ib_wq_attr * wq_attr ,
4419
+ u32 wq_attr_mask , struct ib_udata * udata )
4420
+ {
4421
+ struct mlx5_ib_dev * dev = to_mdev (wq -> device );
4422
+ struct mlx5_ib_rwq * rwq = to_mrwq (wq );
4423
+ struct mlx5_ib_modify_wq ucmd = {};
4424
+ size_t required_cmd_sz ;
4425
+ int curr_wq_state ;
4426
+ int wq_state ;
4427
+ int inlen ;
4428
+ int err ;
4429
+ void * rqc ;
4430
+ void * in ;
4431
+
4432
+ required_cmd_sz = offsetof(typeof (ucmd ), reserved ) + sizeof (ucmd .reserved );
4433
+ if (udata -> inlen < required_cmd_sz )
4434
+ return - EINVAL ;
4435
+
4436
+ if (udata -> inlen > sizeof (ucmd ) &&
4437
+ !ib_is_udata_cleared (udata , sizeof (ucmd ),
4438
+ udata -> inlen - sizeof (ucmd )))
4439
+ return - EOPNOTSUPP ;
4440
+
4441
+ if (ib_copy_from_udata (& ucmd , udata , min (sizeof (ucmd ), udata -> inlen )))
4442
+ return - EFAULT ;
4443
+
4444
+ if (ucmd .comp_mask || ucmd .reserved )
4445
+ return - EOPNOTSUPP ;
4446
+
4447
+ inlen = MLX5_ST_SZ_BYTES (modify_rq_in );
4448
+ in = mlx5_vzalloc (inlen );
4449
+ if (!in )
4450
+ return - ENOMEM ;
4451
+
4452
+ rqc = MLX5_ADDR_OF (modify_rq_in , in , ctx );
4453
+
4454
+ curr_wq_state = (wq_attr_mask & IB_WQ_CUR_STATE ) ?
4455
+ wq_attr -> curr_wq_state : wq -> state ;
4456
+ wq_state = (wq_attr_mask & IB_WQ_STATE ) ?
4457
+ wq_attr -> wq_state : curr_wq_state ;
4458
+ if (curr_wq_state == IB_WQS_ERR )
4459
+ curr_wq_state = MLX5_RQC_STATE_ERR ;
4460
+ if (wq_state == IB_WQS_ERR )
4461
+ wq_state = MLX5_RQC_STATE_ERR ;
4462
+ MLX5_SET (modify_rq_in , in , rq_state , curr_wq_state );
4463
+ MLX5_SET (rqc , rqc , state , wq_state );
4464
+
4465
+ err = mlx5_core_modify_rq (dev -> mdev , rwq -> rqn , in , inlen );
4466
+ kvfree (in );
4467
+ if (!err )
4468
+ rwq -> ibwq .state = (wq_state == MLX5_RQC_STATE_ERR ) ? IB_WQS_ERR : wq_state ;
4469
+
4470
+ return err ;
4471
+ }
0 commit comments