1 /*-
2 * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
3 *
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:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
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.
22 *
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
30 * SOFTWARE.
31 *
32 * $FreeBSD$
33 */
34
35 #include <linux/errno.h>
36 #include <linux/err.h>
37 #include <linux/completion.h>
38 #include <dev/mlx5/device.h>
39 #include <dev/mlx5/mlx5_fpga/core.h>
40 #include <dev/mlx5/mlx5_fpga/conn.h>
41 #include <dev/mlx5/mlx5_fpga/sdk.h>
42 #include <dev/mlx5/mlx5_fpga/xfer.h>
43 #include <dev/mlx5/mlx5_core/mlx5_core.h>
44 /* #include "accel/ipsec.h" */
45
46 #define MLX5_FPGA_LOAD_TIMEOUT 25000 /* msec */
47
48 struct mem_transfer {
49 struct mlx5_fpga_transaction t;
50 struct completion comp;
51 u8 status;
52 };
53
54 struct mlx5_fpga_conn *
55 mlx5_fpga_sbu_conn_create(struct mlx5_fpga_device *fdev,
56 struct mlx5_fpga_conn_attr *attr)
57 {
58 #ifdef NOT_YET
59 /* XXXKIB */
60 return mlx5_fpga_conn_create(fdev, attr, MLX5_FPGA_QPC_QP_TYPE_SANDBOX_QP);
61 #else
62 return (NULL);
63 #endif
64 }
65 EXPORT_SYMBOL(mlx5_fpga_sbu_conn_create);
66
67 void mlx5_fpga_sbu_conn_destroy(struct mlx5_fpga_conn *conn)
68 {
69 #ifdef NOT_YET
70 /* XXXKIB */
71 mlx5_fpga_conn_destroy(conn);
72 #endif
73 }
74 EXPORT_SYMBOL(mlx5_fpga_sbu_conn_destroy);
75
76 int mlx5_fpga_sbu_conn_sendmsg(struct mlx5_fpga_conn *conn,
77 struct mlx5_fpga_dma_buf *buf)
78 {
79 #ifdef NOT_YET
80 /* XXXKIB */
81 return mlx5_fpga_conn_send(conn, buf);
82 #else
83 return (0);
84 #endif
85 }
86 EXPORT_SYMBOL(mlx5_fpga_sbu_conn_sendmsg);
87
88 static void mem_complete(const struct mlx5_fpga_transaction *complete,
89 u8 status)
90 {
91 struct mem_transfer *xfer;
92
93 mlx5_fpga_dbg(complete->conn->fdev,
94 "transaction %p complete status %u", complete, status);
95
96 xfer = container_of(complete, struct mem_transfer, t);
97 xfer->status = status;
98 complete_all(&xfer->comp);
99 }
100
101 static int mem_transaction(struct mlx5_fpga_device *fdev, size_t size, u64 addr,
102 void *buf, enum mlx5_fpga_direction direction)
103 {
104 int ret;
105 struct mem_transfer xfer;
106
107 if (!fdev->shell_conn) {
108 ret = -ENOTCONN;
109 goto out;
110 }
111
112 xfer.t.data = buf;
113 xfer.t.size = size;
114 xfer.t.addr = addr;
115 xfer.t.conn = fdev->shell_conn;
116 xfer.t.direction = direction;
117 xfer.t.complete1 = mem_complete;
118 init_completion(&xfer.comp);
119 ret = mlx5_fpga_xfer_exec(&xfer.t);
120 if (ret) {
121 mlx5_fpga_dbg(fdev, "Transfer execution failed: %d\n", ret);
122 goto out;
123 }
124 wait_for_completion(&xfer.comp);
125 if (xfer.status != 0)
126 ret = -EIO;
127
128 out:
129 return ret;
130 }
131
132 static int mlx5_fpga_mem_read_i2c(struct mlx5_fpga_device *fdev, size_t size,
133 u64 addr, u8 *buf)
134 {
135 size_t max_size = MLX5_FPGA_ACCESS_REG_SIZE_MAX;
136 size_t bytes_done = 0;
137 u8 actual_size;
138 int err = 0;
139
140 if (!size)
141 return -EINVAL;
142
143 if (!fdev->mdev)
144 return -ENOTCONN;
145
146 while (bytes_done < size) {
147 actual_size = min(max_size, (size - bytes_done));
148
149 err = mlx5_fpga_access_reg(fdev->mdev, actual_size,
150 addr + bytes_done,
151 buf + bytes_done, false);
152 if (err) {
153 mlx5_fpga_err(fdev, "Failed to read over I2C: %d\n",
154 err);
155 break;
156 }
157
158 bytes_done += actual_size;
159 }
160
161 return err;
162 }
163
164 static int mlx5_fpga_mem_write_i2c(struct mlx5_fpga_device *fdev, size_t size,
165 u64 addr, u8 *buf)
166 {
167 size_t max_size = MLX5_FPGA_ACCESS_REG_SIZE_MAX;
168 size_t bytes_done = 0;
169 u8 actual_size;
170 int err = 0;
171
172 if (!size)
173 return -EINVAL;
174
175 if (!fdev->mdev)
176 return -ENOTCONN;
177
178 while (bytes_done < size) {
179 actual_size = min(max_size, (size - bytes_done));
180
181 err = mlx5_fpga_access_reg(fdev->mdev, actual_size,
182 addr + bytes_done,
183 buf + bytes_done, true);
184 if (err) {
185 mlx5_fpga_err(fdev, "Failed to write FPGA crspace\n");
186 break;
187 }
188
189 bytes_done += actual_size;
190 }
191
192 return err;
193 }
194
195 int mlx5_fpga_mem_read(struct mlx5_fpga_device *fdev, size_t size, u64 addr,
196 void *buf, enum mlx5_fpga_access_type access_type)
197 {
198 int ret;
199
200 if (access_type == MLX5_FPGA_ACCESS_TYPE_DONTCARE)
201 access_type = fdev->shell_conn ? MLX5_FPGA_ACCESS_TYPE_RDMA :
202 MLX5_FPGA_ACCESS_TYPE_I2C;
203
204 mlx5_fpga_dbg(fdev, "Reading %zu bytes at 0x%jx over %s",
205 size, (uintmax_t)addr, access_type ? "RDMA" : "I2C");
206
207 switch (access_type) {
208 case MLX5_FPGA_ACCESS_TYPE_RDMA:
209 ret = mem_transaction(fdev, size, addr, buf, MLX5_FPGA_READ);
210 if (ret)
211 return ret;
212 break;
213 case MLX5_FPGA_ACCESS_TYPE_I2C:
214 ret = mlx5_fpga_mem_read_i2c(fdev, size, addr, buf);
215 if (ret)
216 return ret;
217 break;
218 default:
219 mlx5_fpga_warn(fdev, "Unexpected read access_type %u\n",
220 access_type);
221 return -EACCES;
222 }
223
224 return size;
225 }
226 EXPORT_SYMBOL(mlx5_fpga_mem_read);
227
228 int mlx5_fpga_mem_write(struct mlx5_fpga_device *fdev, size_t size, u64 addr,
229 void *buf, enum mlx5_fpga_access_type access_type)
230 {
231 int ret;
232
233 if (access_type == MLX5_FPGA_ACCESS_TYPE_DONTCARE)
234 access_type = fdev->shell_conn ? MLX5_FPGA_ACCESS_TYPE_RDMA :
235 MLX5_FPGA_ACCESS_TYPE_I2C;
236
237 mlx5_fpga_dbg(fdev, "Writing %zu bytes at 0x%jx over %s",
238 size, (uintmax_t)addr, access_type ? "RDMA" : "I2C");
239
240 switch (access_type) {
241 case MLX5_FPGA_ACCESS_TYPE_RDMA:
242 ret = mem_transaction(fdev, size, addr, buf, MLX5_FPGA_WRITE);
243 if (ret)
244 return ret;
245 break;
246 case MLX5_FPGA_ACCESS_TYPE_I2C:
247 ret = mlx5_fpga_mem_write_i2c(fdev, size, addr, buf);
248 if (ret)
249 return ret;
250 break;
251 default:
252 mlx5_fpga_warn(fdev, "Unexpected write access_type %u\n",
253 access_type);
254 return -EACCES;
255 }
256
257 return size;
258 }
259 EXPORT_SYMBOL(mlx5_fpga_mem_write);
260
261 int mlx5_fpga_get_sbu_caps(struct mlx5_fpga_device *fdev, int size, void *buf)
262 {
263 return mlx5_fpga_sbu_caps(fdev->mdev, buf, size);
264 }
265 EXPORT_SYMBOL(mlx5_fpga_get_sbu_caps);
266
267 u64 mlx5_fpga_ddr_size_get(struct mlx5_fpga_device *fdev)
268 {
269 return (u64)MLX5_CAP_FPGA(fdev->mdev, fpga_ddr_size) << 10;
270 }
271 EXPORT_SYMBOL(mlx5_fpga_ddr_size_get);
272
273 u64 mlx5_fpga_ddr_base_get(struct mlx5_fpga_device *fdev)
274 {
275 return MLX5_CAP64_FPGA(fdev->mdev, fpga_ddr_start_addr);
276 }
277 EXPORT_SYMBOL(mlx5_fpga_ddr_base_get);
278
279 void mlx5_fpga_client_data_set(struct mlx5_fpga_device *fdev,
280 struct mlx5_fpga_client *client, void *data)
281 {
282 struct mlx5_fpga_client_data *context;
283
284 list_for_each_entry(context, &fdev->client_data_list, list) {
285 if (context->client != client)
286 continue;
287 context->data = data;
288 return;
289 }
290
291 mlx5_fpga_warn(fdev, "No client context found for %s\n", client->name);
292 }
293 EXPORT_SYMBOL(mlx5_fpga_client_data_set);
294
295 void *mlx5_fpga_client_data_get(struct mlx5_fpga_device *fdev,
296 struct mlx5_fpga_client *client)
297 {
298 struct mlx5_fpga_client_data *context;
299 void *ret = NULL;
300
301 list_for_each_entry(context, &fdev->client_data_list, list) {
302 if (context->client != client)
303 continue;
304 ret = context->data;
305 goto out;
306 }
307 mlx5_fpga_warn(fdev, "No client context found for %s\n", client->name);
308
309 out:
310 return ret;
311 }
312 EXPORT_SYMBOL(mlx5_fpga_client_data_get);
313
314 void mlx5_fpga_device_query(struct mlx5_fpga_device *fdev,
315 struct mlx5_fpga_query *query)
316 {
317 unsigned long flags;
318
319 spin_lock_irqsave(&fdev->state_lock, flags);
320 query->image_status = fdev->image_status;
321 query->admin_image = fdev->last_admin_image;
322 query->oper_image = fdev->last_oper_image;
323 spin_unlock_irqrestore(&fdev->state_lock, flags);
324 }
325 EXPORT_SYMBOL(mlx5_fpga_device_query);
326
327 static int mlx5_fpga_device_reload_cmd(struct mlx5_fpga_device *fdev)
328 {
329 struct mlx5_core_dev *mdev = fdev->mdev;
330 unsigned long timeout;
331 unsigned long flags;
332 int err = 0;
333
334 mlx5_fpga_info(fdev, "mlx5/fpga - reload started\n");
335 fdev->fdev_state = MLX5_FDEV_STATE_IN_PROGRESS;
336 reinit_completion(&fdev->load_event);
337 err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_RELOAD);
338 if (err) {
339 mlx5_fpga_err(fdev, "Failed to request reload: %d\n",
340 err);
341 goto out;
342 }
343 timeout = jiffies + msecs_to_jiffies(MLX5_FPGA_LOAD_TIMEOUT);
344 err = wait_for_completion_timeout(&fdev->load_event,
345 timeout - jiffies);
346 if (err < 0) {
347 mlx5_fpga_err(fdev, "Failed waiting for reload: %d\n", err);
348 fdev->fdev_state = MLX5_FDEV_STATE_FAILURE;
349 goto out;
350 }
351 /* Check device loaded successful */
352 err = mlx5_fpga_device_start(mdev);
353 if (err) {
354 mlx5_fpga_err(fdev, "Failed load check for reload: %d\n", err);
355 fdev->fdev_state = MLX5_FDEV_STATE_FAILURE;
356 goto out;
357 }
358 spin_lock_irqsave(&fdev->state_lock, flags);
359 fdev->fdev_state = MLX5_FDEV_STATE_SUCCESS;
360 spin_unlock_irqrestore(&fdev->state_lock, flags);
361 mlx5_fpga_info(fdev, "mlx5/fpga - reload ended\n");
362 out:
363 return err;
364 }
365
366 int mlx5_fpga_device_reload(struct mlx5_fpga_device *fdev,
367 enum mlx5_fpga_image image)
368 {
369 struct mlx5_core_dev *mdev = fdev->mdev;
370 unsigned long timeout;
371 unsigned long flags;
372 int err = 0;
373
374 spin_lock_irqsave(&fdev->state_lock, flags);
375 switch (fdev->fdev_state) {
376 case MLX5_FDEV_STATE_NONE:
377 err = -ENODEV;
378 break;
379 case MLX5_FDEV_STATE_IN_PROGRESS:
380 err = -EBUSY;
381 break;
382 case MLX5_FDEV_STATE_SUCCESS:
383 case MLX5_FDEV_STATE_FAILURE:
384 case MLX5_FDEV_STATE_DISCONNECTED:
385 break;
386 }
387 spin_unlock_irqrestore(&fdev->state_lock, flags);
388 if (err)
389 return err;
390
391 mutex_lock(&mdev->intf_state_mutex);
392
393 if (image == MLX5_FPGA_IMAGE_RELOAD) {
394 err = mlx5_fpga_device_reload_cmd(fdev);
395 goto out;
396 }
397
398 clear_bit(MLX5_INTERFACE_STATE_UP, &mdev->intf_state);
399
400 mlx5_unregister_device(mdev);
401 /* XXXKIB mlx5_accel_ipsec_cleanup(mdev); */
402 mlx5_fpga_device_stop(mdev);
403
404 fdev->fdev_state = MLX5_FDEV_STATE_IN_PROGRESS;
405 reinit_completion(&fdev->load_event);
406
407 if (image <= MLX5_FPGA_IMAGE_FACTORY) {
408 mlx5_fpga_info(fdev, "Loading from flash\n");
409 err = mlx5_fpga_load(mdev, image);
410 if (err) {
411 mlx5_fpga_err(fdev, "Failed to request load: %d\n",
412 err);
413 goto out;
414 }
415 } else if (image == MLX5_FPGA_IMAGE_RESET) {
416 mlx5_fpga_info(fdev, "Resetting\n");
417 err = mlx5_fpga_ctrl_op(mdev, MLX5_FPGA_CTRL_OPERATION_RESET);
418 if (err) {
419 mlx5_fpga_err(fdev, "Failed to request reset: %d\n",
420 err);
421 goto out;
422 }
423 } else {
424 mlx5_fpga_err(fdev, "Unknown command: %d\n",
425 image);
426 goto out;
427 }
428
429 timeout = jiffies + msecs_to_jiffies(MLX5_FPGA_LOAD_TIMEOUT);
430 err = wait_for_completion_timeout(&fdev->load_event, timeout - jiffies);
431 if (err < 0) {
432 mlx5_fpga_err(fdev, "Failed waiting for FPGA load: %d\n", err);
433 fdev->fdev_state = MLX5_FDEV_STATE_FAILURE;
434 goto out;
435 }
436
437 err = mlx5_fpga_device_start(mdev);
438 if (err) {
439 mlx5_core_err(mdev, "fpga device start failed %d\n", err);
440 goto out;
441 }
442 /* XXXKIB err = mlx5_accel_ipsec_init(mdev); */
443 if (err) {
444 mlx5_core_err(mdev, "IPSec device start failed %d\n", err);
445 goto err_fpga;
446 }
447
448 err = mlx5_register_device(mdev);
449 if (err) {
450 mlx5_core_err(mdev, "mlx5_register_device failed %d\n", err);
451 fdev->fdev_state = MLX5_FDEV_STATE_FAILURE;
452 goto err_ipsec;
453 }
454
455 set_bit(MLX5_INTERFACE_STATE_UP, &mdev->intf_state);
456 goto out;
457
458 err_ipsec:
459 /* XXXKIB mlx5_accel_ipsec_cleanup(mdev); */
460 err_fpga:
461 mlx5_fpga_device_stop(mdev);
462 out:
463 mutex_unlock(&mdev->intf_state_mutex);
464 return err;
465 }
466 EXPORT_SYMBOL(mlx5_fpga_device_reload);
467
468 int mlx5_fpga_flash_select(struct mlx5_fpga_device *fdev,
469 enum mlx5_fpga_image image)
470 {
471 unsigned long flags;
472 int err;
473
474 spin_lock_irqsave(&fdev->state_lock, flags);
475 switch (fdev->fdev_state) {
476 case MLX5_FDEV_STATE_NONE:
477 spin_unlock_irqrestore(&fdev->state_lock, flags);
478 return -ENODEV;
479 case MLX5_FDEV_STATE_DISCONNECTED:
480 case MLX5_FDEV_STATE_IN_PROGRESS:
481 case MLX5_FDEV_STATE_SUCCESS:
482 case MLX5_FDEV_STATE_FAILURE:
483 break;
484 }
485 spin_unlock_irqrestore(&fdev->state_lock, flags);
486
487 err = mlx5_fpga_image_select(fdev->mdev, image);
488 if (err)
489 mlx5_fpga_err(fdev, "Failed to select flash image: %d\n", err);
490 else
491 fdev->last_admin_image = image;
492 return err;
493 }
494 EXPORT_SYMBOL(mlx5_fpga_flash_select);
495
496 int mlx5_fpga_connectdisconnect(struct mlx5_fpga_device *fdev,
497 enum mlx5_fpga_connect *connect)
498 {
499 unsigned long flags;
500 int err;
501
502 spin_lock_irqsave(&fdev->state_lock, flags);
503 switch (fdev->fdev_state) {
504 case MLX5_FDEV_STATE_NONE:
505 spin_unlock_irqrestore(&fdev->state_lock, flags);
506 return -ENODEV;
507 case MLX5_FDEV_STATE_IN_PROGRESS:
508 case MLX5_FDEV_STATE_SUCCESS:
509 case MLX5_FDEV_STATE_FAILURE:
510 case MLX5_FDEV_STATE_DISCONNECTED:
511 break;
512 }
513 spin_unlock_irqrestore(&fdev->state_lock, flags);
514
515 err = mlx5_fpga_ctrl_connect(fdev->mdev, connect);
516 if (err)
517 mlx5_fpga_err(fdev, "Failed to connect/disconnect: %d\n", err);
518 return err;
519 }
520 EXPORT_SYMBOL(mlx5_fpga_connectdisconnect);
521
522 int mlx5_fpga_temperature(struct mlx5_fpga_device *fdev,
523 struct mlx5_fpga_temperature *temp)
524 {
525 return mlx5_fpga_query_mtmp(fdev->mdev, temp);
526 }
527 EXPORT_SYMBOL(mlx5_fpga_temperature);
528
529 struct device *mlx5_fpga_dev(struct mlx5_fpga_device *fdev)
530 {
531 return &fdev->mdev->pdev->dev;
532 }
533 EXPORT_SYMBOL(mlx5_fpga_dev);
534
535 void mlx5_fpga_get_cap(struct mlx5_fpga_device *fdev, u32 *fpga_caps)
536 {
537 unsigned long flags;
538
539 spin_lock_irqsave(&fdev->state_lock, flags);
540 memcpy(fpga_caps, &fdev->mdev->caps.fpga, sizeof(fdev->mdev->caps.fpga));
541 spin_unlock_irqrestore(&fdev->state_lock, flags);
542 }
543 EXPORT_SYMBOL(mlx5_fpga_get_cap);
Cache object: da9deb056133976303a7e10435d46acd
|