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