]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/mlx5/mlx5_fpga/mlx5fpga_sdk.c
Update nvi to 2.2.0-05ed8b9
[FreeBSD/FreeBSD.git] / sys / dev / mlx5 / mlx5_fpga / mlx5fpga_sdk.c
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);