IB/mlx5: Implement VHCA tunnel mechanism in DEVX

This mechanism will allow function-A to perform operations "on behalf" of
function-B via tunnel object. Function-A will have privileges for creating
and using this tunnel object.

For example, in the device emulation feature presented in Bluefield-1 SoC,
using device emulation capability, one can present NVMe function to the
host OS.

Since the NVMe function doesn't have a normal command interface to the HCA
HW, here is a need to create a channel that will be able to issue commands
"on behalf" of this function.

This channel is the VHCA_TUNNEL general object. The emulation software
will create this tunnel for every managed function and issue commands via
devx general cmd interface using the appropriate tunnel ID. When devX
context will receive a command with non-zero vhca_tunnel_id, it will pass
the command as-is down to the HCA.

All the validation, security and resource tracking of the commands and the
created tunneled objects is in the responsibility of the HCA FW. When a
VHCA_TUNNEL object destroyed, the device will issue an internal
FLR (function level reset) to the emulated function associated with this
tunnel. This will destroy all the created resources using the tunnel
mechanism.

Signed-off-by: Max Gurtovoy <maxg@mellanox.com>
Reviewed-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
Max Gurtovoy 2019-07-01 21:14:02 +03:00 committed by Jason Gunthorpe
parent 1dd7382b1b
commit b6142608e8
1 changed files with 20 additions and 4 deletions

View File

@ -715,12 +715,16 @@ static int devx_get_uid(struct mlx5_ib_ucontext *c, void *cmd_in)
return c->devx_uid; return c->devx_uid;
} }
static bool devx_is_general_cmd(void *in)
static bool devx_is_general_cmd(void *in, struct mlx5_ib_dev *dev)
{ {
u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode); u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
if (opcode >= MLX5_CMD_OP_GENERAL_START && /* Pass all cmds for vhca_tunnel as general, tracking is done in FW */
opcode < MLX5_CMD_OP_GENERAL_END) if ((MLX5_CAP_GEN_64(dev->mdev, vhca_tunnel_commands) &&
MLX5_GET(general_obj_in_cmd_hdr, in, vhca_tunnel_id)) ||
(opcode >= MLX5_CMD_OP_GENERAL_START &&
opcode < MLX5_CMD_OP_GENERAL_END))
return true; return true;
switch (opcode) { switch (opcode) {
@ -846,7 +850,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(
return uid; return uid;
/* Only white list of some general HCA commands are allowed for this method. */ /* Only white list of some general HCA commands are allowed for this method. */
if (!devx_is_general_cmd(cmd_in)) if (!devx_is_general_cmd(cmd_in, dev))
return -EINVAL; return -EINVAL;
cmd_out = uverbs_zalloc(attrs, cmd_out_len); cmd_out = uverbs_zalloc(attrs, cmd_out_len);
@ -1169,6 +1173,9 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
u32 obj_id; u32 obj_id;
u16 opcode; u16 opcode;
if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
return -EINVAL;
uid = devx_get_uid(c, cmd_in); uid = devx_get_uid(c, cmd_in);
if (uid < 0) if (uid < 0)
return uid; return uid;
@ -1259,6 +1266,9 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)(
int err; int err;
int uid; int uid;
if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
return -EINVAL;
uid = devx_get_uid(c, cmd_in); uid = devx_get_uid(c, cmd_in);
if (uid < 0) if (uid < 0)
return uid; return uid;
@ -1301,6 +1311,9 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(
int uid; int uid;
struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device); struct mlx5_ib_dev *mdev = to_mdev(c->ibucontext.device);
if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
return -EINVAL;
uid = devx_get_uid(c, cmd_in); uid = devx_get_uid(c, cmd_in);
if (uid < 0) if (uid < 0)
return uid; return uid;
@ -1406,6 +1419,9 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY)(
struct devx_async_cmd_event_file *ev_file; struct devx_async_cmd_event_file *ev_file;
struct devx_async_data *async_data; struct devx_async_data *async_data;
if (MLX5_GET(general_obj_in_cmd_hdr, cmd_in, vhca_tunnel_id))
return -EINVAL;
uid = devx_get_uid(c, cmd_in); uid = devx_get_uid(c, cmd_in);
if (uid < 0) if (uid < 0)
return uid; return uid;