mlx5_fs_cmd.c revision 329200
1/*- 2 * Copyright (c) 2013-2017, Mellanox Technologies, Ltd. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 * 25 * $FreeBSD: stable/11/sys/dev/mlx5/mlx5_core/mlx5_fs_cmd.c 329200 2018-02-13 14:37:21Z hselasky $ 26 */ 27 28#include <linux/types.h> 29#include <linux/module.h> 30#include <dev/mlx5/mlx5_ifc.h> 31#include <dev/mlx5/device.h> 32#include <dev/mlx5/fs.h> 33 34#include "fs_core.h" 35#include "mlx5_core.h" 36 37int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev, 38 enum fs_ft_type type, 39 unsigned int id) 40{ 41 u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)]; 42 u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)]; 43 44 if (!dev) 45 return -EINVAL; 46 memset(in, 0, sizeof(in)); 47 48 MLX5_SET(set_flow_table_root_in, in, opcode, 49 MLX5_CMD_OP_SET_FLOW_TABLE_ROOT); 50 MLX5_SET(set_flow_table_root_in, in, table_type, type); 51 MLX5_SET(set_flow_table_root_in, in, table_id, id); 52 53 memset(out, 0, sizeof(out)); 54 return mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, 55 sizeof(out)); 56} 57 58int mlx5_cmd_fs_create_ft(struct mlx5_core_dev *dev, 59 u16 vport, 60 enum fs_ft_type type, unsigned int level, 61 unsigned int log_size, unsigned int *table_id) 62{ 63 u32 in[MLX5_ST_SZ_DW(create_flow_table_in)]; 64 u32 out[MLX5_ST_SZ_DW(create_flow_table_out)]; 65 int err; 66 67 if (!dev) 68 return -EINVAL; 69 memset(in, 0, sizeof(in)); 70 71 MLX5_SET(create_flow_table_in, in, opcode, 72 MLX5_CMD_OP_CREATE_FLOW_TABLE); 73 74 MLX5_SET(create_flow_table_in, in, table_type, type); 75 MLX5_SET(create_flow_table_in, in, flow_table_context.level, level); 76 MLX5_SET(create_flow_table_in, in, flow_table_context.log_size, 77 log_size); 78 if (vport) { 79 MLX5_SET(create_flow_table_in, in, vport_number, vport); 80 MLX5_SET(create_flow_table_in, in, other_vport, 1); 81 } 82 83 memset(out, 0, sizeof(out)); 84 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, 85 sizeof(out)); 86 if (err) 87 return err; 88 89 *table_id = MLX5_GET(create_flow_table_out, out, table_id); 90 91 return 0; 92} 93 94int mlx5_cmd_fs_destroy_ft(struct mlx5_core_dev *dev, 95 u16 vport, 96 enum fs_ft_type type, unsigned int table_id) 97{ 98 u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)]; 99 u32 out[MLX5_ST_SZ_DW(destroy_flow_table_out)]; 100 101 if (!dev) 102 return -EINVAL; 103 memset(in, 0, sizeof(in)); 104 memset(out, 0, sizeof(out)); 105 106 MLX5_SET(destroy_flow_table_in, in, opcode, 107 MLX5_CMD_OP_DESTROY_FLOW_TABLE); 108 MLX5_SET(destroy_flow_table_in, in, table_type, type); 109 MLX5_SET(destroy_flow_table_in, in, table_id, table_id); 110 if (vport) { 111 MLX5_SET(destroy_flow_table_in, in, vport_number, vport); 112 MLX5_SET(destroy_flow_table_in, in, other_vport, 1); 113 } 114 115 return mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 116} 117 118int mlx5_cmd_fs_create_fg(struct mlx5_core_dev *dev, 119 u32 *in, 120 u16 vport, 121 enum fs_ft_type type, unsigned int table_id, 122 unsigned int *group_id) 123{ 124 u32 out[MLX5_ST_SZ_DW(create_flow_group_out)]; 125 int err; 126 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 127 if (!dev) 128 return -EINVAL; 129 memset(out, 0, sizeof(out)); 130 131 MLX5_SET(create_flow_group_in, in, opcode, 132 MLX5_CMD_OP_CREATE_FLOW_GROUP); 133 MLX5_SET(create_flow_group_in, in, table_type, type); 134 MLX5_SET(create_flow_group_in, in, table_id, table_id); 135 if (vport) { 136 MLX5_SET(create_flow_group_in, in, vport_number, vport); 137 MLX5_SET(create_flow_group_in, in, other_vport, 1); 138 } 139 140 err = mlx5_cmd_exec_check_status(dev, in, 141 inlen, out, 142 sizeof(out)); 143 if (!err) 144 *group_id = MLX5_GET(create_flow_group_out, out, group_id); 145 146 return err; 147} 148 149int mlx5_cmd_fs_destroy_fg(struct mlx5_core_dev *dev, 150 u16 vport, 151 enum fs_ft_type type, unsigned int table_id, 152 unsigned int group_id) 153{ 154 u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)]; 155 u32 out[MLX5_ST_SZ_DW(destroy_flow_group_out)]; 156 157 if (!dev) 158 return -EINVAL; 159 memset(in, 0, sizeof(in)); 160 memset(out, 0, sizeof(out)); 161 162 MLX5_SET(destroy_flow_group_in, in, opcode, 163 MLX5_CMD_OP_DESTROY_FLOW_GROUP); 164 MLX5_SET(destroy_flow_group_in, in, table_type, type); 165 MLX5_SET(destroy_flow_group_in, in, table_id, table_id); 166 MLX5_SET(destroy_flow_group_in, in, group_id, group_id); 167 if (vport) { 168 MLX5_SET(destroy_flow_group_in, in, vport_number, vport); 169 MLX5_SET(destroy_flow_group_in, in, other_vport, 1); 170 } 171 172 return mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 173} 174 175int mlx5_cmd_fs_set_fte(struct mlx5_core_dev *dev, 176 u16 vport, 177 enum fs_fte_status *fte_status, 178 u32 *match_val, 179 enum fs_ft_type type, unsigned int table_id, 180 unsigned int index, unsigned int group_id, 181 unsigned int flow_tag, 182 unsigned short action, int dest_size, 183 struct list_head *dests) /* mlx5_flow_desination */ 184{ 185 u32 out[MLX5_ST_SZ_DW(set_fte_out)]; 186 u32 *in; 187 unsigned int inlen; 188 struct mlx5_flow_rule *dst; 189 void *in_flow_context; 190 void *in_match_value; 191 void *in_dests; 192 int err; 193 int opmod = 0; 194 int modify_mask = 0; 195 int atomic_mod_cap; 196 197 if (action != MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) 198 dest_size = 0; 199 200 inlen = MLX5_ST_SZ_BYTES(set_fte_in) + 201 dest_size * MLX5_ST_SZ_BYTES(dest_format_struct); 202 203 if (!dev) 204 return -EINVAL; 205 206 if (*fte_status & FS_FTE_STATUS_EXISTING) { 207 atomic_mod_cap = MLX5_CAP_FLOWTABLE(dev, 208 flow_table_properties_nic_receive. 209 flow_modify_en); 210 if (!atomic_mod_cap) 211 return -ENOTSUPP; 212 opmod = 1; 213 modify_mask = 1 << 214 MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST; 215 } 216 217 in = mlx5_vzalloc(inlen); 218 if (!in) { 219 mlx5_core_warn(dev, "failed to allocate inbox\n"); 220 return -ENOMEM; 221 } 222 223 MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY); 224 MLX5_SET(set_fte_in, in, op_mod, opmod); 225 MLX5_SET(set_fte_in, in, modify_enable_mask, modify_mask); 226 MLX5_SET(set_fte_in, in, table_type, type); 227 MLX5_SET(set_fte_in, in, table_id, table_id); 228 MLX5_SET(set_fte_in, in, flow_index, index); 229 if (vport) { 230 MLX5_SET(set_fte_in, in, vport_number, vport); 231 MLX5_SET(set_fte_in, in, other_vport, 1); 232 } 233 234 in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context); 235 MLX5_SET(flow_context, in_flow_context, group_id, group_id); 236 MLX5_SET(flow_context, in_flow_context, flow_tag, flow_tag); 237 MLX5_SET(flow_context, in_flow_context, action, action); 238 MLX5_SET(flow_context, in_flow_context, destination_list_size, 239 dest_size); 240 in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context, 241 match_value); 242 memcpy(in_match_value, match_val, MLX5_ST_SZ_BYTES(fte_match_param)); 243 if (dest_size) { 244 in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination); 245 list_for_each_entry(dst, dests, base.list) { 246 unsigned int id; 247 248 MLX5_SET(dest_format_struct, in_dests, destination_type, 249 dst->dest_attr.type); 250 if (dst->dest_attr.type == 251 MLX5_FLOW_CONTEXT_DEST_TYPE_FLOW_TABLE) 252 id = dst->dest_attr.ft->id; 253 else 254 id = dst->dest_attr.tir_num; 255 MLX5_SET(dest_format_struct, in_dests, destination_id, id); 256 in_dests += MLX5_ST_SZ_BYTES(dest_format_struct); 257 } 258 } 259 memset(out, 0, sizeof(out)); 260 err = mlx5_cmd_exec_check_status(dev, in, inlen, out, 261 sizeof(out)); 262 if (!err) 263 *fte_status |= FS_FTE_STATUS_EXISTING; 264 265 kvfree(in); 266 267 return err; 268} 269 270int mlx5_cmd_fs_delete_fte(struct mlx5_core_dev *dev, 271 u16 vport, 272 enum fs_fte_status *fte_status, 273 enum fs_ft_type type, unsigned int table_id, 274 unsigned int index) 275{ 276 u32 in[MLX5_ST_SZ_DW(delete_fte_in)]; 277 u32 out[MLX5_ST_SZ_DW(delete_fte_out)]; 278 int err; 279 280 if (!(*fte_status & FS_FTE_STATUS_EXISTING)) 281 return 0; 282 283 if (!dev) 284 return -EINVAL; 285 memset(in, 0, sizeof(in)); 286 memset(out, 0, sizeof(out)); 287 288 MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY); 289 MLX5_SET(delete_fte_in, in, table_type, type); 290 MLX5_SET(delete_fte_in, in, table_id, table_id); 291 MLX5_SET(delete_fte_in, in, flow_index, index); 292 if (vport) { 293 MLX5_SET(delete_fte_in, in, vport_number, vport); 294 MLX5_SET(delete_fte_in, in, other_vport, 1); 295 } 296 297 err = mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out)); 298 if (!err) 299 *fte_status = 0; 300 301 return err; 302} 303