1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* 3 * Copyright (c) 2018 Mellanox Technologies. All rights reserved. 4 */ 5 6 #include "ib_rep.h" 7 8 static const struct mlx5_ib_profile rep_profile = { 9 STAGE_CREATE(MLX5_IB_STAGE_INIT, 10 mlx5_ib_stage_init_init, 11 mlx5_ib_stage_init_cleanup), 12 STAGE_CREATE(MLX5_IB_STAGE_FLOW_DB, 13 mlx5_ib_stage_rep_flow_db_init, 14 NULL), 15 STAGE_CREATE(MLX5_IB_STAGE_CAPS, 16 mlx5_ib_stage_caps_init, 17 NULL), 18 STAGE_CREATE(MLX5_IB_STAGE_NON_DEFAULT_CB, 19 mlx5_ib_stage_rep_non_default_cb, 20 NULL), 21 STAGE_CREATE(MLX5_IB_STAGE_ROCE, 22 mlx5_ib_stage_rep_roce_init, 23 mlx5_ib_stage_rep_roce_cleanup), 24 STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES, 25 mlx5_ib_stage_dev_res_init, 26 mlx5_ib_stage_dev_res_cleanup), 27 STAGE_CREATE(MLX5_IB_STAGE_COUNTERS, 28 mlx5_ib_stage_counters_init, 29 mlx5_ib_stage_counters_cleanup), 30 STAGE_CREATE(MLX5_IB_STAGE_BFREG, 31 mlx5_ib_stage_bfrag_init, 32 mlx5_ib_stage_bfrag_cleanup), 33 STAGE_CREATE(MLX5_IB_STAGE_PRE_IB_REG_UMR, 34 NULL, 35 mlx5_ib_stage_pre_ib_reg_umr_cleanup), 36 STAGE_CREATE(MLX5_IB_STAGE_IB_REG, 37 mlx5_ib_stage_ib_reg_init, 38 mlx5_ib_stage_ib_reg_cleanup), 39 STAGE_CREATE(MLX5_IB_STAGE_POST_IB_REG_UMR, 40 mlx5_ib_stage_post_ib_reg_umr_init, 41 NULL), 42 STAGE_CREATE(MLX5_IB_STAGE_CLASS_ATTR, 43 mlx5_ib_stage_class_attr_init, 44 NULL), 45 }; 46 47 static int 48 mlx5_ib_nic_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) 49 { 50 return 0; 51 } 52 53 static void 54 mlx5_ib_nic_rep_unload(struct mlx5_eswitch_rep *rep) 55 { 56 rep->rep_if[REP_IB].priv = NULL; 57 } 58 59 static int 60 mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) 61 { 62 struct mlx5_ib_dev *ibdev; 63 64 ibdev = (struct mlx5_ib_dev *)ib_alloc_device(sizeof(*ibdev)); 65 if (!ibdev) 66 return -ENOMEM; 67 68 ibdev->rep = rep; 69 ibdev->mdev = dev; 70 ibdev->num_ports = max(MLX5_CAP_GEN(dev, num_ports), 71 MLX5_CAP_GEN(dev, num_vhca_ports)); 72 if (!__mlx5_ib_add(ibdev, &rep_profile)) 73 return -EINVAL; 74 75 rep->rep_if[REP_IB].priv = ibdev; 76 77 return 0; 78 } 79 80 static void 81 mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep) 82 { 83 struct mlx5_ib_dev *dev; 84 85 if (!rep->rep_if[REP_IB].priv) 86 return; 87 88 dev = mlx5_ib_rep_to_dev(rep); 89 __mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX); 90 rep->rep_if[REP_IB].priv = NULL; 91 } 92 93 static void *mlx5_ib_vport_get_proto_dev(struct mlx5_eswitch_rep *rep) 94 { 95 return mlx5_ib_rep_to_dev(rep); 96 } 97 98 static void mlx5_ib_rep_register_vf_vports(struct mlx5_ib_dev *dev) 99 { 100 struct mlx5_eswitch *esw = dev->mdev->priv.eswitch; 101 int total_vfs = MLX5_TOTAL_VPORTS(dev->mdev); 102 int vport; 103 104 for (vport = 1; vport < total_vfs; vport++) { 105 struct mlx5_eswitch_rep_if rep_if = {}; 106 107 rep_if.load = mlx5_ib_vport_rep_load; 108 rep_if.unload = mlx5_ib_vport_rep_unload; 109 rep_if.get_proto_dev = mlx5_ib_vport_get_proto_dev; 110 mlx5_eswitch_register_vport_rep(esw, vport, &rep_if, REP_IB); 111 } 112 } 113 114 static void mlx5_ib_rep_unregister_vf_vports(struct mlx5_ib_dev *dev) 115 { 116 struct mlx5_eswitch *esw = dev->mdev->priv.eswitch; 117 int total_vfs = MLX5_TOTAL_VPORTS(dev->mdev); 118 int vport; 119 120 for (vport = 1; vport < total_vfs; vport++) 121 mlx5_eswitch_unregister_vport_rep(esw, vport, REP_IB); 122 } 123 124 void mlx5_ib_register_vport_reps(struct mlx5_ib_dev *dev) 125 { 126 struct mlx5_eswitch *esw = dev->mdev->priv.eswitch; 127 struct mlx5_eswitch_rep_if rep_if = {}; 128 129 rep_if.load = mlx5_ib_nic_rep_load; 130 rep_if.unload = mlx5_ib_nic_rep_unload; 131 rep_if.get_proto_dev = mlx5_ib_vport_get_proto_dev; 132 rep_if.priv = dev; 133 134 mlx5_eswitch_register_vport_rep(esw, 0, &rep_if, REP_IB); 135 136 mlx5_ib_rep_register_vf_vports(dev); 137 } 138 139 void mlx5_ib_unregister_vport_reps(struct mlx5_ib_dev *dev) 140 { 141 struct mlx5_eswitch *esw = dev->mdev->priv.eswitch; 142 143 mlx5_ib_rep_unregister_vf_vports(dev); /* VFs vports */ 144 mlx5_eswitch_unregister_vport_rep(esw, 0, REP_IB); /* UPLINK PF*/ 145 } 146 147 u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw) 148 { 149 return mlx5_eswitch_mode(esw); 150 } 151 152 struct mlx5_ib_dev *mlx5_ib_get_rep_ibdev(struct mlx5_eswitch *esw, 153 int vport_index) 154 { 155 return mlx5_eswitch_get_proto_dev(esw, vport_index, REP_IB); 156 } 157 158 struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw, 159 int vport_index) 160 { 161 return mlx5_eswitch_get_proto_dev(esw, vport_index, REP_ETH); 162 } 163 164 struct mlx5_ib_dev *mlx5_ib_get_uplink_ibdev(struct mlx5_eswitch *esw) 165 { 166 return mlx5_eswitch_uplink_get_proto_dev(esw, REP_IB); 167 } 168 169 struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw, int vport) 170 { 171 return mlx5_eswitch_vport_rep(esw, vport); 172 } 173 174 int create_flow_rule_vport_sq(struct mlx5_ib_dev *dev, 175 struct mlx5_ib_sq *sq) 176 { 177 struct mlx5_flow_handle *flow_rule; 178 struct mlx5_eswitch *esw = dev->mdev->priv.eswitch; 179 180 if (!dev->rep) 181 return 0; 182 183 flow_rule = 184 mlx5_eswitch_add_send_to_vport_rule(esw, 185 dev->rep->vport, 186 sq->base.mqp.qpn); 187 if (IS_ERR(flow_rule)) 188 return PTR_ERR(flow_rule); 189 sq->flow_rule = flow_rule; 190 191 return 0; 192 } 193