xref: /linux/drivers/infiniband/hw/mlx5/ib_rep.c (revision 02ff58dcf70ad7d11b01523dc404166ed11021da)
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