xref: /freebsd-src/sys/dev/mlx5/mlx5_fpga/mlx5fpga_core.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
1e9dcd831SSlava Shwartsman /*-
2e9dcd831SSlava Shwartsman  * Copyright (c) 2017, Mellanox Technologies. All rights reserved.
3e9dcd831SSlava Shwartsman  *
4e9dcd831SSlava Shwartsman  * This software is available to you under a choice of one of two
5e9dcd831SSlava Shwartsman  * licenses.  You may choose to be licensed under the terms of the GNU
6e9dcd831SSlava Shwartsman  * General Public License (GPL) Version 2, available from the file
7e9dcd831SSlava Shwartsman  * COPYING in the main directory of this source tree, or the
8e9dcd831SSlava Shwartsman  * OpenIB.org BSD license below:
9e9dcd831SSlava Shwartsman  *
10e9dcd831SSlava Shwartsman  *     Redistribution and use in source and binary forms, with or
11e9dcd831SSlava Shwartsman  *     without modification, are permitted provided that the following
12e9dcd831SSlava Shwartsman  *     conditions are met:
13e9dcd831SSlava Shwartsman  *
14e9dcd831SSlava Shwartsman  *      - Redistributions of source code must retain the above
15e9dcd831SSlava Shwartsman  *        copyright notice, this list of conditions and the following
16e9dcd831SSlava Shwartsman  *        disclaimer.
17e9dcd831SSlava Shwartsman  *
18e9dcd831SSlava Shwartsman  *      - Redistributions in binary form must reproduce the above
19e9dcd831SSlava Shwartsman  *        copyright notice, this list of conditions and the following
20e9dcd831SSlava Shwartsman  *        disclaimer in the documentation and/or other materials
21e9dcd831SSlava Shwartsman  *        provided with the distribution.
22e9dcd831SSlava Shwartsman  *
23e9dcd831SSlava Shwartsman  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24e9dcd831SSlava Shwartsman  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25e9dcd831SSlava Shwartsman  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26e9dcd831SSlava Shwartsman  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27e9dcd831SSlava Shwartsman  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28e9dcd831SSlava Shwartsman  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29e9dcd831SSlava Shwartsman  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30e9dcd831SSlava Shwartsman  * SOFTWARE.
31e9dcd831SSlava Shwartsman  */
32e9dcd831SSlava Shwartsman 
33e9dcd831SSlava Shwartsman #include <linux/module.h>
34e9dcd831SSlava Shwartsman #include <linux/etherdevice.h>
35e9dcd831SSlava Shwartsman #include <dev/mlx5/driver.h>
36e9dcd831SSlava Shwartsman #include <dev/mlx5/mlx5_core/mlx5_core.h>
37e9dcd831SSlava Shwartsman #include <dev/mlx5/mlx5_lib/mlx5.h>
38e9dcd831SSlava Shwartsman #include <dev/mlx5/mlx5_fpga/core.h>
39e9dcd831SSlava Shwartsman #include <dev/mlx5/mlx5_fpga/conn.h>
40e9dcd831SSlava Shwartsman #include <dev/mlx5/mlx5_fpga/trans.h>
41e9dcd831SSlava Shwartsman 
42e9dcd831SSlava Shwartsman static LIST_HEAD(mlx5_fpga_devices);
43e9dcd831SSlava Shwartsman static LIST_HEAD(mlx5_fpga_clients);
44e9dcd831SSlava Shwartsman /* protects access between client un/registration and device add/remove calls */
45e9dcd831SSlava Shwartsman static DEFINE_MUTEX(mlx5_fpga_mutex);
46e9dcd831SSlava Shwartsman 
47e9dcd831SSlava Shwartsman static const char *const mlx5_fpga_error_strings[] = {
48e9dcd831SSlava Shwartsman 	"Null Syndrome",
49e9dcd831SSlava Shwartsman 	"Corrupted DDR",
50e9dcd831SSlava Shwartsman 	"Flash Timeout",
51e9dcd831SSlava Shwartsman 	"Internal Link Error",
52e9dcd831SSlava Shwartsman 	"Watchdog HW Failure",
53e9dcd831SSlava Shwartsman 	"I2C Failure",
54e9dcd831SSlava Shwartsman 	"Image Changed",
55e9dcd831SSlava Shwartsman 	"Temperature Critical",
56e9dcd831SSlava Shwartsman };
57e9dcd831SSlava Shwartsman 
58e9dcd831SSlava Shwartsman static const char * const mlx5_fpga_qp_error_strings[] = {
59e9dcd831SSlava Shwartsman 	"Null Syndrome",
60e9dcd831SSlava Shwartsman 	"Retry Counter Expired",
61e9dcd831SSlava Shwartsman 	"RNR Expired",
62e9dcd831SSlava Shwartsman };
63e9dcd831SSlava Shwartsman 
client_context_destroy(struct mlx5_fpga_device * fdev,struct mlx5_fpga_client_data * context)64e9dcd831SSlava Shwartsman static void client_context_destroy(struct mlx5_fpga_device *fdev,
65e9dcd831SSlava Shwartsman 				   struct mlx5_fpga_client_data *context)
66e9dcd831SSlava Shwartsman {
67e9dcd831SSlava Shwartsman 	mlx5_fpga_dbg(fdev, "Deleting client context %p of client %p\n",
68e9dcd831SSlava Shwartsman 		      context, context->client);
69e9dcd831SSlava Shwartsman 	if (context->client->destroy)
70e9dcd831SSlava Shwartsman 		context->client->destroy(fdev);
71e9dcd831SSlava Shwartsman 	list_del(&context->list);
72e9dcd831SSlava Shwartsman 	kfree(context);
73e9dcd831SSlava Shwartsman }
74e9dcd831SSlava Shwartsman 
client_context_create(struct mlx5_fpga_device * fdev,struct mlx5_fpga_client * client,struct mlx5_fpga_client_data ** pctx)75e9dcd831SSlava Shwartsman static int client_context_create(struct mlx5_fpga_device *fdev,
76e9dcd831SSlava Shwartsman 				 struct mlx5_fpga_client *client,
77e9dcd831SSlava Shwartsman 				 struct mlx5_fpga_client_data **pctx)
78e9dcd831SSlava Shwartsman {
79e9dcd831SSlava Shwartsman 	struct mlx5_fpga_client_data *context;
80e9dcd831SSlava Shwartsman 
81e9dcd831SSlava Shwartsman 	context = kmalloc(sizeof(*context), GFP_KERNEL);
82e9dcd831SSlava Shwartsman 	if (!context)
83e9dcd831SSlava Shwartsman 		return -ENOMEM;
84e9dcd831SSlava Shwartsman 
85e9dcd831SSlava Shwartsman 	context->client = client;
86e9dcd831SSlava Shwartsman 	context->data = NULL;
87e9dcd831SSlava Shwartsman 	context->added  = false;
88e9dcd831SSlava Shwartsman 	list_add(&context->list, &fdev->client_data_list);
89e9dcd831SSlava Shwartsman 
90e9dcd831SSlava Shwartsman 	mlx5_fpga_dbg(fdev, "Adding client context %p client %p\n",
91e9dcd831SSlava Shwartsman 		      context, client);
92e9dcd831SSlava Shwartsman 
93e9dcd831SSlava Shwartsman 	if (client->create)
94e9dcd831SSlava Shwartsman 		client->create(fdev);
95e9dcd831SSlava Shwartsman 
96e9dcd831SSlava Shwartsman 	if (pctx)
97e9dcd831SSlava Shwartsman 		*pctx = context;
98e9dcd831SSlava Shwartsman 	return 0;
99e9dcd831SSlava Shwartsman }
100e9dcd831SSlava Shwartsman 
mlx5_fpga_device_alloc(void)101e9dcd831SSlava Shwartsman static struct mlx5_fpga_device *mlx5_fpga_device_alloc(void)
102e9dcd831SSlava Shwartsman {
103e9dcd831SSlava Shwartsman 	struct mlx5_fpga_device *fdev = NULL;
104e9dcd831SSlava Shwartsman 
105e9dcd831SSlava Shwartsman 	fdev = kzalloc(sizeof(*fdev), GFP_KERNEL);
106e9dcd831SSlava Shwartsman 	if (!fdev)
107e9dcd831SSlava Shwartsman 		return NULL;
108e9dcd831SSlava Shwartsman 
109e9dcd831SSlava Shwartsman 	spin_lock_init(&fdev->state_lock);
110e9dcd831SSlava Shwartsman 	init_completion(&fdev->load_event);
111e9dcd831SSlava Shwartsman 	fdev->fdev_state = MLX5_FDEV_STATE_NONE;
112e9dcd831SSlava Shwartsman 	INIT_LIST_HEAD(&fdev->client_data_list);
113e9dcd831SSlava Shwartsman 	return fdev;
114e9dcd831SSlava Shwartsman }
115e9dcd831SSlava Shwartsman 
mlx5_fpga_image_name(enum mlx5_fpga_image image)116e9dcd831SSlava Shwartsman static const char *mlx5_fpga_image_name(enum mlx5_fpga_image image)
117e9dcd831SSlava Shwartsman {
118e9dcd831SSlava Shwartsman 	switch (image) {
119e9dcd831SSlava Shwartsman 	case MLX5_FPGA_IMAGE_USER:
120e9dcd831SSlava Shwartsman 		return "user";
121e9dcd831SSlava Shwartsman 	case MLX5_FPGA_IMAGE_FACTORY:
122e9dcd831SSlava Shwartsman 		return "factory";
123e9dcd831SSlava Shwartsman 	default:
124e9dcd831SSlava Shwartsman 		return "unknown";
125e9dcd831SSlava Shwartsman 	}
126e9dcd831SSlava Shwartsman }
127e9dcd831SSlava Shwartsman 
mlx5_fpga_name(u32 fpga_id)128e9dcd831SSlava Shwartsman static const char *mlx5_fpga_name(u32 fpga_id)
129e9dcd831SSlava Shwartsman {
130e9dcd831SSlava Shwartsman 	static char ret[32];
131e9dcd831SSlava Shwartsman 
132e9dcd831SSlava Shwartsman 	switch (fpga_id) {
133e9dcd831SSlava Shwartsman 	case MLX5_FPGA_NEWTON:
134e9dcd831SSlava Shwartsman 		return "Newton";
135e9dcd831SSlava Shwartsman 	case MLX5_FPGA_EDISON:
136e9dcd831SSlava Shwartsman 		return "Edison";
137e9dcd831SSlava Shwartsman 	case MLX5_FPGA_MORSE:
138e9dcd831SSlava Shwartsman 		return "Morse";
139*b5f57512SSlava Shwartsman 	case MLX5_FPGA_MORSEQ:
140*b5f57512SSlava Shwartsman 		return "MorseQ";
141e9dcd831SSlava Shwartsman 	}
142e9dcd831SSlava Shwartsman 
143e9dcd831SSlava Shwartsman 	snprintf(ret, sizeof(ret), "Unknown %d", fpga_id);
144e9dcd831SSlava Shwartsman 	return ret;
145e9dcd831SSlava Shwartsman }
146e9dcd831SSlava Shwartsman 
mlx5_fpga_device_load_check(struct mlx5_fpga_device * fdev)147e9dcd831SSlava Shwartsman static int mlx5_fpga_device_load_check(struct mlx5_fpga_device *fdev)
148e9dcd831SSlava Shwartsman {
149e9dcd831SSlava Shwartsman 	struct mlx5_fpga_query query;
150e9dcd831SSlava Shwartsman 	int err;
151*b5f57512SSlava Shwartsman 	u32 fpga_id;
152e9dcd831SSlava Shwartsman 
153e9dcd831SSlava Shwartsman 	err = mlx5_fpga_query(fdev->mdev, &query);
154e9dcd831SSlava Shwartsman 	if (err) {
155e9dcd831SSlava Shwartsman 		mlx5_fpga_err(fdev, "Failed to query status: %d\n", err);
156e9dcd831SSlava Shwartsman 		return err;
157e9dcd831SSlava Shwartsman 	}
158e9dcd831SSlava Shwartsman 
159e9dcd831SSlava Shwartsman 	fdev->last_admin_image = query.admin_image;
160e9dcd831SSlava Shwartsman 	fdev->last_oper_image = query.oper_image;
161e9dcd831SSlava Shwartsman 	fdev->image_status = query.image_status;
162e9dcd831SSlava Shwartsman 
163e9dcd831SSlava Shwartsman 	mlx5_fpga_info(fdev, "Status %u; Admin image %u; Oper image %u\n",
164e9dcd831SSlava Shwartsman 		      query.image_status, query.admin_image, query.oper_image);
165e9dcd831SSlava Shwartsman 
166*b5f57512SSlava Shwartsman 	/* For Morse projects FPGA has no influence to network functionality */
167*b5f57512SSlava Shwartsman 	fpga_id = MLX5_CAP_FPGA(fdev->mdev, fpga_id);
168*b5f57512SSlava Shwartsman 	if (fpga_id == MLX5_FPGA_MORSE || fpga_id == MLX5_FPGA_MORSEQ)
169e9dcd831SSlava Shwartsman 		return 0;
170e9dcd831SSlava Shwartsman 
171e9dcd831SSlava Shwartsman 	if (query.image_status != MLX5_FPGA_STATUS_SUCCESS) {
172e9dcd831SSlava Shwartsman 		mlx5_fpga_err(fdev, "%s image failed to load; status %u\n",
173e9dcd831SSlava Shwartsman 			      mlx5_fpga_image_name(fdev->last_oper_image),
174e9dcd831SSlava Shwartsman 			      query.image_status);
175e9dcd831SSlava Shwartsman 		return -EIO;
176e9dcd831SSlava Shwartsman 	}
177e9dcd831SSlava Shwartsman 
178e9dcd831SSlava Shwartsman 	return 0;
179e9dcd831SSlava Shwartsman }
180e9dcd831SSlava Shwartsman 
mlx5_fpga_device_brb(struct mlx5_fpga_device * fdev)181e9dcd831SSlava Shwartsman static int mlx5_fpga_device_brb(struct mlx5_fpga_device *fdev)
182e9dcd831SSlava Shwartsman {
183e9dcd831SSlava Shwartsman 	int err;
184e9dcd831SSlava Shwartsman 	struct mlx5_core_dev *mdev = fdev->mdev;
185e9dcd831SSlava Shwartsman 
186e9dcd831SSlava Shwartsman 	err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_SANDBOX_BYPASS_ON);
187e9dcd831SSlava Shwartsman 	if (err) {
188e9dcd831SSlava Shwartsman 		mlx5_fpga_err(fdev, "Failed to set bypass on: %d\n", err);
189e9dcd831SSlava Shwartsman 		return err;
190e9dcd831SSlava Shwartsman 	}
191e9dcd831SSlava Shwartsman 	err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_RESET_SANDBOX);
192e9dcd831SSlava Shwartsman 	if (err) {
193e9dcd831SSlava Shwartsman 		mlx5_fpga_err(fdev, "Failed to reset SBU: %d\n", err);
194e9dcd831SSlava Shwartsman 		return err;
195e9dcd831SSlava Shwartsman 	}
196e9dcd831SSlava Shwartsman 	err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_SANDBOX_BYPASS_OFF);
197e9dcd831SSlava Shwartsman 	if (err) {
198e9dcd831SSlava Shwartsman 		mlx5_fpga_err(fdev, "Failed to set bypass off: %d\n", err);
199e9dcd831SSlava Shwartsman 		return err;
200e9dcd831SSlava Shwartsman 	}
201e9dcd831SSlava Shwartsman 	return 0;
202e9dcd831SSlava Shwartsman }
203e9dcd831SSlava Shwartsman 
mlx5_fpga_device_start(struct mlx5_core_dev * mdev)204e9dcd831SSlava Shwartsman int mlx5_fpga_device_start(struct mlx5_core_dev *mdev)
205e9dcd831SSlava Shwartsman {
206e9dcd831SSlava Shwartsman 	struct mlx5_fpga_client_data *client_context;
207e9dcd831SSlava Shwartsman 	struct mlx5_fpga_device *fdev = mdev->fpga;
208e9dcd831SSlava Shwartsman 	struct mlx5_fpga_conn_attr conn_attr = {0};
209e9dcd831SSlava Shwartsman 	struct mlx5_fpga_conn *conn;
210e9dcd831SSlava Shwartsman 	unsigned int max_num_qps;
211e9dcd831SSlava Shwartsman 	unsigned long flags;
212e9dcd831SSlava Shwartsman 	u32 fpga_id;
213e9dcd831SSlava Shwartsman 	u32 vid;
214e9dcd831SSlava Shwartsman 	u16 pid;
215e9dcd831SSlava Shwartsman 	int err;
216e9dcd831SSlava Shwartsman 
217e9dcd831SSlava Shwartsman 	if (!fdev)
218e9dcd831SSlava Shwartsman 		return 0;
219e9dcd831SSlava Shwartsman 
220e9dcd831SSlava Shwartsman 	err = mlx5_fpga_caps(fdev->mdev);
221e9dcd831SSlava Shwartsman 	if (err)
222e9dcd831SSlava Shwartsman 		goto out;
223e9dcd831SSlava Shwartsman 
224e9dcd831SSlava Shwartsman 	err = mlx5_fpga_device_load_check(fdev);
225e9dcd831SSlava Shwartsman 	if (err)
226e9dcd831SSlava Shwartsman 		goto out;
227e9dcd831SSlava Shwartsman 
228e9dcd831SSlava Shwartsman 	fpga_id = MLX5_CAP_FPGA(fdev->mdev, fpga_id);
229e9dcd831SSlava Shwartsman 	mlx5_fpga_info(fdev, "FPGA card %s\n", mlx5_fpga_name(fpga_id));
230e9dcd831SSlava Shwartsman 
231*b5f57512SSlava Shwartsman 	if (fpga_id == MLX5_FPGA_MORSE || fpga_id == MLX5_FPGA_MORSEQ)
232e9dcd831SSlava Shwartsman 		goto out;
233e9dcd831SSlava Shwartsman 
234e9dcd831SSlava Shwartsman 	mlx5_fpga_info(fdev, "%s(%d) image, version %u; SBU %06x:%04x version %d\n",
235e9dcd831SSlava Shwartsman 		       mlx5_fpga_image_name(fdev->last_oper_image),
236e9dcd831SSlava Shwartsman 		       fdev->last_oper_image,
237e9dcd831SSlava Shwartsman 		       MLX5_CAP_FPGA(fdev->mdev, image_version),
238e9dcd831SSlava Shwartsman 		       MLX5_CAP_FPGA(fdev->mdev, ieee_vendor_id),
239e9dcd831SSlava Shwartsman 		       MLX5_CAP_FPGA(fdev->mdev, sandbox_product_id),
240e9dcd831SSlava Shwartsman 		       MLX5_CAP_FPGA(fdev->mdev, sandbox_product_version));
241e9dcd831SSlava Shwartsman 
242e9dcd831SSlava Shwartsman 	max_num_qps = MLX5_CAP_FPGA(mdev, shell_caps.max_num_qps);
243e9dcd831SSlava Shwartsman 	err = mlx5_core_reserve_gids(mdev, max_num_qps);
244e9dcd831SSlava Shwartsman 	if (err)
245e9dcd831SSlava Shwartsman 		goto out;
246e9dcd831SSlava Shwartsman 
247e9dcd831SSlava Shwartsman #ifdef NOT_YET
248e9dcd831SSlava Shwartsman 	/* XXXKIB */
249e9dcd831SSlava Shwartsman 	err = mlx5_fpga_conn_device_init(fdev);
250e9dcd831SSlava Shwartsman #else
251e9dcd831SSlava Shwartsman 	err = 0;
252e9dcd831SSlava Shwartsman #endif
253e9dcd831SSlava Shwartsman 	if (err)
254e9dcd831SSlava Shwartsman 		goto err_rsvd_gid;
255e9dcd831SSlava Shwartsman 
256e9dcd831SSlava Shwartsman 	err = mlx5_fpga_trans_device_init(fdev);
257e9dcd831SSlava Shwartsman 	if (err) {
258e9dcd831SSlava Shwartsman 		mlx5_fpga_err(fdev, "Failed to init transaction: %d\n",
259e9dcd831SSlava Shwartsman 			      err);
260e9dcd831SSlava Shwartsman 		goto err_conn_init;
261e9dcd831SSlava Shwartsman 	}
262e9dcd831SSlava Shwartsman 
263e9dcd831SSlava Shwartsman 	conn_attr.tx_size = MLX5_FPGA_TID_COUNT;
264e9dcd831SSlava Shwartsman 	conn_attr.rx_size = MLX5_FPGA_TID_COUNT;
265e9dcd831SSlava Shwartsman 	conn_attr.recv_cb = mlx5_fpga_trans_recv;
266e9dcd831SSlava Shwartsman 	conn_attr.cb_arg = fdev;
267e9dcd831SSlava Shwartsman #ifdef NOT_YET
268e9dcd831SSlava Shwartsman 	/* XXXKIB */
269e9dcd831SSlava Shwartsman 	conn = mlx5_fpga_conn_create(fdev, &conn_attr,
270e9dcd831SSlava Shwartsman 				     MLX5_FPGA_QPC_QP_TYPE_SHELL_QP);
271e9dcd831SSlava Shwartsman 	if (IS_ERR(conn)) {
272e9dcd831SSlava Shwartsman 		err = PTR_ERR(conn);
273e9dcd831SSlava Shwartsman 		mlx5_fpga_err(fdev, "Failed to create shell conn: %d\n", err);
274e9dcd831SSlava Shwartsman 		goto err_trans;
275e9dcd831SSlava Shwartsman 	}
276e9dcd831SSlava Shwartsman #else
277e9dcd831SSlava Shwartsman 	conn = NULL;
278e9dcd831SSlava Shwartsman #endif
279e9dcd831SSlava Shwartsman 	fdev->shell_conn = conn;
280e9dcd831SSlava Shwartsman 
281e9dcd831SSlava Shwartsman 	if (fdev->last_oper_image == MLX5_FPGA_IMAGE_USER) {
282e9dcd831SSlava Shwartsman 		err = mlx5_fpga_device_brb(fdev);
283e9dcd831SSlava Shwartsman 		if (err)
284e9dcd831SSlava Shwartsman 			goto err_shell_conn;
285e9dcd831SSlava Shwartsman 
286e9dcd831SSlava Shwartsman 		vid = MLX5_CAP_FPGA(fdev->mdev, ieee_vendor_id);
287e9dcd831SSlava Shwartsman 		pid = MLX5_CAP_FPGA(fdev->mdev, sandbox_product_id);
288e9dcd831SSlava Shwartsman 		mutex_lock(&mlx5_fpga_mutex);
289e9dcd831SSlava Shwartsman 		list_for_each_entry(client_context, &fdev->client_data_list,
290e9dcd831SSlava Shwartsman 				    list) {
291e9dcd831SSlava Shwartsman 			if (client_context->client->add(fdev, vid, pid))
292e9dcd831SSlava Shwartsman 				continue;
293e9dcd831SSlava Shwartsman 			client_context->added = true;
294e9dcd831SSlava Shwartsman 		}
295e9dcd831SSlava Shwartsman 		mutex_unlock(&mlx5_fpga_mutex);
296e9dcd831SSlava Shwartsman 	}
297e9dcd831SSlava Shwartsman 
298e9dcd831SSlava Shwartsman 	goto out;
299e9dcd831SSlava Shwartsman 
300e9dcd831SSlava Shwartsman err_shell_conn:
301e9dcd831SSlava Shwartsman 	if (fdev->shell_conn) {
302e9dcd831SSlava Shwartsman #ifdef NOT_YET
303e9dcd831SSlava Shwartsman 		/* XXXKIB */
304e9dcd831SSlava Shwartsman 		mlx5_fpga_conn_destroy(fdev->shell_conn);
305e9dcd831SSlava Shwartsman #endif
306e9dcd831SSlava Shwartsman 		fdev->shell_conn = NULL;
307e9dcd831SSlava Shwartsman 	}
308e9dcd831SSlava Shwartsman 
309e9dcd831SSlava Shwartsman #ifdef NOT_YET
310e9dcd831SSlava Shwartsman 		/* XXXKIB */
311e9dcd831SSlava Shwartsman err_trans:
312e9dcd831SSlava Shwartsman #endif
313e9dcd831SSlava Shwartsman 	mlx5_fpga_trans_device_cleanup(fdev);
314e9dcd831SSlava Shwartsman 
315e9dcd831SSlava Shwartsman err_conn_init:
316e9dcd831SSlava Shwartsman #ifdef NOT_YET
317e9dcd831SSlava Shwartsman 	/* XXXKIB */
318e9dcd831SSlava Shwartsman 	mlx5_fpga_conn_device_cleanup(fdev);
319e9dcd831SSlava Shwartsman #endif
320e9dcd831SSlava Shwartsman 
321e9dcd831SSlava Shwartsman err_rsvd_gid:
322e9dcd831SSlava Shwartsman 	mlx5_core_unreserve_gids(mdev, max_num_qps);
323e9dcd831SSlava Shwartsman out:
324e9dcd831SSlava Shwartsman 	spin_lock_irqsave(&fdev->state_lock, flags);
325e9dcd831SSlava Shwartsman 	fdev->fdev_state = err ? MLX5_FDEV_STATE_FAILURE : MLX5_FDEV_STATE_SUCCESS;
326e9dcd831SSlava Shwartsman 	spin_unlock_irqrestore(&fdev->state_lock, flags);
327e9dcd831SSlava Shwartsman 	return err;
328e9dcd831SSlava Shwartsman }
329e9dcd831SSlava Shwartsman 
mlx5_fpga_init(struct mlx5_core_dev * mdev)330e9dcd831SSlava Shwartsman int mlx5_fpga_init(struct mlx5_core_dev *mdev)
331e9dcd831SSlava Shwartsman {
332e9dcd831SSlava Shwartsman 	struct mlx5_fpga_device *fdev = NULL;
333e9dcd831SSlava Shwartsman 	struct mlx5_fpga_client *client;
334e9dcd831SSlava Shwartsman 
335e9dcd831SSlava Shwartsman 	if (!MLX5_CAP_GEN(mdev, fpga)) {
336e9dcd831SSlava Shwartsman 		mlx5_core_dbg(mdev, "FPGA capability not present\n");
337e9dcd831SSlava Shwartsman 		return 0;
338e9dcd831SSlava Shwartsman 	}
339e9dcd831SSlava Shwartsman 
340e9dcd831SSlava Shwartsman 	mlx5_core_dbg(mdev, "Initializing FPGA\n");
341e9dcd831SSlava Shwartsman 
342e9dcd831SSlava Shwartsman 	fdev = mlx5_fpga_device_alloc();
343e9dcd831SSlava Shwartsman 	if (!fdev)
344e9dcd831SSlava Shwartsman 		return -ENOMEM;
345e9dcd831SSlava Shwartsman 
346e9dcd831SSlava Shwartsman 	fdev->mdev = mdev;
347e9dcd831SSlava Shwartsman 	mdev->fpga = fdev;
348e9dcd831SSlava Shwartsman 
349e9dcd831SSlava Shwartsman 	mutex_lock(&mlx5_fpga_mutex);
350e9dcd831SSlava Shwartsman 
351e9dcd831SSlava Shwartsman 	list_add_tail(&fdev->list, &mlx5_fpga_devices);
352e9dcd831SSlava Shwartsman 	list_for_each_entry(client, &mlx5_fpga_clients, list)
353e9dcd831SSlava Shwartsman 		client_context_create(fdev, client, NULL);
354e9dcd831SSlava Shwartsman 
355e9dcd831SSlava Shwartsman 	mutex_unlock(&mlx5_fpga_mutex);
356e9dcd831SSlava Shwartsman 	return 0;
357e9dcd831SSlava Shwartsman }
358e9dcd831SSlava Shwartsman 
mlx5_fpga_device_stop(struct mlx5_core_dev * mdev)359e9dcd831SSlava Shwartsman void mlx5_fpga_device_stop(struct mlx5_core_dev *mdev)
360e9dcd831SSlava Shwartsman {
361e9dcd831SSlava Shwartsman 	struct mlx5_fpga_client_data *client_context;
362e9dcd831SSlava Shwartsman 	struct mlx5_fpga_device *fdev = mdev->fpga;
363e9dcd831SSlava Shwartsman 	unsigned int max_num_qps;
364e9dcd831SSlava Shwartsman 	unsigned long flags;
365e9dcd831SSlava Shwartsman 	int err;
366*b5f57512SSlava Shwartsman 	u32 fpga_id;
367e9dcd831SSlava Shwartsman 
368e9dcd831SSlava Shwartsman 	if (!fdev)
369e9dcd831SSlava Shwartsman 		return;
370e9dcd831SSlava Shwartsman 
371*b5f57512SSlava Shwartsman 	fpga_id = MLX5_CAP_FPGA(mdev, fpga_id);
372*b5f57512SSlava Shwartsman 	if (fpga_id == MLX5_FPGA_MORSE || fpga_id == MLX5_FPGA_MORSEQ)
373e9dcd831SSlava Shwartsman 		return;
374e9dcd831SSlava Shwartsman 
375*b5f57512SSlava Shwartsman 	spin_lock_irqsave(&fdev->state_lock, flags);
376*b5f57512SSlava Shwartsman 
377e9dcd831SSlava Shwartsman 	if (fdev->fdev_state != MLX5_FDEV_STATE_SUCCESS) {
378e9dcd831SSlava Shwartsman 		spin_unlock_irqrestore(&fdev->state_lock, flags);
379e9dcd831SSlava Shwartsman 		return;
380e9dcd831SSlava Shwartsman 	}
381e9dcd831SSlava Shwartsman 	fdev->fdev_state = MLX5_FDEV_STATE_NONE;
382e9dcd831SSlava Shwartsman 	spin_unlock_irqrestore(&fdev->state_lock, flags);
383e9dcd831SSlava Shwartsman 
384e9dcd831SSlava Shwartsman 	if (fdev->last_oper_image == MLX5_FPGA_IMAGE_USER) {
385e9dcd831SSlava Shwartsman 		err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_SANDBOX_BYPASS_ON);
386e9dcd831SSlava Shwartsman 		if (err)
387e9dcd831SSlava Shwartsman 			mlx5_fpga_err(fdev, "Failed to re-set SBU bypass on: %d\n",
388e9dcd831SSlava Shwartsman 				      err);
389e9dcd831SSlava Shwartsman 	}
390e9dcd831SSlava Shwartsman 
391e9dcd831SSlava Shwartsman 	mutex_lock(&mlx5_fpga_mutex);
392e9dcd831SSlava Shwartsman 	list_for_each_entry(client_context, &fdev->client_data_list, list) {
393e9dcd831SSlava Shwartsman 		if (!client_context->added)
394e9dcd831SSlava Shwartsman 			continue;
395e9dcd831SSlava Shwartsman 		client_context->client->remove(fdev);
396e9dcd831SSlava Shwartsman 		client_context->added = false;
397e9dcd831SSlava Shwartsman 	}
398e9dcd831SSlava Shwartsman 	mutex_unlock(&mlx5_fpga_mutex);
399e9dcd831SSlava Shwartsman 
400e9dcd831SSlava Shwartsman 	if (fdev->shell_conn) {
401e9dcd831SSlava Shwartsman #ifdef NOT_YET
402e9dcd831SSlava Shwartsman 		/* XXXKIB */
403e9dcd831SSlava Shwartsman 		mlx5_fpga_conn_destroy(fdev->shell_conn);
404e9dcd831SSlava Shwartsman #endif
405e9dcd831SSlava Shwartsman 		fdev->shell_conn = NULL;
406e9dcd831SSlava Shwartsman 		mlx5_fpga_trans_device_cleanup(fdev);
407e9dcd831SSlava Shwartsman 	}
408e9dcd831SSlava Shwartsman #ifdef NOT_YET
409e9dcd831SSlava Shwartsman 	/* XXXKIB */
410e9dcd831SSlava Shwartsman 	mlx5_fpga_conn_device_cleanup(fdev);
411e9dcd831SSlava Shwartsman #endif
412e9dcd831SSlava Shwartsman 	max_num_qps = MLX5_CAP_FPGA(mdev, shell_caps.max_num_qps);
413e9dcd831SSlava Shwartsman 	mlx5_core_unreserve_gids(mdev, max_num_qps);
414e9dcd831SSlava Shwartsman }
415e9dcd831SSlava Shwartsman 
mlx5_fpga_cleanup(struct mlx5_core_dev * mdev)416e9dcd831SSlava Shwartsman void mlx5_fpga_cleanup(struct mlx5_core_dev *mdev)
417e9dcd831SSlava Shwartsman {
418e9dcd831SSlava Shwartsman 	struct mlx5_fpga_client_data *context, *tmp;
419e9dcd831SSlava Shwartsman 	struct mlx5_fpga_device *fdev = mdev->fpga;
420e9dcd831SSlava Shwartsman 
421e9dcd831SSlava Shwartsman 	if (!fdev)
422e9dcd831SSlava Shwartsman 		return;
423e9dcd831SSlava Shwartsman 
424e9dcd831SSlava Shwartsman 	mutex_lock(&mlx5_fpga_mutex);
425e9dcd831SSlava Shwartsman 
426e9dcd831SSlava Shwartsman 	mlx5_fpga_device_stop(mdev);
427e9dcd831SSlava Shwartsman 
428e9dcd831SSlava Shwartsman 	list_for_each_entry_safe(context, tmp, &fdev->client_data_list, list)
429e9dcd831SSlava Shwartsman 		client_context_destroy(fdev, context);
430e9dcd831SSlava Shwartsman 
431e9dcd831SSlava Shwartsman 	list_del(&fdev->list);
432e9dcd831SSlava Shwartsman 	kfree(fdev);
433e9dcd831SSlava Shwartsman 	mdev->fpga = NULL;
434e9dcd831SSlava Shwartsman 
435e9dcd831SSlava Shwartsman 	mutex_unlock(&mlx5_fpga_mutex);
436e9dcd831SSlava Shwartsman }
437e9dcd831SSlava Shwartsman 
mlx5_fpga_syndrome_to_string(u8 syndrome)438e9dcd831SSlava Shwartsman static const char *mlx5_fpga_syndrome_to_string(u8 syndrome)
439e9dcd831SSlava Shwartsman {
440e9dcd831SSlava Shwartsman 	if (syndrome < ARRAY_SIZE(mlx5_fpga_error_strings))
441e9dcd831SSlava Shwartsman 		return mlx5_fpga_error_strings[syndrome];
442e9dcd831SSlava Shwartsman 	return "Unknown";
443e9dcd831SSlava Shwartsman }
444e9dcd831SSlava Shwartsman 
mlx5_fpga_qp_syndrome_to_string(u8 syndrome)445e9dcd831SSlava Shwartsman static const char *mlx5_fpga_qp_syndrome_to_string(u8 syndrome)
446e9dcd831SSlava Shwartsman {
447e9dcd831SSlava Shwartsman 	if (syndrome < ARRAY_SIZE(mlx5_fpga_qp_error_strings))
448e9dcd831SSlava Shwartsman 		return mlx5_fpga_qp_error_strings[syndrome];
449e9dcd831SSlava Shwartsman 	return "Unknown";
450e9dcd831SSlava Shwartsman }
451e9dcd831SSlava Shwartsman 
mlx5_fpga_event(struct mlx5_core_dev * mdev,u8 event,void * data)452e9dcd831SSlava Shwartsman void mlx5_fpga_event(struct mlx5_core_dev *mdev, u8 event, void *data)
453e9dcd831SSlava Shwartsman {
454e9dcd831SSlava Shwartsman 	struct mlx5_fpga_device *fdev = mdev->fpga;
455e9dcd831SSlava Shwartsman 	const char *event_name;
456e9dcd831SSlava Shwartsman 	bool teardown = false;
457e9dcd831SSlava Shwartsman 	unsigned long flags;
458e9dcd831SSlava Shwartsman 	u32 fpga_qpn;
459e9dcd831SSlava Shwartsman 	u8 syndrome;
460e9dcd831SSlava Shwartsman 
461e9dcd831SSlava Shwartsman 	switch (event) {
462e9dcd831SSlava Shwartsman 	case MLX5_EVENT_TYPE_FPGA_ERROR:
463e9dcd831SSlava Shwartsman 		syndrome = MLX5_GET(fpga_error_event, data, syndrome);
464e9dcd831SSlava Shwartsman 		event_name = mlx5_fpga_syndrome_to_string(syndrome);
465e9dcd831SSlava Shwartsman 		break;
466e9dcd831SSlava Shwartsman 	case MLX5_EVENT_TYPE_FPGA_QP_ERROR:
467e9dcd831SSlava Shwartsman 		syndrome = MLX5_GET(fpga_qp_error_event, data, syndrome);
468e9dcd831SSlava Shwartsman 		event_name = mlx5_fpga_qp_syndrome_to_string(syndrome);
469e9dcd831SSlava Shwartsman 		fpga_qpn = MLX5_GET(fpga_qp_error_event, data, fpga_qpn);
470e9dcd831SSlava Shwartsman 		mlx5_fpga_err(fdev, "Error %u on QP %u: %s\n",
471e9dcd831SSlava Shwartsman 			      syndrome, fpga_qpn, event_name);
472e9dcd831SSlava Shwartsman 		break;
473e9dcd831SSlava Shwartsman 	default:
474e9dcd831SSlava Shwartsman 		mlx5_fpga_warn_ratelimited(fdev, "Unexpected event %u\n",
475e9dcd831SSlava Shwartsman 					   event);
476e9dcd831SSlava Shwartsman 		return;
477e9dcd831SSlava Shwartsman 	}
478e9dcd831SSlava Shwartsman 
479e9dcd831SSlava Shwartsman 	spin_lock_irqsave(&fdev->state_lock, flags);
480e9dcd831SSlava Shwartsman 	switch (fdev->fdev_state) {
481e9dcd831SSlava Shwartsman 	case MLX5_FDEV_STATE_SUCCESS:
482e9dcd831SSlava Shwartsman 		mlx5_fpga_warn(fdev, "Error %u: %s\n", syndrome, event_name);
483e9dcd831SSlava Shwartsman 		teardown = true;
484e9dcd831SSlava Shwartsman 		break;
485e9dcd831SSlava Shwartsman 	case MLX5_FDEV_STATE_IN_PROGRESS:
486e9dcd831SSlava Shwartsman 		if (syndrome != MLX5_FPGA_ERROR_EVENT_SYNDROME_IMAGE_CHANGED)
487e9dcd831SSlava Shwartsman 			mlx5_fpga_warn(fdev, "Error while loading %u: %s\n",
488e9dcd831SSlava Shwartsman 				       syndrome, event_name);
489e9dcd831SSlava Shwartsman 		complete(&fdev->load_event);
490e9dcd831SSlava Shwartsman 		break;
491e9dcd831SSlava Shwartsman 	default:
492e9dcd831SSlava Shwartsman 		mlx5_fpga_warn_ratelimited(fdev, "Unexpected error event %u: %s\n",
493e9dcd831SSlava Shwartsman 					   syndrome, event_name);
494e9dcd831SSlava Shwartsman 	}
495e9dcd831SSlava Shwartsman 	spin_unlock_irqrestore(&fdev->state_lock, flags);
496e9dcd831SSlava Shwartsman 	/* We tear-down the card's interfaces and functionality because
497e9dcd831SSlava Shwartsman 	 * the FPGA bump-on-the-wire is misbehaving and we lose ability
498e9dcd831SSlava Shwartsman 	 * to communicate with the network. User may still be able to
499e9dcd831SSlava Shwartsman 	 * recover by re-programming or debugging the FPGA
500e9dcd831SSlava Shwartsman 	 */
501e9dcd831SSlava Shwartsman 	if (teardown)
502e9dcd831SSlava Shwartsman 		mlx5_trigger_health_work(fdev->mdev);
503e9dcd831SSlava Shwartsman }
504e9dcd831SSlava Shwartsman 
mlx5_fpga_client_register(struct mlx5_fpga_client * client)505e9dcd831SSlava Shwartsman void mlx5_fpga_client_register(struct mlx5_fpga_client *client)
506e9dcd831SSlava Shwartsman {
507e9dcd831SSlava Shwartsman 	struct mlx5_fpga_client_data *context;
508e9dcd831SSlava Shwartsman 	struct mlx5_fpga_device *fdev;
509e9dcd831SSlava Shwartsman 	bool call_add = false;
510e9dcd831SSlava Shwartsman 	unsigned long flags;
511e9dcd831SSlava Shwartsman 	u32 vid;
512e9dcd831SSlava Shwartsman 	u16 pid;
513e9dcd831SSlava Shwartsman 	int err;
514e9dcd831SSlava Shwartsman 
515e9dcd831SSlava Shwartsman 	pr_debug("Client register %s\n", client->name);
516e9dcd831SSlava Shwartsman 
517e9dcd831SSlava Shwartsman 	mutex_lock(&mlx5_fpga_mutex);
518e9dcd831SSlava Shwartsman 
519e9dcd831SSlava Shwartsman 	list_add_tail(&client->list, &mlx5_fpga_clients);
520e9dcd831SSlava Shwartsman 
521e9dcd831SSlava Shwartsman 	list_for_each_entry(fdev, &mlx5_fpga_devices, list) {
522e9dcd831SSlava Shwartsman 		err = client_context_create(fdev, client, &context);
523e9dcd831SSlava Shwartsman 		if (err)
524e9dcd831SSlava Shwartsman 			continue;
525e9dcd831SSlava Shwartsman 
526e9dcd831SSlava Shwartsman 		spin_lock_irqsave(&fdev->state_lock, flags);
527e9dcd831SSlava Shwartsman 		call_add = (fdev->fdev_state == MLX5_FDEV_STATE_SUCCESS);
528e9dcd831SSlava Shwartsman 		spin_unlock_irqrestore(&fdev->state_lock, flags);
529e9dcd831SSlava Shwartsman 
530e9dcd831SSlava Shwartsman 		if (call_add) {
531e9dcd831SSlava Shwartsman 			vid = MLX5_CAP_FPGA(fdev->mdev, ieee_vendor_id);
532e9dcd831SSlava Shwartsman 			pid = MLX5_CAP_FPGA(fdev->mdev, sandbox_product_id);
533e9dcd831SSlava Shwartsman 			if (!client->add(fdev, vid, pid))
534e9dcd831SSlava Shwartsman 				context->added = true;
535e9dcd831SSlava Shwartsman 		}
536e9dcd831SSlava Shwartsman 	}
537e9dcd831SSlava Shwartsman 
538e9dcd831SSlava Shwartsman 	mutex_unlock(&mlx5_fpga_mutex);
539e9dcd831SSlava Shwartsman }
540e9dcd831SSlava Shwartsman EXPORT_SYMBOL(mlx5_fpga_client_register);
541e9dcd831SSlava Shwartsman 
mlx5_fpga_client_unregister(struct mlx5_fpga_client * client)542e9dcd831SSlava Shwartsman void mlx5_fpga_client_unregister(struct mlx5_fpga_client *client)
543e9dcd831SSlava Shwartsman {
544e9dcd831SSlava Shwartsman 	struct mlx5_fpga_client_data *context, *tmp_context;
545e9dcd831SSlava Shwartsman 	struct mlx5_fpga_device *fdev;
546e9dcd831SSlava Shwartsman 
547e9dcd831SSlava Shwartsman 	pr_debug("Client unregister %s\n", client->name);
548e9dcd831SSlava Shwartsman 
549e9dcd831SSlava Shwartsman 	mutex_lock(&mlx5_fpga_mutex);
550e9dcd831SSlava Shwartsman 
551e9dcd831SSlava Shwartsman 	list_for_each_entry(fdev, &mlx5_fpga_devices, list) {
552e9dcd831SSlava Shwartsman 		list_for_each_entry_safe(context, tmp_context,
553e9dcd831SSlava Shwartsman 					 &fdev->client_data_list,
554e9dcd831SSlava Shwartsman 					 list) {
555e9dcd831SSlava Shwartsman 			if (context->client != client)
556e9dcd831SSlava Shwartsman 				continue;
557e9dcd831SSlava Shwartsman 			if (context->added)
558e9dcd831SSlava Shwartsman 				client->remove(fdev);
559e9dcd831SSlava Shwartsman 			client_context_destroy(fdev, context);
560e9dcd831SSlava Shwartsman 			break;
561e9dcd831SSlava Shwartsman 		}
562e9dcd831SSlava Shwartsman 	}
563e9dcd831SSlava Shwartsman 
564e9dcd831SSlava Shwartsman 	list_del(&client->list);
565e9dcd831SSlava Shwartsman 	mutex_unlock(&mlx5_fpga_mutex);
566e9dcd831SSlava Shwartsman }
567e9dcd831SSlava Shwartsman EXPORT_SYMBOL(mlx5_fpga_client_unregister);
568e9dcd831SSlava Shwartsman 
569e9dcd831SSlava Shwartsman MODULE_DEPEND(mlx5fpga, linuxkpi, 1, 1, 1);
570e9dcd831SSlava Shwartsman MODULE_DEPEND(mlx5fpga, mlx5, 1, 1, 1);
571e9dcd831SSlava Shwartsman MODULE_VERSION(mlx5fpga, 1);
572