2 * Copyright (c) 2017, Mellanox Technologies. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35 #include <linux/module.h>
36 #include <linux/etherdevice.h>
37 #include <dev/mlx5/driver.h>
38 #include <dev/mlx5/mlx5_core/mlx5_core.h>
39 #include <dev/mlx5/mlx5_lib/mlx5.h>
40 #include <dev/mlx5/mlx5_fpga/core.h>
41 #include <dev/mlx5/mlx5_fpga/conn.h>
42 #include <dev/mlx5/mlx5_fpga/trans.h>
44 static LIST_HEAD(mlx5_fpga_devices);
45 static LIST_HEAD(mlx5_fpga_clients);
46 /* protects access between client un/registration and device add/remove calls */
47 static DEFINE_MUTEX(mlx5_fpga_mutex);
49 static const char *const mlx5_fpga_error_strings[] = {
53 "Internal Link Error",
54 "Watchdog HW Failure",
57 "Temperature Critical",
60 static const char * const mlx5_fpga_qp_error_strings[] = {
62 "Retry Counter Expired",
66 static void client_context_destroy(struct mlx5_fpga_device *fdev,
67 struct mlx5_fpga_client_data *context)
69 mlx5_fpga_dbg(fdev, "Deleting client context %p of client %p\n",
70 context, context->client);
71 if (context->client->destroy)
72 context->client->destroy(fdev);
73 list_del(&context->list);
77 static int client_context_create(struct mlx5_fpga_device *fdev,
78 struct mlx5_fpga_client *client,
79 struct mlx5_fpga_client_data **pctx)
81 struct mlx5_fpga_client_data *context;
83 context = kmalloc(sizeof(*context), GFP_KERNEL);
87 context->client = client;
89 context->added = false;
90 list_add(&context->list, &fdev->client_data_list);
92 mlx5_fpga_dbg(fdev, "Adding client context %p client %p\n",
103 static struct mlx5_fpga_device *mlx5_fpga_device_alloc(void)
105 struct mlx5_fpga_device *fdev = NULL;
107 fdev = kzalloc(sizeof(*fdev), GFP_KERNEL);
111 spin_lock_init(&fdev->state_lock);
112 init_completion(&fdev->load_event);
113 fdev->fdev_state = MLX5_FDEV_STATE_NONE;
114 INIT_LIST_HEAD(&fdev->client_data_list);
118 static const char *mlx5_fpga_image_name(enum mlx5_fpga_image image)
121 case MLX5_FPGA_IMAGE_USER:
123 case MLX5_FPGA_IMAGE_FACTORY:
130 static const char *mlx5_fpga_name(u32 fpga_id)
135 case MLX5_FPGA_NEWTON:
137 case MLX5_FPGA_EDISON:
139 case MLX5_FPGA_MORSE:
141 case MLX5_FPGA_MORSEQ:
145 snprintf(ret, sizeof(ret), "Unknown %d", fpga_id);
149 static int mlx5_fpga_device_load_check(struct mlx5_fpga_device *fdev)
151 struct mlx5_fpga_query query;
155 err = mlx5_fpga_query(fdev->mdev, &query);
157 mlx5_fpga_err(fdev, "Failed to query status: %d\n", err);
161 fdev->last_admin_image = query.admin_image;
162 fdev->last_oper_image = query.oper_image;
163 fdev->image_status = query.image_status;
165 mlx5_fpga_info(fdev, "Status %u; Admin image %u; Oper image %u\n",
166 query.image_status, query.admin_image, query.oper_image);
168 /* For Morse projects FPGA has no influence to network functionality */
169 fpga_id = MLX5_CAP_FPGA(fdev->mdev, fpga_id);
170 if (fpga_id == MLX5_FPGA_MORSE || fpga_id == MLX5_FPGA_MORSEQ)
173 if (query.image_status != MLX5_FPGA_STATUS_SUCCESS) {
174 mlx5_fpga_err(fdev, "%s image failed to load; status %u\n",
175 mlx5_fpga_image_name(fdev->last_oper_image),
183 static int mlx5_fpga_device_brb(struct mlx5_fpga_device *fdev)
186 struct mlx5_core_dev *mdev = fdev->mdev;
188 err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_SANDBOX_BYPASS_ON);
190 mlx5_fpga_err(fdev, "Failed to set bypass on: %d\n", err);
193 err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_RESET_SANDBOX);
195 mlx5_fpga_err(fdev, "Failed to reset SBU: %d\n", err);
198 err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_SANDBOX_BYPASS_OFF);
200 mlx5_fpga_err(fdev, "Failed to set bypass off: %d\n", err);
206 int mlx5_fpga_device_start(struct mlx5_core_dev *mdev)
208 struct mlx5_fpga_client_data *client_context;
209 struct mlx5_fpga_device *fdev = mdev->fpga;
210 struct mlx5_fpga_conn_attr conn_attr = {0};
211 struct mlx5_fpga_conn *conn;
212 unsigned int max_num_qps;
222 err = mlx5_fpga_caps(fdev->mdev);
226 err = mlx5_fpga_device_load_check(fdev);
230 fpga_id = MLX5_CAP_FPGA(fdev->mdev, fpga_id);
231 mlx5_fpga_info(fdev, "FPGA card %s\n", mlx5_fpga_name(fpga_id));
233 if (fpga_id == MLX5_FPGA_MORSE || fpga_id == MLX5_FPGA_MORSEQ)
236 mlx5_fpga_info(fdev, "%s(%d) image, version %u; SBU %06x:%04x version %d\n",
237 mlx5_fpga_image_name(fdev->last_oper_image),
238 fdev->last_oper_image,
239 MLX5_CAP_FPGA(fdev->mdev, image_version),
240 MLX5_CAP_FPGA(fdev->mdev, ieee_vendor_id),
241 MLX5_CAP_FPGA(fdev->mdev, sandbox_product_id),
242 MLX5_CAP_FPGA(fdev->mdev, sandbox_product_version));
244 max_num_qps = MLX5_CAP_FPGA(mdev, shell_caps.max_num_qps);
245 err = mlx5_core_reserve_gids(mdev, max_num_qps);
251 err = mlx5_fpga_conn_device_init(fdev);
258 err = mlx5_fpga_trans_device_init(fdev);
260 mlx5_fpga_err(fdev, "Failed to init transaction: %d\n",
265 conn_attr.tx_size = MLX5_FPGA_TID_COUNT;
266 conn_attr.rx_size = MLX5_FPGA_TID_COUNT;
267 conn_attr.recv_cb = mlx5_fpga_trans_recv;
268 conn_attr.cb_arg = fdev;
271 conn = mlx5_fpga_conn_create(fdev, &conn_attr,
272 MLX5_FPGA_QPC_QP_TYPE_SHELL_QP);
275 mlx5_fpga_err(fdev, "Failed to create shell conn: %d\n", err);
281 fdev->shell_conn = conn;
283 if (fdev->last_oper_image == MLX5_FPGA_IMAGE_USER) {
284 err = mlx5_fpga_device_brb(fdev);
288 vid = MLX5_CAP_FPGA(fdev->mdev, ieee_vendor_id);
289 pid = MLX5_CAP_FPGA(fdev->mdev, sandbox_product_id);
290 mutex_lock(&mlx5_fpga_mutex);
291 list_for_each_entry(client_context, &fdev->client_data_list,
293 if (client_context->client->add(fdev, vid, pid))
295 client_context->added = true;
297 mutex_unlock(&mlx5_fpga_mutex);
303 if (fdev->shell_conn) {
306 mlx5_fpga_conn_destroy(fdev->shell_conn);
308 fdev->shell_conn = NULL;
315 mlx5_fpga_trans_device_cleanup(fdev);
320 mlx5_fpga_conn_device_cleanup(fdev);
324 mlx5_core_unreserve_gids(mdev, max_num_qps);
326 spin_lock_irqsave(&fdev->state_lock, flags);
327 fdev->fdev_state = err ? MLX5_FDEV_STATE_FAILURE : MLX5_FDEV_STATE_SUCCESS;
328 spin_unlock_irqrestore(&fdev->state_lock, flags);
332 int mlx5_fpga_init(struct mlx5_core_dev *mdev)
334 struct mlx5_fpga_device *fdev = NULL;
335 struct mlx5_fpga_client *client;
337 if (!MLX5_CAP_GEN(mdev, fpga)) {
338 mlx5_core_dbg(mdev, "FPGA capability not present\n");
342 mlx5_core_dbg(mdev, "Initializing FPGA\n");
344 fdev = mlx5_fpga_device_alloc();
351 mutex_lock(&mlx5_fpga_mutex);
353 list_add_tail(&fdev->list, &mlx5_fpga_devices);
354 list_for_each_entry(client, &mlx5_fpga_clients, list)
355 client_context_create(fdev, client, NULL);
357 mutex_unlock(&mlx5_fpga_mutex);
361 void mlx5_fpga_device_stop(struct mlx5_core_dev *mdev)
363 struct mlx5_fpga_client_data *client_context;
364 struct mlx5_fpga_device *fdev = mdev->fpga;
365 unsigned int max_num_qps;
373 fpga_id = MLX5_CAP_FPGA(mdev, fpga_id);
374 if (fpga_id == MLX5_FPGA_MORSE || fpga_id == MLX5_FPGA_MORSEQ)
377 spin_lock_irqsave(&fdev->state_lock, flags);
379 if (fdev->fdev_state != MLX5_FDEV_STATE_SUCCESS) {
380 spin_unlock_irqrestore(&fdev->state_lock, flags);
383 fdev->fdev_state = MLX5_FDEV_STATE_NONE;
384 spin_unlock_irqrestore(&fdev->state_lock, flags);
386 if (fdev->last_oper_image == MLX5_FPGA_IMAGE_USER) {
387 err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_SANDBOX_BYPASS_ON);
389 mlx5_fpga_err(fdev, "Failed to re-set SBU bypass on: %d\n",
393 mutex_lock(&mlx5_fpga_mutex);
394 list_for_each_entry(client_context, &fdev->client_data_list, list) {
395 if (!client_context->added)
397 client_context->client->remove(fdev);
398 client_context->added = false;
400 mutex_unlock(&mlx5_fpga_mutex);
402 if (fdev->shell_conn) {
405 mlx5_fpga_conn_destroy(fdev->shell_conn);
407 fdev->shell_conn = NULL;
408 mlx5_fpga_trans_device_cleanup(fdev);
412 mlx5_fpga_conn_device_cleanup(fdev);
414 max_num_qps = MLX5_CAP_FPGA(mdev, shell_caps.max_num_qps);
415 mlx5_core_unreserve_gids(mdev, max_num_qps);
418 void mlx5_fpga_cleanup(struct mlx5_core_dev *mdev)
420 struct mlx5_fpga_client_data *context, *tmp;
421 struct mlx5_fpga_device *fdev = mdev->fpga;
426 mutex_lock(&mlx5_fpga_mutex);
428 mlx5_fpga_device_stop(mdev);
430 list_for_each_entry_safe(context, tmp, &fdev->client_data_list, list)
431 client_context_destroy(fdev, context);
433 list_del(&fdev->list);
437 mutex_unlock(&mlx5_fpga_mutex);
440 static const char *mlx5_fpga_syndrome_to_string(u8 syndrome)
442 if (syndrome < ARRAY_SIZE(mlx5_fpga_error_strings))
443 return mlx5_fpga_error_strings[syndrome];
447 static const char *mlx5_fpga_qp_syndrome_to_string(u8 syndrome)
449 if (syndrome < ARRAY_SIZE(mlx5_fpga_qp_error_strings))
450 return mlx5_fpga_qp_error_strings[syndrome];
454 void mlx5_fpga_event(struct mlx5_core_dev *mdev, u8 event, void *data)
456 struct mlx5_fpga_device *fdev = mdev->fpga;
457 const char *event_name;
458 bool teardown = false;
464 case MLX5_EVENT_TYPE_FPGA_ERROR:
465 syndrome = MLX5_GET(fpga_error_event, data, syndrome);
466 event_name = mlx5_fpga_syndrome_to_string(syndrome);
468 case MLX5_EVENT_TYPE_FPGA_QP_ERROR:
469 syndrome = MLX5_GET(fpga_qp_error_event, data, syndrome);
470 event_name = mlx5_fpga_qp_syndrome_to_string(syndrome);
471 fpga_qpn = MLX5_GET(fpga_qp_error_event, data, fpga_qpn);
472 mlx5_fpga_err(fdev, "Error %u on QP %u: %s\n",
473 syndrome, fpga_qpn, event_name);
476 mlx5_fpga_warn_ratelimited(fdev, "Unexpected event %u\n",
481 spin_lock_irqsave(&fdev->state_lock, flags);
482 switch (fdev->fdev_state) {
483 case MLX5_FDEV_STATE_SUCCESS:
484 mlx5_fpga_warn(fdev, "Error %u: %s\n", syndrome, event_name);
487 case MLX5_FDEV_STATE_IN_PROGRESS:
488 if (syndrome != MLX5_FPGA_ERROR_EVENT_SYNDROME_IMAGE_CHANGED)
489 mlx5_fpga_warn(fdev, "Error while loading %u: %s\n",
490 syndrome, event_name);
491 complete(&fdev->load_event);
494 mlx5_fpga_warn_ratelimited(fdev, "Unexpected error event %u: %s\n",
495 syndrome, event_name);
497 spin_unlock_irqrestore(&fdev->state_lock, flags);
498 /* We tear-down the card's interfaces and functionality because
499 * the FPGA bump-on-the-wire is misbehaving and we lose ability
500 * to communicate with the network. User may still be able to
501 * recover by re-programming or debugging the FPGA
504 mlx5_trigger_health_work(fdev->mdev);
507 void mlx5_fpga_client_register(struct mlx5_fpga_client *client)
509 struct mlx5_fpga_client_data *context;
510 struct mlx5_fpga_device *fdev;
511 bool call_add = false;
517 pr_debug("Client register %s\n", client->name);
519 mutex_lock(&mlx5_fpga_mutex);
521 list_add_tail(&client->list, &mlx5_fpga_clients);
523 list_for_each_entry(fdev, &mlx5_fpga_devices, list) {
524 err = client_context_create(fdev, client, &context);
528 spin_lock_irqsave(&fdev->state_lock, flags);
529 call_add = (fdev->fdev_state == MLX5_FDEV_STATE_SUCCESS);
530 spin_unlock_irqrestore(&fdev->state_lock, flags);
533 vid = MLX5_CAP_FPGA(fdev->mdev, ieee_vendor_id);
534 pid = MLX5_CAP_FPGA(fdev->mdev, sandbox_product_id);
535 if (!client->add(fdev, vid, pid))
536 context->added = true;
540 mutex_unlock(&mlx5_fpga_mutex);
542 EXPORT_SYMBOL(mlx5_fpga_client_register);
544 void mlx5_fpga_client_unregister(struct mlx5_fpga_client *client)
546 struct mlx5_fpga_client_data *context, *tmp_context;
547 struct mlx5_fpga_device *fdev;
549 pr_debug("Client unregister %s\n", client->name);
551 mutex_lock(&mlx5_fpga_mutex);
553 list_for_each_entry(fdev, &mlx5_fpga_devices, list) {
554 list_for_each_entry_safe(context, tmp_context,
555 &fdev->client_data_list,
557 if (context->client != client)
560 client->remove(fdev);
561 client_context_destroy(fdev, context);
566 list_del(&client->list);
567 mutex_unlock(&mlx5_fpga_mutex);
569 EXPORT_SYMBOL(mlx5_fpga_client_unregister);
571 #if (__FreeBSD_version >= 1100000)
572 MODULE_DEPEND(mlx5fpga, linuxkpi, 1, 1, 1);
574 MODULE_DEPEND(mlx5fpga, mlx5, 1, 1, 1);
575 MODULE_VERSION(mlx5fpga, 1);