xref: /openbmc/linux/drivers/infiniband/hw/mlx5/ib_rep.c (revision 943126417891372d56aa3fe46295cbf53db31370)
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 };
43 
44 static int
45 mlx5_ib_nic_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
46 {
47 	return 0;
48 }
49 
50 static void
51 mlx5_ib_nic_rep_unload(struct mlx5_eswitch_rep *rep)
52 {
53 	rep->rep_if[REP_IB].priv = NULL;
54 }
55 
56 static int
57 mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
58 {
59 	struct mlx5_ib_dev *ibdev;
60 
61 	ibdev = (struct mlx5_ib_dev *)ib_alloc_device(sizeof(*ibdev));
62 	if (!ibdev)
63 		return -ENOMEM;
64 
65 	ibdev->rep = rep;
66 	ibdev->mdev = dev;
67 	ibdev->num_ports = max(MLX5_CAP_GEN(dev, num_ports),
68 			       MLX5_CAP_GEN(dev, num_vhca_ports));
69 	if (!__mlx5_ib_add(ibdev, &rep_profile))
70 		return -EINVAL;
71 
72 	rep->rep_if[REP_IB].priv = ibdev;
73 
74 	return 0;
75 }
76 
77 static void
78 mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep)
79 {
80 	struct mlx5_ib_dev *dev;
81 
82 	if (!rep->rep_if[REP_IB].priv)
83 		return;
84 
85 	dev = mlx5_ib_rep_to_dev(rep);
86 	__mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX);
87 	rep->rep_if[REP_IB].priv = NULL;
88 }
89 
90 static void *mlx5_ib_vport_get_proto_dev(struct mlx5_eswitch_rep *rep)
91 {
92 	return mlx5_ib_rep_to_dev(rep);
93 }
94 
95 static void mlx5_ib_rep_register_vf_vports(struct mlx5_ib_dev *dev)
96 {
97 	struct mlx5_eswitch *esw   = dev->mdev->priv.eswitch;
98 	int total_vfs = MLX5_TOTAL_VPORTS(dev->mdev);
99 	int vport;
100 
101 	for (vport = 1; vport < total_vfs; vport++) {
102 		struct mlx5_eswitch_rep_if rep_if = {};
103 
104 		rep_if.load = mlx5_ib_vport_rep_load;
105 		rep_if.unload = mlx5_ib_vport_rep_unload;
106 		rep_if.get_proto_dev = mlx5_ib_vport_get_proto_dev;
107 		mlx5_eswitch_register_vport_rep(esw, vport, &rep_if, REP_IB);
108 	}
109 }
110 
111 static void mlx5_ib_rep_unregister_vf_vports(struct mlx5_ib_dev *dev)
112 {
113 	struct mlx5_eswitch *esw   = dev->mdev->priv.eswitch;
114 	int total_vfs = MLX5_TOTAL_VPORTS(dev->mdev);
115 	int vport;
116 
117 	for (vport = 1; vport < total_vfs; vport++)
118 		mlx5_eswitch_unregister_vport_rep(esw, vport, REP_IB);
119 }
120 
121 void mlx5_ib_register_vport_reps(struct mlx5_ib_dev *dev)
122 {
123 	struct mlx5_eswitch *esw = dev->mdev->priv.eswitch;
124 	struct mlx5_eswitch_rep_if rep_if = {};
125 
126 	rep_if.load = mlx5_ib_nic_rep_load;
127 	rep_if.unload = mlx5_ib_nic_rep_unload;
128 	rep_if.get_proto_dev = mlx5_ib_vport_get_proto_dev;
129 	rep_if.priv = dev;
130 
131 	mlx5_eswitch_register_vport_rep(esw, 0, &rep_if, REP_IB);
132 
133 	mlx5_ib_rep_register_vf_vports(dev);
134 }
135 
136 void mlx5_ib_unregister_vport_reps(struct mlx5_ib_dev *dev)
137 {
138 	struct mlx5_eswitch *esw   = dev->mdev->priv.eswitch;
139 
140 	mlx5_ib_rep_unregister_vf_vports(dev); /* VFs vports */
141 	mlx5_eswitch_unregister_vport_rep(esw, 0, REP_IB); /* UPLINK PF*/
142 }
143 
144 u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw)
145 {
146 	return mlx5_eswitch_mode(esw);
147 }
148 
149 struct mlx5_ib_dev *mlx5_ib_get_rep_ibdev(struct mlx5_eswitch *esw,
150 					  int vport_index)
151 {
152 	return mlx5_eswitch_get_proto_dev(esw, vport_index, REP_IB);
153 }
154 
155 struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
156 					  int vport_index)
157 {
158 	return mlx5_eswitch_get_proto_dev(esw, vport_index, REP_ETH);
159 }
160 
161 struct mlx5_ib_dev *mlx5_ib_get_uplink_ibdev(struct mlx5_eswitch *esw)
162 {
163 	return mlx5_eswitch_uplink_get_proto_dev(esw, REP_IB);
164 }
165 
166 struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw, int vport)
167 {
168 	return mlx5_eswitch_vport_rep(esw, vport);
169 }
170 
171 int create_flow_rule_vport_sq(struct mlx5_ib_dev *dev,
172 			      struct mlx5_ib_sq *sq)
173 {
174 	struct mlx5_flow_handle *flow_rule;
175 	struct mlx5_eswitch *esw = dev->mdev->priv.eswitch;
176 
177 	if (!dev->rep)
178 		return 0;
179 
180 	flow_rule =
181 		mlx5_eswitch_add_send_to_vport_rule(esw,
182 						    dev->rep->vport,
183 						    sq->base.mqp.qpn);
184 	if (IS_ERR(flow_rule))
185 		return PTR_ERR(flow_rule);
186 	sq->flow_rule = flow_rule;
187 
188 	return 0;
189 }
190