2018-06-17 12:59:57 +03:00
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/*
* Copyright ( c ) 2018 , Mellanox Technologies inc . All rights reserved .
*/
# include <rdma/ib_user_verbs.h>
# include <rdma/ib_verbs.h>
# include <rdma/uverbs_types.h>
# include <rdma/uverbs_ioctl.h>
# include <rdma/mlx5_user_ioctl_cmds.h>
# include <rdma/ib_umem.h>
2018-11-26 09:28:35 +03:00
# include <rdma/uverbs_std_types.h>
2018-06-17 12:59:57 +03:00
# include <linux/mlx5/driver.h>
# include <linux/mlx5/fs.h>
# include "mlx5_ib.h"
2018-06-17 13:00:00 +03:00
# define UVERBS_MODULE_NAME mlx5_ib
# include <rdma/uverbs_named_ioctl.h>
2018-06-17 13:00:01 +03:00
# define MLX5_MAX_DESTROY_INBOX_SIZE_DW MLX5_ST_SZ_DW(delete_fte_in)
struct devx_obj {
struct mlx5_core_dev * mdev ;
2018-10-07 12:06:34 +03:00
u64 obj_id ;
2018-06-17 13:00:01 +03:00
u32 dinlen ; /* destroy inbox length */
u32 dinbox [ MLX5_MAX_DESTROY_INBOX_SIZE_DW ] ;
} ;
2018-06-17 13:00:04 +03:00
struct devx_umem {
struct mlx5_core_dev * mdev ;
struct ib_umem * umem ;
u32 page_offset ;
int page_shift ;
int ncont ;
u32 dinlen ;
u32 dinbox [ MLX5_ST_SZ_DW ( general_obj_in_cmd_hdr ) ] ;
} ;
struct devx_umem_reg_cmd {
void * in ;
u32 inlen ;
u32 out [ MLX5_ST_SZ_DW ( general_obj_out_cmd_hdr ) ] ;
} ;
2018-11-25 21:51:15 +03:00
static struct mlx5_ib_ucontext *
devx_ufile2uctx ( const struct uverbs_attr_bundle * attrs )
2018-06-17 13:00:00 +03:00
{
2018-11-25 21:51:15 +03:00
return to_mucontext ( ib_uverbs_get_ucontext ( attrs ) ) ;
2018-06-17 13:00:00 +03:00
}
2018-11-26 09:28:36 +03:00
int mlx5_ib_devx_create ( struct mlx5_ib_dev * dev , bool is_user )
2018-06-17 12:59:57 +03:00
{
u32 in [ MLX5_ST_SZ_DW ( create_uctx_in ) ] = { 0 } ;
u32 out [ MLX5_ST_SZ_DW ( general_obj_out_cmd_hdr ) ] = { 0 } ;
2018-12-19 17:28:15 +03:00
void * uctx ;
2018-06-17 12:59:57 +03:00
int err ;
2018-09-20 21:45:19 +03:00
u16 uid ;
2018-11-26 09:28:36 +03:00
u32 cap = 0 ;
2018-06-17 12:59:57 +03:00
2018-12-19 17:28:15 +03:00
/* 0 means not supported */
if ( ! MLX5_CAP_GEN ( dev - > mdev , log_max_uctx ) )
2018-06-17 12:59:57 +03:00
return - EINVAL ;
2018-12-19 17:28:15 +03:00
uctx = MLX5_ADDR_OF ( create_uctx_in , in , uctx ) ;
2018-11-26 09:28:36 +03:00
if ( is_user & & capable ( CAP_NET_RAW ) & &
( MLX5_CAP_GEN ( dev - > mdev , uctx_cap ) & MLX5_UCTX_CAP_RAW_TX ) )
cap | = MLX5_UCTX_CAP_RAW_TX ;
2018-12-19 17:28:15 +03:00
MLX5_SET ( create_uctx_in , in , opcode , MLX5_CMD_OP_CREATE_UCTX ) ;
2018-11-26 09:28:36 +03:00
MLX5_SET ( uctx , uctx , cap , cap ) ;
2018-06-17 12:59:57 +03:00
err = mlx5_cmd_exec ( dev - > mdev , in , sizeof ( in ) , out , sizeof ( out ) ) ;
if ( err )
return err ;
2018-09-20 21:45:19 +03:00
uid = MLX5_GET ( general_obj_out_cmd_hdr , out , obj_id ) ;
return uid ;
2018-06-17 12:59:57 +03:00
}
2018-09-20 21:45:19 +03:00
void mlx5_ib_devx_destroy ( struct mlx5_ib_dev * dev , u16 uid )
2018-06-17 12:59:57 +03:00
{
2018-12-19 17:28:15 +03:00
u32 in [ MLX5_ST_SZ_DW ( destroy_uctx_in ) ] = { 0 } ;
2018-06-17 12:59:57 +03:00
u32 out [ MLX5_ST_SZ_DW ( general_obj_out_cmd_hdr ) ] = { 0 } ;
2018-12-19 17:28:15 +03:00
MLX5_SET ( destroy_uctx_in , in , opcode , MLX5_CMD_OP_DESTROY_UCTX ) ;
MLX5_SET ( destroy_uctx_in , in , uid , uid ) ;
2018-06-17 12:59:57 +03:00
mlx5_cmd_exec ( dev - > mdev , in , sizeof ( in ) , out , sizeof ( out ) ) ;
}
2018-06-17 13:00:00 +03:00
2018-07-23 15:25:09 +03:00
bool mlx5_ib_devx_is_flow_dest ( void * obj , int * dest_id , int * dest_type )
{
struct devx_obj * devx_obj = obj ;
u16 opcode = MLX5_GET ( general_obj_in_cmd_hdr , devx_obj - > dinbox , opcode ) ;
switch ( opcode ) {
case MLX5_CMD_OP_DESTROY_TIR :
* dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR ;
* dest_id = MLX5_GET ( general_obj_in_cmd_hdr , devx_obj - > dinbox ,
obj_id ) ;
return true ;
case MLX5_CMD_OP_DESTROY_FLOW_TABLE :
* dest_type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE ;
* dest_id = MLX5_GET ( destroy_flow_table_in , devx_obj - > dinbox ,
table_id ) ;
return true ;
default :
return false ;
}
}
2018-11-20 21:31:08 +03:00
bool mlx5_ib_devx_is_flow_counter ( void * obj , u32 * counter_id )
{
struct devx_obj * devx_obj = obj ;
u16 opcode = MLX5_GET ( general_obj_in_cmd_hdr , devx_obj - > dinbox , opcode ) ;
if ( opcode = = MLX5_CMD_OP_DEALLOC_FLOW_COUNTER ) {
* counter_id = MLX5_GET ( dealloc_flow_counter_in ,
devx_obj - > dinbox ,
flow_counter_id ) ;
return true ;
}
return false ;
}
2018-10-07 12:06:34 +03:00
/*
* As the obj_id in the firmware is not globally unique the object type
* must be considered upon checking for a valid object id .
* For that the opcode of the creator command is encoded as part of the obj_id .
*/
static u64 get_enc_obj_id ( u16 opcode , u32 obj_id )
{
return ( ( u64 ) opcode < < 32 ) | obj_id ;
}
2018-11-26 09:28:35 +03:00
static u64 devx_get_obj_id ( const void * in )
2018-06-17 13:00:02 +03:00
{
u16 opcode = MLX5_GET ( general_obj_in_cmd_hdr , in , opcode ) ;
2018-10-07 12:06:34 +03:00
u64 obj_id ;
2018-06-17 13:00:02 +03:00
switch ( opcode ) {
case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT :
case MLX5_CMD_OP_QUERY_GENERAL_OBJECT :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_GENERAL_OBJECT ,
MLX5_GET ( general_obj_in_cmd_hdr , in ,
obj_id ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_MKEY :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_MKEY ,
MLX5_GET ( query_mkey_in , in ,
mkey_index ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_CQ :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_CQ ,
MLX5_GET ( query_cq_in , in , cqn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_MODIFY_CQ :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_CQ ,
MLX5_GET ( modify_cq_in , in , cqn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_SQ :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_SQ ,
MLX5_GET ( query_sq_in , in , sqn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_MODIFY_SQ :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_SQ ,
MLX5_GET ( modify_sq_in , in , sqn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_RQ :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_RQ ,
MLX5_GET ( query_rq_in , in , rqn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_MODIFY_RQ :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_RQ ,
MLX5_GET ( modify_rq_in , in , rqn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_RMP :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_RMP ,
MLX5_GET ( query_rmp_in , in , rmpn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_MODIFY_RMP :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_RMP ,
MLX5_GET ( modify_rmp_in , in , rmpn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_RQT :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_RQT ,
MLX5_GET ( query_rqt_in , in , rqtn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_MODIFY_RQT :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_RQT ,
MLX5_GET ( modify_rqt_in , in , rqtn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_TIR :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_TIR ,
MLX5_GET ( query_tir_in , in , tirn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_MODIFY_TIR :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_TIR ,
MLX5_GET ( modify_tir_in , in , tirn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_TIS :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_TIS ,
MLX5_GET ( query_tis_in , in , tisn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_MODIFY_TIS :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_TIS ,
MLX5_GET ( modify_tis_in , in , tisn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_FLOW_TABLE :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_FLOW_TABLE ,
MLX5_GET ( query_flow_table_in , in ,
table_id ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_MODIFY_FLOW_TABLE :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_FLOW_TABLE ,
MLX5_GET ( modify_flow_table_in , in ,
table_id ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_FLOW_GROUP :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_FLOW_GROUP ,
MLX5_GET ( query_flow_group_in , in ,
group_id ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY ,
MLX5_GET ( query_fte_in , in ,
flow_index ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY ,
MLX5_GET ( set_fte_in , in , flow_index ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_Q_COUNTER :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_ALLOC_Q_COUNTER ,
MLX5_GET ( query_q_counter_in , in ,
counter_set_id ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_FLOW_COUNTER :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_ALLOC_FLOW_COUNTER ,
MLX5_GET ( query_flow_counter_in , in ,
flow_counter_id ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT ,
MLX5_GET ( general_obj_in_cmd_hdr , in ,
obj_id ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT ,
MLX5_GET ( query_scheduling_element_in ,
in , scheduling_element_id ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT ,
MLX5_GET ( modify_scheduling_element_in ,
in , scheduling_element_id ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT ,
MLX5_GET ( add_vxlan_udp_dport_in , in ,
vxlan_udp_port ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_SET_L2_TABLE_ENTRY ,
MLX5_GET ( query_l2_table_entry_in , in ,
table_index ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_SET_L2_TABLE_ENTRY :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_SET_L2_TABLE_ENTRY ,
MLX5_GET ( set_l2_table_entry_in , in ,
table_index ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_QP :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_QP ,
MLX5_GET ( query_qp_in , in , qpn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_RST2INIT_QP :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_QP ,
MLX5_GET ( rst2init_qp_in , in , qpn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_INIT2RTR_QP :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_QP ,
MLX5_GET ( init2rtr_qp_in , in , qpn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_RTR2RTS_QP :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_QP ,
MLX5_GET ( rtr2rts_qp_in , in , qpn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_RTS2RTS_QP :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_QP ,
MLX5_GET ( rts2rts_qp_in , in , qpn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_SQERR2RTS_QP :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_QP ,
MLX5_GET ( sqerr2rts_qp_in , in , qpn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_2ERR_QP :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_QP ,
MLX5_GET ( qp_2err_in , in , qpn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_2RST_QP :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_QP ,
MLX5_GET ( qp_2rst_in , in , qpn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_DCT :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_DCT ,
MLX5_GET ( query_dct_in , in , dctn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_XRQ :
2018-11-26 09:28:37 +03:00
case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY :
case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_XRQ ,
MLX5_GET ( query_xrq_in , in , xrqn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_XRC_SRQ :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_XRC_SRQ ,
MLX5_GET ( query_xrc_srq_in , in ,
xrc_srqn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_ARM_XRC_SRQ :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_XRC_SRQ ,
MLX5_GET ( arm_xrc_srq_in , in , xrc_srqn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_QUERY_SRQ :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_SRQ ,
MLX5_GET ( query_srq_in , in , srqn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_ARM_RQ :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_RQ ,
MLX5_GET ( arm_rq_in , in , srq_number ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_DRAIN_DCT :
case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_DCT ,
MLX5_GET ( drain_dct_in , in , dctn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
case MLX5_CMD_OP_ARM_XRQ :
2018-11-26 09:28:37 +03:00
case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY :
2018-10-07 12:06:34 +03:00
obj_id = get_enc_obj_id ( MLX5_CMD_OP_CREATE_XRQ ,
MLX5_GET ( arm_xrq_in , in , xrqn ) ) ;
2018-06-17 13:00:02 +03:00
break ;
2018-11-26 09:28:37 +03:00
case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT :
obj_id = get_enc_obj_id
( MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT ,
MLX5_GET ( query_packet_reformat_context_in ,
in , packet_reformat_id ) ) ;
break ;
2018-06-17 13:00:02 +03:00
default :
2018-11-26 09:28:35 +03:00
obj_id = 0 ;
}
return obj_id ;
}
static bool devx_is_valid_obj_id ( struct ib_uobject * uobj , const void * in )
{
u64 obj_id = devx_get_obj_id ( in ) ;
if ( ! obj_id )
2018-06-17 13:00:02 +03:00
return false ;
2018-11-26 09:28:35 +03:00
switch ( uobj_get_object_id ( uobj ) ) {
case UVERBS_OBJECT_CQ :
return get_enc_obj_id ( MLX5_CMD_OP_CREATE_CQ ,
to_mcq ( uobj - > object ) - > mcq . cqn ) = =
obj_id ;
case UVERBS_OBJECT_SRQ :
{
struct mlx5_core_srq * srq = & ( to_msrq ( uobj - > object ) - > msrq ) ;
struct mlx5_ib_dev * dev = to_mdev ( uobj - > context - > device ) ;
u16 opcode ;
switch ( srq - > common . res ) {
case MLX5_RES_XSRQ :
opcode = MLX5_CMD_OP_CREATE_XRC_SRQ ;
break ;
case MLX5_RES_XRQ :
opcode = MLX5_CMD_OP_CREATE_XRQ ;
break ;
default :
if ( ! dev - > mdev - > issi )
opcode = MLX5_CMD_OP_CREATE_SRQ ;
else
opcode = MLX5_CMD_OP_CREATE_RMP ;
}
return get_enc_obj_id ( opcode ,
to_msrq ( uobj - > object ) - > msrq . srqn ) = =
obj_id ;
2018-06-17 13:00:02 +03:00
}
2018-11-26 09:28:35 +03:00
case UVERBS_OBJECT_QP :
{
struct mlx5_ib_qp * qp = to_mqp ( uobj - > object ) ;
enum ib_qp_type qp_type = qp - > ibqp . qp_type ;
if ( qp_type = = IB_QPT_RAW_PACKET | |
( qp - > flags & MLX5_IB_QP_UNDERLAY ) ) {
struct mlx5_ib_raw_packet_qp * raw_packet_qp =
& qp - > raw_packet_qp ;
struct mlx5_ib_rq * rq = & raw_packet_qp - > rq ;
struct mlx5_ib_sq * sq = & raw_packet_qp - > sq ;
return ( get_enc_obj_id ( MLX5_CMD_OP_CREATE_RQ ,
rq - > base . mqp . qpn ) = = obj_id | |
get_enc_obj_id ( MLX5_CMD_OP_CREATE_SQ ,
sq - > base . mqp . qpn ) = = obj_id | |
get_enc_obj_id ( MLX5_CMD_OP_CREATE_TIR ,
rq - > tirn ) = = obj_id | |
get_enc_obj_id ( MLX5_CMD_OP_CREATE_TIS ,
sq - > tisn ) = = obj_id ) ;
}
if ( qp_type = = MLX5_IB_QPT_DCT )
return get_enc_obj_id ( MLX5_CMD_OP_CREATE_DCT ,
qp - > dct . mdct . mqp . qpn ) = = obj_id ;
return get_enc_obj_id ( MLX5_CMD_OP_CREATE_QP ,
qp - > ibqp . qp_num ) = = obj_id ;
}
2018-06-17 13:00:02 +03:00
2018-11-26 09:28:35 +03:00
case UVERBS_OBJECT_WQ :
return get_enc_obj_id ( MLX5_CMD_OP_CREATE_RQ ,
to_mrwq ( uobj - > object ) - > core_qp . qpn ) = =
obj_id ;
case UVERBS_OBJECT_RWQ_IND_TBL :
return get_enc_obj_id ( MLX5_CMD_OP_CREATE_RQT ,
to_mrwq_ind_table ( uobj - > object ) - > rqtn ) = =
obj_id ;
case MLX5_IB_OBJECT_DEVX_OBJ :
return ( ( struct devx_obj * ) uobj - > object ) - > obj_id = = obj_id ;
default :
return false ;
}
2018-06-17 13:00:02 +03:00
}
2018-09-20 21:39:33 +03:00
static void devx_set_umem_valid ( const void * in )
{
u16 opcode = MLX5_GET ( general_obj_in_cmd_hdr , in , opcode ) ;
switch ( opcode ) {
case MLX5_CMD_OP_CREATE_MKEY :
MLX5_SET ( create_mkey_in , in , mkey_umem_valid , 1 ) ;
break ;
case MLX5_CMD_OP_CREATE_CQ :
{
void * cqc ;
MLX5_SET ( create_cq_in , in , cq_umem_valid , 1 ) ;
cqc = MLX5_ADDR_OF ( create_cq_in , in , cq_context ) ;
MLX5_SET ( cqc , cqc , dbr_umem_valid , 1 ) ;
break ;
}
case MLX5_CMD_OP_CREATE_QP :
{
void * qpc ;
qpc = MLX5_ADDR_OF ( create_qp_in , in , qpc ) ;
MLX5_SET ( qpc , qpc , dbr_umem_valid , 1 ) ;
MLX5_SET ( create_qp_in , in , wq_umem_valid , 1 ) ;
break ;
}
case MLX5_CMD_OP_CREATE_RQ :
{
void * rqc , * wq ;
rqc = MLX5_ADDR_OF ( create_rq_in , in , ctx ) ;
wq = MLX5_ADDR_OF ( rqc , rqc , wq ) ;
MLX5_SET ( wq , wq , dbr_umem_valid , 1 ) ;
MLX5_SET ( wq , wq , wq_umem_valid , 1 ) ;
break ;
}
case MLX5_CMD_OP_CREATE_SQ :
{
void * sqc , * wq ;
sqc = MLX5_ADDR_OF ( create_sq_in , in , ctx ) ;
wq = MLX5_ADDR_OF ( sqc , sqc , wq ) ;
MLX5_SET ( wq , wq , dbr_umem_valid , 1 ) ;
MLX5_SET ( wq , wq , wq_umem_valid , 1 ) ;
break ;
}
case MLX5_CMD_OP_MODIFY_CQ :
MLX5_SET ( modify_cq_in , in , cq_umem_valid , 1 ) ;
break ;
case MLX5_CMD_OP_CREATE_RMP :
{
void * rmpc , * wq ;
rmpc = MLX5_ADDR_OF ( create_rmp_in , in , ctx ) ;
wq = MLX5_ADDR_OF ( rmpc , rmpc , wq ) ;
MLX5_SET ( wq , wq , dbr_umem_valid , 1 ) ;
MLX5_SET ( wq , wq , wq_umem_valid , 1 ) ;
break ;
}
case MLX5_CMD_OP_CREATE_XRQ :
{
void * xrqc , * wq ;
xrqc = MLX5_ADDR_OF ( create_xrq_in , in , xrq_context ) ;
wq = MLX5_ADDR_OF ( xrqc , xrqc , wq ) ;
MLX5_SET ( wq , wq , dbr_umem_valid , 1 ) ;
MLX5_SET ( wq , wq , wq_umem_valid , 1 ) ;
break ;
}
case MLX5_CMD_OP_CREATE_XRC_SRQ :
{
void * xrc_srqc ;
MLX5_SET ( create_xrc_srq_in , in , xrc_srq_umem_valid , 1 ) ;
xrc_srqc = MLX5_ADDR_OF ( create_xrc_srq_in , in ,
xrc_srq_context_entry ) ;
MLX5_SET ( xrc_srqc , xrc_srqc , dbr_umem_valid , 1 ) ;
break ;
}
default :
return ;
}
}
2018-10-07 12:06:34 +03:00
static bool devx_is_obj_create_cmd ( const void * in , u16 * opcode )
2018-06-17 13:00:01 +03:00
{
2018-10-07 12:06:34 +03:00
* opcode = MLX5_GET ( general_obj_in_cmd_hdr , in , opcode ) ;
2018-06-17 13:00:01 +03:00
2018-10-07 12:06:34 +03:00
switch ( * opcode ) {
2018-06-17 13:00:01 +03:00
case MLX5_CMD_OP_CREATE_GENERAL_OBJECT :
case MLX5_CMD_OP_CREATE_MKEY :
case MLX5_CMD_OP_CREATE_CQ :
case MLX5_CMD_OP_ALLOC_PD :
case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN :
case MLX5_CMD_OP_CREATE_RMP :
case MLX5_CMD_OP_CREATE_SQ :
case MLX5_CMD_OP_CREATE_RQ :
case MLX5_CMD_OP_CREATE_RQT :
case MLX5_CMD_OP_CREATE_TIR :
case MLX5_CMD_OP_CREATE_TIS :
case MLX5_CMD_OP_ALLOC_Q_COUNTER :
case MLX5_CMD_OP_CREATE_FLOW_TABLE :
case MLX5_CMD_OP_CREATE_FLOW_GROUP :
case MLX5_CMD_OP_ALLOC_FLOW_COUNTER :
2018-08-28 14:18:46 +03:00
case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT :
2018-06-17 13:00:01 +03:00
case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT :
case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT :
case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT :
case MLX5_CMD_OP_SET_L2_TABLE_ENTRY :
case MLX5_CMD_OP_CREATE_QP :
case MLX5_CMD_OP_CREATE_SRQ :
case MLX5_CMD_OP_CREATE_XRC_SRQ :
case MLX5_CMD_OP_CREATE_DCT :
case MLX5_CMD_OP_CREATE_XRQ :
case MLX5_CMD_OP_ATTACH_TO_MCG :
case MLX5_CMD_OP_ALLOC_XRCD :
return true ;
case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY :
{
u16 op_mod = MLX5_GET ( set_fte_in , in , op_mod ) ;
if ( op_mod = = 0 )
return true ;
return false ;
}
default :
return false ;
}
}
2018-06-17 13:00:02 +03:00
static bool devx_is_obj_modify_cmd ( const void * in )
{
u16 opcode = MLX5_GET ( general_obj_in_cmd_hdr , in , opcode ) ;
switch ( opcode ) {
case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT :
case MLX5_CMD_OP_MODIFY_CQ :
case MLX5_CMD_OP_MODIFY_RMP :
case MLX5_CMD_OP_MODIFY_SQ :
case MLX5_CMD_OP_MODIFY_RQ :
case MLX5_CMD_OP_MODIFY_RQT :
case MLX5_CMD_OP_MODIFY_TIR :
case MLX5_CMD_OP_MODIFY_TIS :
case MLX5_CMD_OP_MODIFY_FLOW_TABLE :
case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT :
case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT :
case MLX5_CMD_OP_SET_L2_TABLE_ENTRY :
case MLX5_CMD_OP_RST2INIT_QP :
case MLX5_CMD_OP_INIT2RTR_QP :
case MLX5_CMD_OP_RTR2RTS_QP :
case MLX5_CMD_OP_RTS2RTS_QP :
case MLX5_CMD_OP_SQERR2RTS_QP :
case MLX5_CMD_OP_2ERR_QP :
case MLX5_CMD_OP_2RST_QP :
case MLX5_CMD_OP_ARM_XRC_SRQ :
case MLX5_CMD_OP_ARM_RQ :
case MLX5_CMD_OP_DRAIN_DCT :
case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION :
case MLX5_CMD_OP_ARM_XRQ :
2018-11-26 09:28:37 +03:00
case MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY :
2018-06-17 13:00:02 +03:00
return true ;
case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY :
{
u16 op_mod = MLX5_GET ( set_fte_in , in , op_mod ) ;
if ( op_mod = = 1 )
return true ;
return false ;
}
default :
return false ;
}
}
static bool devx_is_obj_query_cmd ( const void * in )
{
u16 opcode = MLX5_GET ( general_obj_in_cmd_hdr , in , opcode ) ;
switch ( opcode ) {
case MLX5_CMD_OP_QUERY_GENERAL_OBJECT :
case MLX5_CMD_OP_QUERY_MKEY :
case MLX5_CMD_OP_QUERY_CQ :
case MLX5_CMD_OP_QUERY_RMP :
case MLX5_CMD_OP_QUERY_SQ :
case MLX5_CMD_OP_QUERY_RQ :
case MLX5_CMD_OP_QUERY_RQT :
case MLX5_CMD_OP_QUERY_TIR :
case MLX5_CMD_OP_QUERY_TIS :
case MLX5_CMD_OP_QUERY_Q_COUNTER :
case MLX5_CMD_OP_QUERY_FLOW_TABLE :
case MLX5_CMD_OP_QUERY_FLOW_GROUP :
case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY :
case MLX5_CMD_OP_QUERY_FLOW_COUNTER :
case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT :
case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT :
case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY :
case MLX5_CMD_OP_QUERY_QP :
case MLX5_CMD_OP_QUERY_SRQ :
case MLX5_CMD_OP_QUERY_XRC_SRQ :
case MLX5_CMD_OP_QUERY_DCT :
case MLX5_CMD_OP_QUERY_XRQ :
2018-11-26 09:28:37 +03:00
case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY :
case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS :
case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT :
2018-06-17 13:00:02 +03:00
return true ;
default :
return false ;
}
}
2018-09-20 21:45:20 +03:00
static bool devx_is_whitelist_cmd ( void * in )
{
u16 opcode = MLX5_GET ( general_obj_in_cmd_hdr , in , opcode ) ;
switch ( opcode ) {
case MLX5_CMD_OP_QUERY_HCA_CAP :
case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT :
return true ;
default :
return false ;
}
}
static int devx_get_uid ( struct mlx5_ib_ucontext * c , void * cmd_in )
{
if ( devx_is_whitelist_cmd ( cmd_in ) ) {
struct mlx5_ib_dev * dev ;
if ( c - > devx_uid )
return c - > devx_uid ;
dev = to_mdev ( c - > ibucontext . device ) ;
if ( dev - > devx_whitelist_uid )
return dev - > devx_whitelist_uid ;
return - EOPNOTSUPP ;
}
if ( ! c - > devx_uid )
return - EINVAL ;
return c - > devx_uid ;
}
2018-06-17 13:00:02 +03:00
static bool devx_is_general_cmd ( void * in )
2018-06-17 13:00:00 +03:00
{
u16 opcode = MLX5_GET ( general_obj_in_cmd_hdr , in , opcode ) ;
2018-11-26 09:28:37 +03:00
if ( opcode > = MLX5_CMD_OP_GENERAL_START & &
opcode < MLX5_CMD_OP_GENERAL_END )
return true ;
2018-06-17 13:00:00 +03:00
switch ( opcode ) {
case MLX5_CMD_OP_QUERY_HCA_CAP :
2018-09-20 21:45:20 +03:00
case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT :
2018-06-17 13:00:00 +03:00
case MLX5_CMD_OP_QUERY_VPORT_STATE :
case MLX5_CMD_OP_QUERY_ADAPTER :
case MLX5_CMD_OP_QUERY_ISSI :
case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT :
case MLX5_CMD_OP_QUERY_ROCE_ADDRESS :
case MLX5_CMD_OP_QUERY_VNIC_ENV :
case MLX5_CMD_OP_QUERY_VPORT_COUNTER :
case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG :
case MLX5_CMD_OP_NOP :
case MLX5_CMD_OP_QUERY_CONG_STATUS :
case MLX5_CMD_OP_QUERY_CONG_PARAMS :
case MLX5_CMD_OP_QUERY_CONG_STATISTICS :
return true ;
default :
return false ;
}
}
2018-07-26 06:40:18 +03:00
static int UVERBS_HANDLER ( MLX5_IB_METHOD_DEVX_QUERY_EQN ) (
2018-11-25 21:51:15 +03:00
struct uverbs_attr_bundle * attrs )
2018-06-17 13:00:05 +03:00
{
2018-07-26 06:40:18 +03:00
struct mlx5_ib_ucontext * c ;
struct mlx5_ib_dev * dev ;
2018-06-17 13:00:05 +03:00
int user_vector ;
int dev_eqn ;
unsigned int irqn ;
int err ;
if ( uverbs_copy_from ( & user_vector , attrs ,
MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC ) )
return - EFAULT ;
2018-11-25 21:51:15 +03:00
c = devx_ufile2uctx ( attrs ) ;
2018-07-26 06:40:18 +03:00
if ( IS_ERR ( c ) )
return PTR_ERR ( c ) ;
dev = to_mdev ( c - > ibucontext . device ) ;
2018-06-17 13:00:05 +03:00
err = mlx5_vector2eqn ( dev - > mdev , user_vector , & dev_eqn , & irqn ) ;
if ( err < 0 )
return err ;
if ( uverbs_copy_to ( attrs , MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN ,
& dev_eqn , sizeof ( dev_eqn ) ) )
return - EFAULT ;
return 0 ;
}
2018-06-17 13:00:03 +03:00
/*
* Security note :
* The hardware protection mechanism works like this : Each device object that
* is subject to UAR doorbells ( QP / SQ / CQ ) gets a UAR ID ( called uar_page in
* the device specification manual ) upon its creation . Then upon doorbell ,
* hardware fetches the object context for which the doorbell was rang , and
* validates that the UAR through which the DB was rang matches the UAR ID
* of the object .
* If no match the doorbell is silently ignored by the hardware . Of course ,
* the user cannot ring a doorbell on a UAR that was not mapped to it .
* Now in devx , as the devx kernel does not manipulate the QP / SQ / CQ command
* mailboxes ( except tagging them with UID ) , we expose to the user its UAR
* ID , so it can embed it in these objects in the expected specification
* format . So the only thing the user can do is hurt itself by creating a
* QP / SQ / CQ with a UAR ID other than his , and then in this case other users
* may ring a doorbell on its objects .
* The consequence of that will be that another user can schedule a QP / SQ
* of the buggy user for execution ( just insert it to the hardware schedule
* queue or arm its CQ for event generation ) , no further harm is expected .
*/
2018-07-26 06:40:18 +03:00
static int UVERBS_HANDLER ( MLX5_IB_METHOD_DEVX_QUERY_UAR ) (
2018-11-25 21:51:15 +03:00
struct uverbs_attr_bundle * attrs )
2018-06-17 13:00:03 +03:00
{
2018-07-10 22:43:06 +03:00
struct mlx5_ib_ucontext * c ;
struct mlx5_ib_dev * dev ;
2018-06-17 13:00:03 +03:00
u32 user_idx ;
s32 dev_idx ;
2018-11-25 21:51:15 +03:00
c = devx_ufile2uctx ( attrs ) ;
2018-07-10 22:43:06 +03:00
if ( IS_ERR ( c ) )
return PTR_ERR ( c ) ;
dev = to_mdev ( c - > ibucontext . device ) ;
2018-06-17 13:00:03 +03:00
if ( uverbs_copy_from ( & user_idx , attrs ,
MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX ) )
return - EFAULT ;
2018-07-10 22:43:06 +03:00
dev_idx = bfregn_to_uar_index ( dev , & c - > bfregi , user_idx , true ) ;
2018-06-17 13:00:03 +03:00
if ( dev_idx < 0 )
return dev_idx ;
if ( uverbs_copy_to ( attrs , MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX ,
& dev_idx , sizeof ( dev_idx ) ) )
return - EFAULT ;
return 0 ;
}
2018-07-26 06:40:18 +03:00
static int UVERBS_HANDLER ( MLX5_IB_METHOD_DEVX_OTHER ) (
2018-11-25 21:51:15 +03:00
struct uverbs_attr_bundle * attrs )
2018-06-17 13:00:00 +03:00
{
2018-07-10 22:43:06 +03:00
struct mlx5_ib_ucontext * c ;
struct mlx5_ib_dev * dev ;
2018-06-17 13:00:01 +03:00
void * cmd_in = uverbs_attr_get_alloced_ptr (
attrs , MLX5_IB_ATTR_DEVX_OTHER_CMD_IN ) ;
2018-06-17 13:00:00 +03:00
int cmd_out_len = uverbs_attr_get_len ( attrs ,
MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT ) ;
void * cmd_out ;
int err ;
2018-09-20 21:45:20 +03:00
int uid ;
2018-06-17 13:00:00 +03:00
2018-11-25 21:51:15 +03:00
c = devx_ufile2uctx ( attrs ) ;
2018-07-10 22:43:06 +03:00
if ( IS_ERR ( c ) )
return PTR_ERR ( c ) ;
dev = to_mdev ( c - > ibucontext . device ) ;
2018-09-20 21:45:20 +03:00
uid = devx_get_uid ( c , cmd_in ) ;
if ( uid < 0 )
return uid ;
2018-06-17 13:00:00 +03:00
/* Only white list of some general HCA commands are allowed for this method. */
if ( ! devx_is_general_cmd ( cmd_in ) )
return - EINVAL ;
2018-08-10 05:14:41 +03:00
cmd_out = uverbs_zalloc ( attrs , cmd_out_len ) ;
if ( IS_ERR ( cmd_out ) )
return PTR_ERR ( cmd_out ) ;
2018-06-17 13:00:00 +03:00
2018-09-20 21:45:20 +03:00
MLX5_SET ( general_obj_in_cmd_hdr , cmd_in , uid , uid ) ;
2018-06-17 13:00:00 +03:00
err = mlx5_cmd_exec ( dev - > mdev , cmd_in ,
uverbs_attr_get_len ( attrs , MLX5_IB_ATTR_DEVX_OTHER_CMD_IN ) ,
cmd_out , cmd_out_len ) ;
if ( err )
2018-08-10 05:14:41 +03:00
return err ;
2018-06-17 13:00:00 +03:00
2018-08-10 05:14:41 +03:00
return uverbs_copy_to ( attrs , MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT , cmd_out ,
cmd_out_len ) ;
2018-06-17 13:00:00 +03:00
}
2018-06-17 13:00:01 +03:00
static void devx_obj_build_destroy_cmd ( void * in , void * out , void * din ,
u32 * dinlen ,
u32 * obj_id )
{
u16 obj_type = MLX5_GET ( general_obj_in_cmd_hdr , in , obj_type ) ;
u16 uid = MLX5_GET ( general_obj_in_cmd_hdr , in , uid ) ;
* obj_id = MLX5_GET ( general_obj_out_cmd_hdr , out , obj_id ) ;
* dinlen = MLX5_ST_SZ_BYTES ( general_obj_in_cmd_hdr ) ;
MLX5_SET ( general_obj_in_cmd_hdr , din , obj_id , * obj_id ) ;
MLX5_SET ( general_obj_in_cmd_hdr , din , uid , uid ) ;
switch ( MLX5_GET ( general_obj_in_cmd_hdr , in , opcode ) ) {
case MLX5_CMD_OP_CREATE_GENERAL_OBJECT :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DESTROY_GENERAL_OBJECT ) ;
MLX5_SET ( general_obj_in_cmd_hdr , din , obj_type , obj_type ) ;
break ;
2018-12-19 17:28:15 +03:00
case MLX5_CMD_OP_CREATE_UMEM :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode ,
MLX5_CMD_OP_DESTROY_UMEM ) ;
break ;
2018-06-17 13:00:01 +03:00
case MLX5_CMD_OP_CREATE_MKEY :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DESTROY_MKEY ) ;
break ;
case MLX5_CMD_OP_CREATE_CQ :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DESTROY_CQ ) ;
break ;
case MLX5_CMD_OP_ALLOC_PD :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DEALLOC_PD ) ;
break ;
case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode ,
MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN ) ;
break ;
case MLX5_CMD_OP_CREATE_RMP :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DESTROY_RMP ) ;
break ;
case MLX5_CMD_OP_CREATE_SQ :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DESTROY_SQ ) ;
break ;
case MLX5_CMD_OP_CREATE_RQ :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DESTROY_RQ ) ;
break ;
case MLX5_CMD_OP_CREATE_RQT :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DESTROY_RQT ) ;
break ;
case MLX5_CMD_OP_CREATE_TIR :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DESTROY_TIR ) ;
break ;
case MLX5_CMD_OP_CREATE_TIS :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DESTROY_TIS ) ;
break ;
case MLX5_CMD_OP_ALLOC_Q_COUNTER :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode ,
MLX5_CMD_OP_DEALLOC_Q_COUNTER ) ;
break ;
case MLX5_CMD_OP_CREATE_FLOW_TABLE :
* dinlen = MLX5_ST_SZ_BYTES ( destroy_flow_table_in ) ;
* obj_id = MLX5_GET ( create_flow_table_out , out , table_id ) ;
MLX5_SET ( destroy_flow_table_in , din , other_vport ,
MLX5_GET ( create_flow_table_in , in , other_vport ) ) ;
MLX5_SET ( destroy_flow_table_in , din , vport_number ,
MLX5_GET ( create_flow_table_in , in , vport_number ) ) ;
MLX5_SET ( destroy_flow_table_in , din , table_type ,
MLX5_GET ( create_flow_table_in , in , table_type ) ) ;
MLX5_SET ( destroy_flow_table_in , din , table_id , * obj_id ) ;
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode ,
MLX5_CMD_OP_DESTROY_FLOW_TABLE ) ;
break ;
case MLX5_CMD_OP_CREATE_FLOW_GROUP :
* dinlen = MLX5_ST_SZ_BYTES ( destroy_flow_group_in ) ;
* obj_id = MLX5_GET ( create_flow_group_out , out , group_id ) ;
MLX5_SET ( destroy_flow_group_in , din , other_vport ,
MLX5_GET ( create_flow_group_in , in , other_vport ) ) ;
MLX5_SET ( destroy_flow_group_in , din , vport_number ,
MLX5_GET ( create_flow_group_in , in , vport_number ) ) ;
MLX5_SET ( destroy_flow_group_in , din , table_type ,
MLX5_GET ( create_flow_group_in , in , table_type ) ) ;
MLX5_SET ( destroy_flow_group_in , din , table_id ,
MLX5_GET ( create_flow_group_in , in , table_id ) ) ;
MLX5_SET ( destroy_flow_group_in , din , group_id , * obj_id ) ;
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode ,
MLX5_CMD_OP_DESTROY_FLOW_GROUP ) ;
break ;
case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY :
* dinlen = MLX5_ST_SZ_BYTES ( delete_fte_in ) ;
* obj_id = MLX5_GET ( set_fte_in , in , flow_index ) ;
MLX5_SET ( delete_fte_in , din , other_vport ,
MLX5_GET ( set_fte_in , in , other_vport ) ) ;
MLX5_SET ( delete_fte_in , din , vport_number ,
MLX5_GET ( set_fte_in , in , vport_number ) ) ;
MLX5_SET ( delete_fte_in , din , table_type ,
MLX5_GET ( set_fte_in , in , table_type ) ) ;
MLX5_SET ( delete_fte_in , din , table_id ,
MLX5_GET ( set_fte_in , in , table_id ) ) ;
MLX5_SET ( delete_fte_in , din , flow_index , * obj_id ) ;
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode ,
MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY ) ;
break ;
case MLX5_CMD_OP_ALLOC_FLOW_COUNTER :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode ,
MLX5_CMD_OP_DEALLOC_FLOW_COUNTER ) ;
break ;
2018-08-28 14:18:46 +03:00
case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT :
2018-06-17 13:00:01 +03:00
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode ,
2018-08-28 14:18:46 +03:00
MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT ) ;
2018-06-17 13:00:01 +03:00
break ;
case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode ,
MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT ) ;
break ;
case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT :
* dinlen = MLX5_ST_SZ_BYTES ( destroy_scheduling_element_in ) ;
* obj_id = MLX5_GET ( create_scheduling_element_out , out ,
scheduling_element_id ) ;
MLX5_SET ( destroy_scheduling_element_in , din ,
scheduling_hierarchy ,
MLX5_GET ( create_scheduling_element_in , in ,
scheduling_hierarchy ) ) ;
MLX5_SET ( destroy_scheduling_element_in , din ,
scheduling_element_id , * obj_id ) ;
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode ,
MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT ) ;
break ;
case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT :
* dinlen = MLX5_ST_SZ_BYTES ( delete_vxlan_udp_dport_in ) ;
* obj_id = MLX5_GET ( add_vxlan_udp_dport_in , in , vxlan_udp_port ) ;
MLX5_SET ( delete_vxlan_udp_dport_in , din , vxlan_udp_port , * obj_id ) ;
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode ,
MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT ) ;
break ;
case MLX5_CMD_OP_SET_L2_TABLE_ENTRY :
* dinlen = MLX5_ST_SZ_BYTES ( delete_l2_table_entry_in ) ;
* obj_id = MLX5_GET ( set_l2_table_entry_in , in , table_index ) ;
MLX5_SET ( delete_l2_table_entry_in , din , table_index , * obj_id ) ;
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode ,
MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY ) ;
break ;
case MLX5_CMD_OP_CREATE_QP :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DESTROY_QP ) ;
break ;
case MLX5_CMD_OP_CREATE_SRQ :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DESTROY_SRQ ) ;
break ;
case MLX5_CMD_OP_CREATE_XRC_SRQ :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode ,
MLX5_CMD_OP_DESTROY_XRC_SRQ ) ;
break ;
case MLX5_CMD_OP_CREATE_DCT :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DESTROY_DCT ) ;
break ;
case MLX5_CMD_OP_CREATE_XRQ :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DESTROY_XRQ ) ;
break ;
case MLX5_CMD_OP_ATTACH_TO_MCG :
* dinlen = MLX5_ST_SZ_BYTES ( detach_from_mcg_in ) ;
MLX5_SET ( detach_from_mcg_in , din , qpn ,
MLX5_GET ( attach_to_mcg_in , in , qpn ) ) ;
memcpy ( MLX5_ADDR_OF ( detach_from_mcg_in , din , multicast_gid ) ,
MLX5_ADDR_OF ( attach_to_mcg_in , in , multicast_gid ) ,
MLX5_FLD_SZ_BYTES ( attach_to_mcg_in , multicast_gid ) ) ;
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DETACH_FROM_MCG ) ;
break ;
case MLX5_CMD_OP_ALLOC_XRCD :
MLX5_SET ( general_obj_in_cmd_hdr , din , opcode , MLX5_CMD_OP_DEALLOC_XRCD ) ;
break ;
default :
/* The entry must match to one of the devx_is_obj_create_cmd */
WARN_ON ( true ) ;
break ;
}
}
static int devx_obj_cleanup ( struct ib_uobject * uobject ,
enum rdma_remove_reason why )
{
u32 out [ MLX5_ST_SZ_DW ( general_obj_out_cmd_hdr ) ] ;
struct devx_obj * obj = uobject - > object ;
int ret ;
ret = mlx5_cmd_exec ( obj - > mdev , obj - > dinbox , obj - > dinlen , out , sizeof ( out ) ) ;
2018-06-20 17:11:39 +03:00
if ( ib_is_destroy_retryable ( ret , why , uobject ) )
2018-06-17 13:00:01 +03:00
return ret ;
kfree ( obj ) ;
return ret ;
}
2018-07-26 06:40:18 +03:00
static int UVERBS_HANDLER ( MLX5_IB_METHOD_DEVX_OBJ_CREATE ) (
2018-11-25 21:51:15 +03:00
struct uverbs_attr_bundle * attrs )
2018-06-17 13:00:01 +03:00
{
void * cmd_in = uverbs_attr_get_alloced_ptr ( attrs , MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN ) ;
int cmd_out_len = uverbs_attr_get_len ( attrs ,
MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT ) ;
void * cmd_out ;
2018-07-11 05:55:22 +03:00
struct ib_uobject * uobj = uverbs_attr_get_uobject (
attrs , MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE ) ;
struct mlx5_ib_ucontext * c = to_mucontext ( uobj - > context ) ;
struct mlx5_ib_dev * dev = to_mdev ( c - > ibucontext . device ) ;
2018-09-25 12:11:12 +03:00
u32 out [ MLX5_ST_SZ_DW ( general_obj_out_cmd_hdr ) ] ;
2018-06-17 13:00:01 +03:00
struct devx_obj * obj ;
int err ;
2018-09-20 21:45:20 +03:00
int uid ;
2018-10-07 12:06:34 +03:00
u32 obj_id ;
u16 opcode ;
2018-06-17 13:00:01 +03:00
2018-09-20 21:45:20 +03:00
uid = devx_get_uid ( c , cmd_in ) ;
if ( uid < 0 )
return uid ;
2018-06-17 13:00:01 +03:00
2018-10-07 12:06:34 +03:00
if ( ! devx_is_obj_create_cmd ( cmd_in , & opcode ) )
2018-06-17 13:00:01 +03:00
return - EINVAL ;
2018-08-10 05:14:41 +03:00
cmd_out = uverbs_zalloc ( attrs , cmd_out_len ) ;
if ( IS_ERR ( cmd_out ) )
return PTR_ERR ( cmd_out ) ;
2018-06-17 13:00:01 +03:00
obj = kzalloc ( sizeof ( struct devx_obj ) , GFP_KERNEL ) ;
if ( ! obj )
return - ENOMEM ;
2018-09-20 21:45:20 +03:00
MLX5_SET ( general_obj_in_cmd_hdr , cmd_in , uid , uid ) ;
2018-09-20 21:39:33 +03:00
devx_set_umem_valid ( cmd_in ) ;
2018-06-17 13:00:01 +03:00
err = mlx5_cmd_exec ( dev - > mdev , cmd_in ,
uverbs_attr_get_len ( attrs , MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN ) ,
cmd_out , cmd_out_len ) ;
if ( err )
2018-08-10 05:14:41 +03:00
goto obj_free ;
2018-06-17 13:00:01 +03:00
uobj - > object = obj ;
obj - > mdev = dev - > mdev ;
2018-10-07 12:06:34 +03:00
devx_obj_build_destroy_cmd ( cmd_in , cmd_out , obj - > dinbox , & obj - > dinlen ,
& obj_id ) ;
2018-06-17 13:00:01 +03:00
WARN_ON ( obj - > dinlen > MLX5_MAX_DESTROY_INBOX_SIZE_DW * sizeof ( u32 ) ) ;
err = uverbs_copy_to ( attrs , MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT , cmd_out , cmd_out_len ) ;
if ( err )
2018-09-25 12:11:12 +03:00
goto obj_destroy ;
2018-06-17 13:00:01 +03:00
2018-10-07 12:06:34 +03:00
obj - > obj_id = get_enc_obj_id ( opcode , obj_id ) ;
2018-06-17 13:00:01 +03:00
return 0 ;
2018-09-25 12:11:12 +03:00
obj_destroy :
mlx5_cmd_exec ( obj - > mdev , obj - > dinbox , obj - > dinlen , out , sizeof ( out ) ) ;
2018-06-17 13:00:01 +03:00
obj_free :
kfree ( obj ) ;
return err ;
}
2018-07-26 06:40:18 +03:00
static int UVERBS_HANDLER ( MLX5_IB_METHOD_DEVX_OBJ_MODIFY ) (
2018-11-25 21:51:15 +03:00
struct uverbs_attr_bundle * attrs )
2018-06-17 13:00:02 +03:00
{
void * cmd_in = uverbs_attr_get_alloced_ptr ( attrs , MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN ) ;
int cmd_out_len = uverbs_attr_get_len ( attrs ,
MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT ) ;
struct ib_uobject * uobj = uverbs_attr_get_uobject ( attrs ,
MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE ) ;
2018-07-11 05:55:22 +03:00
struct mlx5_ib_ucontext * c = to_mucontext ( uobj - > context ) ;
2018-11-26 09:28:35 +03:00
struct mlx5_ib_dev * mdev = to_mdev ( uobj - > context - > device ) ;
2018-06-17 13:00:02 +03:00
void * cmd_out ;
int err ;
2018-09-20 21:45:20 +03:00
int uid ;
2018-06-17 13:00:02 +03:00
2018-09-20 21:45:20 +03:00
uid = devx_get_uid ( c , cmd_in ) ;
if ( uid < 0 )
return uid ;
2018-06-17 13:00:02 +03:00
if ( ! devx_is_obj_modify_cmd ( cmd_in ) )
return - EINVAL ;
2018-11-26 09:28:35 +03:00
if ( ! devx_is_valid_obj_id ( uobj , cmd_in ) )
2018-06-17 13:00:02 +03:00
return - EINVAL ;
2018-08-10 05:14:41 +03:00
cmd_out = uverbs_zalloc ( attrs , cmd_out_len ) ;
if ( IS_ERR ( cmd_out ) )
return PTR_ERR ( cmd_out ) ;
2018-06-17 13:00:02 +03:00
2018-09-20 21:45:20 +03:00
MLX5_SET ( general_obj_in_cmd_hdr , cmd_in , uid , uid ) ;
2018-09-20 21:39:33 +03:00
devx_set_umem_valid ( cmd_in ) ;
2018-11-26 09:28:35 +03:00
err = mlx5_cmd_exec ( mdev - > mdev , cmd_in ,
2018-06-17 13:00:02 +03:00
uverbs_attr_get_len ( attrs , MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN ) ,
cmd_out , cmd_out_len ) ;
if ( err )
2018-08-10 05:14:41 +03:00
return err ;
2018-06-17 13:00:02 +03:00
2018-08-10 05:14:41 +03:00
return uverbs_copy_to ( attrs , MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT ,
cmd_out , cmd_out_len ) ;
2018-06-17 13:00:02 +03:00
}
2018-07-26 06:40:18 +03:00
static int UVERBS_HANDLER ( MLX5_IB_METHOD_DEVX_OBJ_QUERY ) (
2018-11-25 21:51:15 +03:00
struct uverbs_attr_bundle * attrs )
2018-06-17 13:00:02 +03:00
{
void * cmd_in = uverbs_attr_get_alloced_ptr ( attrs , MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN ) ;
int cmd_out_len = uverbs_attr_get_len ( attrs ,
MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT ) ;
struct ib_uobject * uobj = uverbs_attr_get_uobject ( attrs ,
MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE ) ;
2018-07-11 05:55:22 +03:00
struct mlx5_ib_ucontext * c = to_mucontext ( uobj - > context ) ;
2018-06-17 13:00:02 +03:00
void * cmd_out ;
int err ;
2018-09-20 21:45:20 +03:00
int uid ;
2018-11-26 09:28:35 +03:00
struct mlx5_ib_dev * mdev = to_mdev ( uobj - > context - > device ) ;
2018-06-17 13:00:02 +03:00
2018-09-20 21:45:20 +03:00
uid = devx_get_uid ( c , cmd_in ) ;
if ( uid < 0 )
return uid ;
2018-06-17 13:00:02 +03:00
if ( ! devx_is_obj_query_cmd ( cmd_in ) )
return - EINVAL ;
2018-11-26 09:28:35 +03:00
if ( ! devx_is_valid_obj_id ( uobj , cmd_in ) )
2018-06-17 13:00:02 +03:00
return - EINVAL ;
2018-08-10 05:14:41 +03:00
cmd_out = uverbs_zalloc ( attrs , cmd_out_len ) ;
if ( IS_ERR ( cmd_out ) )
return PTR_ERR ( cmd_out ) ;
2018-06-17 13:00:02 +03:00
2018-09-20 21:45:20 +03:00
MLX5_SET ( general_obj_in_cmd_hdr , cmd_in , uid , uid ) ;
2018-11-26 09:28:35 +03:00
err = mlx5_cmd_exec ( mdev - > mdev , cmd_in ,
2018-06-17 13:00:02 +03:00
uverbs_attr_get_len ( attrs , MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN ) ,
cmd_out , cmd_out_len ) ;
if ( err )
2018-08-10 05:14:41 +03:00
return err ;
2018-06-17 13:00:02 +03:00
2018-08-10 05:14:41 +03:00
return uverbs_copy_to ( attrs , MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT ,
cmd_out , cmd_out_len ) ;
2018-06-17 13:00:02 +03:00
}
2018-06-17 13:00:04 +03:00
static int devx_umem_get ( struct mlx5_ib_dev * dev , struct ib_ucontext * ucontext ,
struct uverbs_attr_bundle * attrs ,
struct devx_umem * obj )
{
u64 addr ;
size_t size ;
2018-07-27 01:37:14 +03:00
u32 access ;
2018-06-17 13:00:04 +03:00
int npages ;
int err ;
u32 page_mask ;
if ( uverbs_copy_from ( & addr , attrs , MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR ) | |
2018-07-27 01:37:14 +03:00
uverbs_copy_from ( & size , attrs , MLX5_IB_ATTR_DEVX_UMEM_REG_LEN ) )
2018-06-17 13:00:04 +03:00
return - EFAULT ;
2018-07-27 01:37:14 +03:00
err = uverbs_get_flags32 ( & access , attrs ,
MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS ,
2018-12-05 16:50:21 +03:00
IB_ACCESS_LOCAL_WRITE |
IB_ACCESS_REMOTE_WRITE |
IB_ACCESS_REMOTE_READ ) ;
2018-07-27 01:37:14 +03:00
if ( err )
return err ;
2018-06-17 13:00:04 +03:00
err = ib_check_mr_access ( access ) ;
if ( err )
return err ;
2019-01-09 12:15:16 +03:00
obj - > umem = ib_umem_get ( & attrs - > driver_udata , addr , size , access , 0 ) ;
2018-06-17 13:00:04 +03:00
if ( IS_ERR ( obj - > umem ) )
return PTR_ERR ( obj - > umem ) ;
mlx5_ib_cont_pages ( obj - > umem , obj - > umem - > address ,
MLX5_MKEY_PAGE_SHIFT_MASK , & npages ,
& obj - > page_shift , & obj - > ncont , NULL ) ;
if ( ! npages ) {
ib_umem_release ( obj - > umem ) ;
return - EINVAL ;
}
page_mask = ( 1 < < obj - > page_shift ) - 1 ;
obj - > page_offset = obj - > umem - > address & page_mask ;
return 0 ;
}
2018-08-10 05:14:41 +03:00
static int devx_umem_reg_cmd_alloc ( struct uverbs_attr_bundle * attrs ,
struct devx_umem * obj ,
2018-06-17 13:00:04 +03:00
struct devx_umem_reg_cmd * cmd )
{
cmd - > inlen = MLX5_ST_SZ_BYTES ( create_umem_in ) +
( MLX5_ST_SZ_BYTES ( mtt ) * obj - > ncont ) ;
2018-08-10 05:14:41 +03:00
cmd - > in = uverbs_zalloc ( attrs , cmd - > inlen ) ;
return PTR_ERR_OR_ZERO ( cmd - > in ) ;
2018-06-17 13:00:04 +03:00
}
static void devx_umem_reg_cmd_build ( struct mlx5_ib_dev * dev ,
struct devx_umem * obj ,
struct devx_umem_reg_cmd * cmd )
{
void * umem ;
__be64 * mtt ;
umem = MLX5_ADDR_OF ( create_umem_in , cmd - > in , umem ) ;
mtt = ( __be64 * ) MLX5_ADDR_OF ( umem , umem , mtt ) ;
2018-12-19 17:28:15 +03:00
MLX5_SET ( create_umem_in , cmd - > in , opcode , MLX5_CMD_OP_CREATE_UMEM ) ;
2018-06-17 13:00:04 +03:00
MLX5_SET64 ( umem , umem , num_of_mtt , obj - > ncont ) ;
MLX5_SET ( umem , umem , log_page_size , obj - > page_shift -
MLX5_ADAPTER_PAGE_SHIFT ) ;
MLX5_SET ( umem , umem , page_offset , obj - > page_offset ) ;
mlx5_ib_populate_pas ( dev , obj - > umem , obj - > page_shift , mtt ,
( obj - > umem - > writable ? MLX5_IB_MTT_WRITE : 0 ) |
MLX5_IB_MTT_READ ) ;
}
2018-07-26 06:40:18 +03:00
static int UVERBS_HANDLER ( MLX5_IB_METHOD_DEVX_UMEM_REG ) (
2018-11-25 21:51:15 +03:00
struct uverbs_attr_bundle * attrs )
2018-06-17 13:00:04 +03:00
{
struct devx_umem_reg_cmd cmd ;
struct devx_umem * obj ;
2018-07-11 05:55:22 +03:00
struct ib_uobject * uobj = uverbs_attr_get_uobject (
attrs , MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE ) ;
2018-06-17 13:00:04 +03:00
u32 obj_id ;
2018-07-11 05:55:22 +03:00
struct mlx5_ib_ucontext * c = to_mucontext ( uobj - > context ) ;
struct mlx5_ib_dev * dev = to_mdev ( c - > ibucontext . device ) ;
2018-06-17 13:00:04 +03:00
int err ;
if ( ! c - > devx_uid )
2018-09-20 21:45:20 +03:00
return - EINVAL ;
2018-06-17 13:00:04 +03:00
obj = kzalloc ( sizeof ( struct devx_umem ) , GFP_KERNEL ) ;
if ( ! obj )
return - ENOMEM ;
err = devx_umem_get ( dev , & c - > ibucontext , attrs , obj ) ;
if ( err )
goto err_obj_free ;
2018-08-10 05:14:41 +03:00
err = devx_umem_reg_cmd_alloc ( attrs , obj , & cmd ) ;
2018-06-17 13:00:04 +03:00
if ( err )
goto err_umem_release ;
devx_umem_reg_cmd_build ( dev , obj , & cmd ) ;
2018-12-19 17:28:15 +03:00
MLX5_SET ( create_umem_in , cmd . in , uid , c - > devx_uid ) ;
2018-06-17 13:00:04 +03:00
err = mlx5_cmd_exec ( dev - > mdev , cmd . in , cmd . inlen , cmd . out ,
sizeof ( cmd . out ) ) ;
if ( err )
2018-08-10 05:14:41 +03:00
goto err_umem_release ;
2018-06-17 13:00:04 +03:00
obj - > mdev = dev - > mdev ;
uobj - > object = obj ;
devx_obj_build_destroy_cmd ( cmd . in , cmd . out , obj - > dinbox , & obj - > dinlen , & obj_id ) ;
err = uverbs_copy_to ( attrs , MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID , & obj_id , sizeof ( obj_id ) ) ;
if ( err )
goto err_umem_destroy ;
return 0 ;
err_umem_destroy :
mlx5_cmd_exec ( obj - > mdev , obj - > dinbox , obj - > dinlen , cmd . out , sizeof ( cmd . out ) ) ;
err_umem_release :
ib_umem_release ( obj - > umem ) ;
err_obj_free :
kfree ( obj ) ;
return err ;
}
static int devx_umem_cleanup ( struct ib_uobject * uobject ,
enum rdma_remove_reason why )
{
struct devx_umem * obj = uobject - > object ;
u32 out [ MLX5_ST_SZ_DW ( general_obj_out_cmd_hdr ) ] ;
int err ;
err = mlx5_cmd_exec ( obj - > mdev , obj - > dinbox , obj - > dinlen , out , sizeof ( out ) ) ;
2018-06-20 17:11:39 +03:00
if ( ib_is_destroy_retryable ( err , why , uobject ) )
2018-06-17 13:00:04 +03:00
return err ;
ib_umem_release ( obj - > umem ) ;
kfree ( obj ) ;
return 0 ;
}
2018-07-04 08:50:28 +03:00
DECLARE_UVERBS_NAMED_METHOD (
MLX5_IB_METHOD_DEVX_UMEM_REG ,
UVERBS_ATTR_IDR ( MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE ,
MLX5_IB_OBJECT_DEVX_UMEM ,
UVERBS_ACCESS_NEW ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ) ,
2018-07-04 08:50:28 +03:00
UVERBS_ATTR_PTR_IN ( MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR ,
UVERBS_ATTR_TYPE ( u64 ) ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ) ,
2018-07-04 08:50:28 +03:00
UVERBS_ATTR_PTR_IN ( MLX5_IB_ATTR_DEVX_UMEM_REG_LEN ,
UVERBS_ATTR_TYPE ( u64 ) ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ) ,
2018-07-27 01:37:14 +03:00
UVERBS_ATTR_FLAGS_IN ( MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS ,
enum ib_access_flags ) ,
2018-07-04 08:50:28 +03:00
UVERBS_ATTR_PTR_OUT ( MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID ,
UVERBS_ATTR_TYPE ( u32 ) ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ) ) ;
2018-07-04 08:50:28 +03:00
2018-07-08 13:24:39 +03:00
DECLARE_UVERBS_NAMED_METHOD_DESTROY (
2018-07-04 08:50:28 +03:00
MLX5_IB_METHOD_DEVX_UMEM_DEREG ,
UVERBS_ATTR_IDR ( MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE ,
MLX5_IB_OBJECT_DEVX_UMEM ,
UVERBS_ACCESS_DESTROY ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ) ) ;
2018-07-04 08:50:28 +03:00
DECLARE_UVERBS_NAMED_METHOD (
MLX5_IB_METHOD_DEVX_QUERY_EQN ,
UVERBS_ATTR_PTR_IN ( MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC ,
UVERBS_ATTR_TYPE ( u32 ) ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ) ,
2018-07-04 08:50:28 +03:00
UVERBS_ATTR_PTR_OUT ( MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN ,
UVERBS_ATTR_TYPE ( u32 ) ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ) ) ;
2018-07-04 08:50:28 +03:00
DECLARE_UVERBS_NAMED_METHOD (
MLX5_IB_METHOD_DEVX_QUERY_UAR ,
UVERBS_ATTR_PTR_IN ( MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX ,
UVERBS_ATTR_TYPE ( u32 ) ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ) ,
2018-07-04 08:50:28 +03:00
UVERBS_ATTR_PTR_OUT ( MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX ,
UVERBS_ATTR_TYPE ( u32 ) ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ) ) ;
2018-07-04 08:50:28 +03:00
DECLARE_UVERBS_NAMED_METHOD (
MLX5_IB_METHOD_DEVX_OTHER ,
UVERBS_ATTR_PTR_IN (
MLX5_IB_ATTR_DEVX_OTHER_CMD_IN ,
UVERBS_ATTR_MIN_SIZE ( MLX5_ST_SZ_BYTES ( general_obj_in_cmd_hdr ) ) ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ,
UA_ALLOC_AND_COPY ) ,
2018-07-04 08:50:28 +03:00
UVERBS_ATTR_PTR_OUT (
MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT ,
UVERBS_ATTR_MIN_SIZE ( MLX5_ST_SZ_BYTES ( general_obj_out_cmd_hdr ) ) ,
2018-07-04 08:50:30 +03:00
UA_MANDATORY ) ) ;
2018-07-04 08:50:28 +03:00
DECLARE_UVERBS_NAMED_METHOD (
MLX5_IB_METHOD_DEVX_OBJ_CREATE ,
UVERBS_ATTR_IDR ( MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE ,
MLX5_IB_OBJECT_DEVX_OBJ ,
UVERBS_ACCESS_NEW ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ) ,
2018-07-04 08:50:28 +03:00
UVERBS_ATTR_PTR_IN (
MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN ,
UVERBS_ATTR_MIN_SIZE ( MLX5_ST_SZ_BYTES ( general_obj_in_cmd_hdr ) ) ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ,
UA_ALLOC_AND_COPY ) ,
2018-07-04 08:50:28 +03:00
UVERBS_ATTR_PTR_OUT (
MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT ,
UVERBS_ATTR_MIN_SIZE ( MLX5_ST_SZ_BYTES ( general_obj_out_cmd_hdr ) ) ,
2018-07-04 08:50:30 +03:00
UA_MANDATORY ) ) ;
2018-07-04 08:50:28 +03:00
2018-07-08 13:24:39 +03:00
DECLARE_UVERBS_NAMED_METHOD_DESTROY (
2018-07-04 08:50:28 +03:00
MLX5_IB_METHOD_DEVX_OBJ_DESTROY ,
UVERBS_ATTR_IDR ( MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE ,
MLX5_IB_OBJECT_DEVX_OBJ ,
UVERBS_ACCESS_DESTROY ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ) ) ;
2018-07-04 08:50:28 +03:00
DECLARE_UVERBS_NAMED_METHOD (
MLX5_IB_METHOD_DEVX_OBJ_MODIFY ,
UVERBS_ATTR_IDR ( MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE ,
2018-11-26 09:28:35 +03:00
UVERBS_IDR_ANY_OBJECT ,
2018-07-04 08:50:28 +03:00
UVERBS_ACCESS_WRITE ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ) ,
2018-07-04 08:50:28 +03:00
UVERBS_ATTR_PTR_IN (
MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN ,
UVERBS_ATTR_MIN_SIZE ( MLX5_ST_SZ_BYTES ( general_obj_in_cmd_hdr ) ) ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ,
UA_ALLOC_AND_COPY ) ,
2018-07-04 08:50:28 +03:00
UVERBS_ATTR_PTR_OUT (
MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT ,
UVERBS_ATTR_MIN_SIZE ( MLX5_ST_SZ_BYTES ( general_obj_out_cmd_hdr ) ) ,
2018-07-04 08:50:30 +03:00
UA_MANDATORY ) ) ;
2018-07-04 08:50:28 +03:00
DECLARE_UVERBS_NAMED_METHOD (
MLX5_IB_METHOD_DEVX_OBJ_QUERY ,
UVERBS_ATTR_IDR ( MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE ,
2018-11-26 09:28:35 +03:00
UVERBS_IDR_ANY_OBJECT ,
2018-07-04 08:50:28 +03:00
UVERBS_ACCESS_READ ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ) ,
2018-07-04 08:50:28 +03:00
UVERBS_ATTR_PTR_IN (
MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN ,
UVERBS_ATTR_MIN_SIZE ( MLX5_ST_SZ_BYTES ( general_obj_in_cmd_hdr ) ) ,
2018-07-04 08:50:29 +03:00
UA_MANDATORY ,
UA_ALLOC_AND_COPY ) ,
2018-07-04 08:50:28 +03:00
UVERBS_ATTR_PTR_OUT (
MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT ,
UVERBS_ATTR_MIN_SIZE ( MLX5_ST_SZ_BYTES ( general_obj_out_cmd_hdr ) ) ,
2018-07-04 08:50:30 +03:00
UA_MANDATORY ) ) ;
2018-06-17 13:00:02 +03:00
2018-07-04 08:50:27 +03:00
DECLARE_UVERBS_GLOBAL_METHODS ( MLX5_IB_OBJECT_DEVX ,
2018-07-04 08:50:28 +03:00
& UVERBS_METHOD ( MLX5_IB_METHOD_DEVX_OTHER ) ,
& UVERBS_METHOD ( MLX5_IB_METHOD_DEVX_QUERY_UAR ) ,
& UVERBS_METHOD ( MLX5_IB_METHOD_DEVX_QUERY_EQN ) ) ;
2018-06-17 13:00:00 +03:00
2018-07-04 08:50:27 +03:00
DECLARE_UVERBS_NAMED_OBJECT ( MLX5_IB_OBJECT_DEVX_OBJ ,
2018-07-04 08:50:28 +03:00
UVERBS_TYPE_ALLOC_IDR ( devx_obj_cleanup ) ,
& UVERBS_METHOD ( MLX5_IB_METHOD_DEVX_OBJ_CREATE ) ,
& UVERBS_METHOD ( MLX5_IB_METHOD_DEVX_OBJ_DESTROY ) ,
& UVERBS_METHOD ( MLX5_IB_METHOD_DEVX_OBJ_MODIFY ) ,
& UVERBS_METHOD ( MLX5_IB_METHOD_DEVX_OBJ_QUERY ) ) ;
2018-06-17 13:00:01 +03:00
2018-07-04 08:50:27 +03:00
DECLARE_UVERBS_NAMED_OBJECT ( MLX5_IB_OBJECT_DEVX_UMEM ,
2018-07-04 08:50:28 +03:00
UVERBS_TYPE_ALLOC_IDR ( devx_umem_cleanup ) ,
& UVERBS_METHOD ( MLX5_IB_METHOD_DEVX_UMEM_REG ) ,
& UVERBS_METHOD ( MLX5_IB_METHOD_DEVX_UMEM_DEREG ) ) ;
2018-06-17 13:00:04 +03:00
2018-11-12 23:59:53 +03:00
static bool devx_is_supported ( struct ib_device * device )
2018-06-17 13:00:06 +03:00
{
2018-11-12 23:59:53 +03:00
struct mlx5_ib_dev * dev = to_mdev ( device ) ;
2018-12-19 17:28:15 +03:00
return ! dev - > rep & & MLX5_CAP_GEN ( dev - > mdev , log_max_uctx ) ;
2018-06-17 13:00:06 +03:00
}
2018-11-12 23:59:53 +03:00
2018-11-12 23:59:50 +03:00
const struct uapi_definition mlx5_ib_devx_defs [ ] = {
2018-11-12 23:59:53 +03:00
UAPI_DEF_CHAIN_OBJ_TREE_NAMED (
MLX5_IB_OBJECT_DEVX ,
UAPI_DEF_IS_OBJ_SUPPORTED ( devx_is_supported ) ) ,
UAPI_DEF_CHAIN_OBJ_TREE_NAMED (
MLX5_IB_OBJECT_DEVX_OBJ ,
UAPI_DEF_IS_OBJ_SUPPORTED ( devx_is_supported ) ) ,
UAPI_DEF_CHAIN_OBJ_TREE_NAMED (
MLX5_IB_OBJECT_DEVX_UMEM ,
UAPI_DEF_IS_OBJ_SUPPORTED ( devx_is_supported ) ) ,
2018-11-12 23:59:50 +03:00
{ } ,
} ;