Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
0002 /* Copyright (c) 2019 Mellanox Technologies */
0003 
0004 #include <linux/mlx5/vport.h>
0005 #include <rdma/ib_verbs.h>
0006 #include <net/addrconf.h>
0007 
0008 #include "lib/mlx5.h"
0009 #include "eswitch.h"
0010 #include "fs_core.h"
0011 #include "rdma.h"
0012 
0013 static void mlx5_rdma_disable_roce_steering(struct mlx5_core_dev *dev)
0014 {
0015     struct mlx5_core_roce *roce = &dev->priv.roce;
0016 
0017     mlx5_del_flow_rules(roce->allow_rule);
0018     mlx5_destroy_flow_group(roce->fg);
0019     mlx5_destroy_flow_table(roce->ft);
0020 }
0021 
0022 static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev)
0023 {
0024     int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
0025     struct mlx5_core_roce *roce = &dev->priv.roce;
0026     struct mlx5_flow_handle *flow_rule = NULL;
0027     struct mlx5_flow_table_attr ft_attr = {};
0028     struct mlx5_flow_namespace *ns = NULL;
0029     struct mlx5_flow_act flow_act = {};
0030     struct mlx5_flow_spec *spec;
0031     struct mlx5_flow_table *ft;
0032     struct mlx5_flow_group *fg;
0033     void *match_criteria;
0034     u32 *flow_group_in;
0035     void *misc;
0036     int err;
0037 
0038     if (!(MLX5_CAP_FLOWTABLE_RDMA_RX(dev, ft_support) &&
0039           MLX5_CAP_FLOWTABLE_RDMA_RX(dev, table_miss_action_domain)))
0040         return -EOPNOTSUPP;
0041 
0042     flow_group_in = kvzalloc(inlen, GFP_KERNEL);
0043     if (!flow_group_in)
0044         return -ENOMEM;
0045     spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
0046     if (!spec) {
0047         kvfree(flow_group_in);
0048         return -ENOMEM;
0049     }
0050 
0051     ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_RDMA_RX_KERNEL);
0052     if (!ns) {
0053         mlx5_core_err(dev, "Failed to get RDMA RX namespace");
0054         err = -EOPNOTSUPP;
0055         goto free;
0056     }
0057 
0058     ft_attr.max_fte = 1;
0059     ft = mlx5_create_flow_table(ns, &ft_attr);
0060     if (IS_ERR(ft)) {
0061         mlx5_core_err(dev, "Failed to create RDMA RX flow table");
0062         err = PTR_ERR(ft);
0063         goto free;
0064     }
0065 
0066     MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
0067          MLX5_MATCH_MISC_PARAMETERS);
0068     match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in,
0069                       match_criteria);
0070     MLX5_SET_TO_ONES(fte_match_param, match_criteria,
0071              misc_parameters.source_port);
0072 
0073     fg = mlx5_create_flow_group(ft, flow_group_in);
0074     if (IS_ERR(fg)) {
0075         err = PTR_ERR(fg);
0076         mlx5_core_err(dev, "Failed to create RDMA RX flow group err(%d)\n", err);
0077         goto destroy_flow_table;
0078     }
0079 
0080     spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
0081     misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
0082                 misc_parameters);
0083     MLX5_SET(fte_match_set_misc, misc, source_port,
0084          dev->priv.eswitch->manager_vport);
0085     misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
0086                 misc_parameters);
0087     MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
0088 
0089     flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
0090     flow_rule = mlx5_add_flow_rules(ft, spec, &flow_act, NULL, 0);
0091     if (IS_ERR(flow_rule)) {
0092         err = PTR_ERR(flow_rule);
0093         mlx5_core_err(dev, "Failed to add RoCE allow rule, err=%d\n",
0094                   err);
0095         goto destroy_flow_group;
0096     }
0097 
0098     kvfree(spec);
0099     kvfree(flow_group_in);
0100     roce->ft = ft;
0101     roce->fg = fg;
0102     roce->allow_rule = flow_rule;
0103 
0104     return 0;
0105 
0106 destroy_flow_group:
0107     mlx5_destroy_flow_group(fg);
0108 destroy_flow_table:
0109     mlx5_destroy_flow_table(ft);
0110 free:
0111     kvfree(spec);
0112     kvfree(flow_group_in);
0113     return err;
0114 }
0115 
0116 static void mlx5_rdma_del_roce_addr(struct mlx5_core_dev *dev)
0117 {
0118     mlx5_core_roce_gid_set(dev, 0, 0, 0,
0119                    NULL, NULL, false, 0, 1);
0120 }
0121 
0122 static void mlx5_rdma_make_default_gid(struct mlx5_core_dev *dev, union ib_gid *gid)
0123 {
0124     u8 hw_id[ETH_ALEN];
0125 
0126     mlx5_query_mac_address(dev, hw_id);
0127     gid->global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL);
0128     addrconf_addr_eui48(&gid->raw[8], hw_id);
0129 }
0130 
0131 static int mlx5_rdma_add_roce_addr(struct mlx5_core_dev *dev)
0132 {
0133     union ib_gid gid;
0134     u8 mac[ETH_ALEN];
0135 
0136     mlx5_rdma_make_default_gid(dev, &gid);
0137     return mlx5_core_roce_gid_set(dev, 0,
0138                       MLX5_ROCE_VERSION_1,
0139                       0, gid.raw, mac,
0140                       false, 0, 1);
0141 }
0142 
0143 void mlx5_rdma_disable_roce(struct mlx5_core_dev *dev)
0144 {
0145     struct mlx5_core_roce *roce = &dev->priv.roce;
0146 
0147     if (!roce->ft)
0148         return;
0149 
0150     mlx5_rdma_disable_roce_steering(dev);
0151     mlx5_rdma_del_roce_addr(dev);
0152     mlx5_nic_vport_disable_roce(dev);
0153 }
0154 
0155 void mlx5_rdma_enable_roce(struct mlx5_core_dev *dev)
0156 {
0157     int err;
0158 
0159     if (!MLX5_CAP_GEN(dev, roce))
0160         return;
0161 
0162     err = mlx5_nic_vport_enable_roce(dev);
0163     if (err) {
0164         mlx5_core_err(dev, "Failed to enable RoCE: %d\n", err);
0165         return;
0166     }
0167 
0168     err = mlx5_rdma_add_roce_addr(dev);
0169     if (err) {
0170         mlx5_core_err(dev, "Failed to add RoCE address: %d\n", err);
0171         goto disable_roce;
0172     }
0173 
0174     err = mlx5_rdma_enable_roce_steering(dev);
0175     if (err) {
0176         mlx5_core_err(dev, "Failed to enable RoCE steering: %d\n", err);
0177         goto del_roce_addr;
0178     }
0179 
0180     return;
0181 
0182 del_roce_addr:
0183     mlx5_rdma_del_roce_addr(dev);
0184 disable_roce:
0185     mlx5_nic_vport_disable_roce(dev);
0186 }