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