This source file includes following definitions.
- mlx5_fpga_tls_put_command_ctx
- mlx5_fpga_tls_cmd_complete
- mlx5_fpga_cmd_send_complete
- mlx5_fpga_tls_cmd_send
- mlx5_fpga_tls_alloc_swid
- mlx5_fpga_tls_release_swid
- mlx_tls_kfree_complete
- mlx5_fpga_tls_teardown_completion
- mlx5_fpga_tls_flow_to_cmd
- mlx5_fpga_tls_resync_rx
- mlx5_fpga_tls_send_teardown_cmd
- mlx5_fpga_tls_del_flow
- mlx5_fpga_tls_setup_completion
- mlx5_fpga_tls_setup_stream_cmd
- mlx5_fpga_tls_hw_qp_recv_cb
- mlx5_fpga_is_tls_device
- mlx5_fpga_tls_get_caps
- mlx5_fpga_tls_init
- mlx5_fpga_tls_cleanup
- mlx5_fpga_tls_set_aes_gcm128_ctx
- mlx5_fpga_tls_set_key_material
- _mlx5_fpga_tls_add_flow
- mlx5_fpga_tls_add_flow
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 #include <linux/mlx5/device.h>
35 #include "fpga/tls.h"
36 #include "fpga/cmd.h"
37 #include "fpga/sdk.h"
38 #include "fpga/core.h"
39 #include "accel/tls.h"
40
41 struct mlx5_fpga_tls_command_context;
42
43 typedef void (*mlx5_fpga_tls_command_complete)
44 (struct mlx5_fpga_conn *conn, struct mlx5_fpga_device *fdev,
45 struct mlx5_fpga_tls_command_context *ctx,
46 struct mlx5_fpga_dma_buf *resp);
47
48 struct mlx5_fpga_tls_command_context {
49 struct list_head list;
50
51
52
53
54
55
56
57 refcount_t ref;
58 struct mlx5_fpga_dma_buf buf;
59 mlx5_fpga_tls_command_complete complete;
60 };
61
62 static void
63 mlx5_fpga_tls_put_command_ctx(struct mlx5_fpga_tls_command_context *ctx)
64 {
65 if (refcount_dec_and_test(&ctx->ref))
66 kfree(ctx);
67 }
68
69 static void mlx5_fpga_tls_cmd_complete(struct mlx5_fpga_device *fdev,
70 struct mlx5_fpga_dma_buf *resp)
71 {
72 struct mlx5_fpga_conn *conn = fdev->tls->conn;
73 struct mlx5_fpga_tls_command_context *ctx;
74 struct mlx5_fpga_tls *tls = fdev->tls;
75 unsigned long flags;
76
77 spin_lock_irqsave(&tls->pending_cmds_lock, flags);
78 ctx = list_first_entry(&tls->pending_cmds,
79 struct mlx5_fpga_tls_command_context, list);
80 list_del(&ctx->list);
81 spin_unlock_irqrestore(&tls->pending_cmds_lock, flags);
82 ctx->complete(conn, fdev, ctx, resp);
83 }
84
85 static void mlx5_fpga_cmd_send_complete(struct mlx5_fpga_conn *conn,
86 struct mlx5_fpga_device *fdev,
87 struct mlx5_fpga_dma_buf *buf,
88 u8 status)
89 {
90 struct mlx5_fpga_tls_command_context *ctx =
91 container_of(buf, struct mlx5_fpga_tls_command_context, buf);
92
93 mlx5_fpga_tls_put_command_ctx(ctx);
94
95 if (unlikely(status))
96 mlx5_fpga_tls_cmd_complete(fdev, NULL);
97 }
98
99 static void mlx5_fpga_tls_cmd_send(struct mlx5_fpga_device *fdev,
100 struct mlx5_fpga_tls_command_context *cmd,
101 mlx5_fpga_tls_command_complete complete)
102 {
103 struct mlx5_fpga_tls *tls = fdev->tls;
104 unsigned long flags;
105 int ret;
106
107 refcount_set(&cmd->ref, 2);
108 cmd->complete = complete;
109 cmd->buf.complete = mlx5_fpga_cmd_send_complete;
110
111 spin_lock_irqsave(&tls->pending_cmds_lock, flags);
112
113
114
115
116 ret = mlx5_fpga_sbu_conn_sendmsg(tls->conn, &cmd->buf);
117 if (likely(!ret))
118 list_add_tail(&cmd->list, &tls->pending_cmds);
119 else
120 complete(tls->conn, fdev, cmd, NULL);
121 spin_unlock_irqrestore(&tls->pending_cmds_lock, flags);
122 }
123
124
125 #define SWID_START 0
126
127 #define SWID_END BIT(24)
128
129 static int mlx5_fpga_tls_alloc_swid(struct idr *idr, spinlock_t *idr_spinlock,
130 void *ptr)
131 {
132 unsigned long flags;
133 int ret;
134
135
136
137
138
139
140 BUILD_BUG_ON((SWID_END - 1) & 0xFF000000);
141
142 idr_preload(GFP_KERNEL);
143 spin_lock_irqsave(idr_spinlock, flags);
144 ret = idr_alloc(idr, ptr, SWID_START, SWID_END, GFP_ATOMIC);
145 spin_unlock_irqrestore(idr_spinlock, flags);
146 idr_preload_end();
147
148 return ret;
149 }
150
151 static void *mlx5_fpga_tls_release_swid(struct idr *idr,
152 spinlock_t *idr_spinlock, u32 swid)
153 {
154 unsigned long flags;
155 void *ptr;
156
157 spin_lock_irqsave(idr_spinlock, flags);
158 ptr = idr_remove(idr, swid);
159 spin_unlock_irqrestore(idr_spinlock, flags);
160 return ptr;
161 }
162
163 static void mlx_tls_kfree_complete(struct mlx5_fpga_conn *conn,
164 struct mlx5_fpga_device *fdev,
165 struct mlx5_fpga_dma_buf *buf, u8 status)
166 {
167 kfree(buf);
168 }
169
170 static void
171 mlx5_fpga_tls_teardown_completion(struct mlx5_fpga_conn *conn,
172 struct mlx5_fpga_device *fdev,
173 struct mlx5_fpga_tls_command_context *cmd,
174 struct mlx5_fpga_dma_buf *resp)
175 {
176 if (resp) {
177 u32 syndrome = MLX5_GET(tls_resp, resp->sg[0].data, syndrome);
178
179 if (syndrome)
180 mlx5_fpga_err(fdev,
181 "Teardown stream failed with syndrome = %d",
182 syndrome);
183 }
184 mlx5_fpga_tls_put_command_ctx(cmd);
185 }
186
187 static void mlx5_fpga_tls_flow_to_cmd(void *flow, void *cmd)
188 {
189 memcpy(MLX5_ADDR_OF(tls_cmd, cmd, src_port), flow,
190 MLX5_BYTE_OFF(tls_flow, ipv6));
191
192 MLX5_SET(tls_cmd, cmd, ipv6, MLX5_GET(tls_flow, flow, ipv6));
193 MLX5_SET(tls_cmd, cmd, direction_sx,
194 MLX5_GET(tls_flow, flow, direction_sx));
195 }
196
197 int mlx5_fpga_tls_resync_rx(struct mlx5_core_dev *mdev, u32 handle, u32 seq,
198 u64 rcd_sn)
199 {
200 struct mlx5_fpga_dma_buf *buf;
201 int size = sizeof(*buf) + MLX5_TLS_COMMAND_SIZE;
202 void *flow;
203 void *cmd;
204 int ret;
205
206 buf = kzalloc(size, GFP_ATOMIC);
207 if (!buf)
208 return -ENOMEM;
209
210 cmd = (buf + 1);
211
212 rcu_read_lock();
213 flow = idr_find(&mdev->fpga->tls->rx_idr, ntohl(handle));
214 if (unlikely(!flow)) {
215 rcu_read_unlock();
216 WARN_ONCE(1, "Received NULL pointer for handle\n");
217 kfree(buf);
218 return -EINVAL;
219 }
220 mlx5_fpga_tls_flow_to_cmd(flow, cmd);
221 rcu_read_unlock();
222
223 MLX5_SET(tls_cmd, cmd, swid, ntohl(handle));
224 MLX5_SET64(tls_cmd, cmd, tls_rcd_sn, be64_to_cpu(rcd_sn));
225 MLX5_SET(tls_cmd, cmd, tcp_sn, seq);
226 MLX5_SET(tls_cmd, cmd, command_type, CMD_RESYNC_RX);
227
228 buf->sg[0].data = cmd;
229 buf->sg[0].size = MLX5_TLS_COMMAND_SIZE;
230 buf->complete = mlx_tls_kfree_complete;
231
232 ret = mlx5_fpga_sbu_conn_sendmsg(mdev->fpga->tls->conn, buf);
233 if (ret < 0)
234 kfree(buf);
235
236 return ret;
237 }
238
239 static void mlx5_fpga_tls_send_teardown_cmd(struct mlx5_core_dev *mdev,
240 void *flow, u32 swid, gfp_t flags)
241 {
242 struct mlx5_fpga_tls_command_context *ctx;
243 struct mlx5_fpga_dma_buf *buf;
244 void *cmd;
245
246 ctx = kzalloc(sizeof(*ctx) + MLX5_TLS_COMMAND_SIZE, flags);
247 if (!ctx)
248 return;
249
250 buf = &ctx->buf;
251 cmd = (ctx + 1);
252 MLX5_SET(tls_cmd, cmd, command_type, CMD_TEARDOWN_STREAM);
253 MLX5_SET(tls_cmd, cmd, swid, swid);
254
255 mlx5_fpga_tls_flow_to_cmd(flow, cmd);
256 kfree(flow);
257
258 buf->sg[0].data = cmd;
259 buf->sg[0].size = MLX5_TLS_COMMAND_SIZE;
260
261 mlx5_fpga_tls_cmd_send(mdev->fpga, ctx,
262 mlx5_fpga_tls_teardown_completion);
263 }
264
265 void mlx5_fpga_tls_del_flow(struct mlx5_core_dev *mdev, u32 swid,
266 gfp_t flags, bool direction_sx)
267 {
268 struct mlx5_fpga_tls *tls = mdev->fpga->tls;
269 void *flow;
270
271 if (direction_sx)
272 flow = mlx5_fpga_tls_release_swid(&tls->tx_idr,
273 &tls->tx_idr_spinlock,
274 swid);
275 else
276 flow = mlx5_fpga_tls_release_swid(&tls->rx_idr,
277 &tls->rx_idr_spinlock,
278 swid);
279
280 if (!flow) {
281 mlx5_fpga_err(mdev->fpga, "No flow information for swid %u\n",
282 swid);
283 return;
284 }
285
286 synchronize_rcu();
287 mlx5_fpga_tls_send_teardown_cmd(mdev, flow, swid, flags);
288 }
289
290 enum mlx5_fpga_setup_stream_status {
291 MLX5_FPGA_CMD_PENDING,
292 MLX5_FPGA_CMD_SEND_FAILED,
293 MLX5_FPGA_CMD_RESPONSE_RECEIVED,
294 MLX5_FPGA_CMD_ABANDONED,
295 };
296
297 struct mlx5_setup_stream_context {
298 struct mlx5_fpga_tls_command_context cmd;
299 atomic_t status;
300 u32 syndrome;
301 struct completion comp;
302 };
303
304 static void
305 mlx5_fpga_tls_setup_completion(struct mlx5_fpga_conn *conn,
306 struct mlx5_fpga_device *fdev,
307 struct mlx5_fpga_tls_command_context *cmd,
308 struct mlx5_fpga_dma_buf *resp)
309 {
310 struct mlx5_setup_stream_context *ctx =
311 container_of(cmd, struct mlx5_setup_stream_context, cmd);
312 int status = MLX5_FPGA_CMD_SEND_FAILED;
313 void *tls_cmd = ctx + 1;
314
315
316 if (resp) {
317 ctx->syndrome = MLX5_GET(tls_resp, resp->sg[0].data, syndrome);
318 status = MLX5_FPGA_CMD_RESPONSE_RECEIVED;
319 }
320
321 status = atomic_xchg_release(&ctx->status, status);
322 if (likely(status != MLX5_FPGA_CMD_ABANDONED)) {
323 complete(&ctx->comp);
324 return;
325 }
326
327 mlx5_fpga_err(fdev, "Command was abandoned, syndrome = %u\n",
328 ctx->syndrome);
329
330 if (!ctx->syndrome) {
331
332
333
334
335
336
337 mlx5_fpga_tls_del_flow(fdev->mdev,
338 MLX5_GET(tls_cmd, tls_cmd, swid),
339 GFP_ATOMIC,
340 MLX5_GET(tls_cmd, tls_cmd,
341 direction_sx));
342 }
343
344 mlx5_fpga_tls_put_command_ctx(cmd);
345 }
346
347 static int mlx5_fpga_tls_setup_stream_cmd(struct mlx5_core_dev *mdev,
348 struct mlx5_setup_stream_context *ctx)
349 {
350 struct mlx5_fpga_dma_buf *buf;
351 void *cmd = ctx + 1;
352 int status, ret = 0;
353
354 buf = &ctx->cmd.buf;
355 buf->sg[0].data = cmd;
356 buf->sg[0].size = MLX5_TLS_COMMAND_SIZE;
357 MLX5_SET(tls_cmd, cmd, command_type, CMD_SETUP_STREAM);
358
359 init_completion(&ctx->comp);
360 atomic_set(&ctx->status, MLX5_FPGA_CMD_PENDING);
361 ctx->syndrome = -1;
362
363 mlx5_fpga_tls_cmd_send(mdev->fpga, &ctx->cmd,
364 mlx5_fpga_tls_setup_completion);
365 wait_for_completion_killable(&ctx->comp);
366
367 status = atomic_xchg_acquire(&ctx->status, MLX5_FPGA_CMD_ABANDONED);
368 if (unlikely(status == MLX5_FPGA_CMD_PENDING))
369
370 return -EINTR;
371
372 if (unlikely(ctx->syndrome))
373 ret = -ENOMEM;
374
375 mlx5_fpga_tls_put_command_ctx(&ctx->cmd);
376 return ret;
377 }
378
379 static void mlx5_fpga_tls_hw_qp_recv_cb(void *cb_arg,
380 struct mlx5_fpga_dma_buf *buf)
381 {
382 struct mlx5_fpga_device *fdev = (struct mlx5_fpga_device *)cb_arg;
383
384 mlx5_fpga_tls_cmd_complete(fdev, buf);
385 }
386
387 bool mlx5_fpga_is_tls_device(struct mlx5_core_dev *mdev)
388 {
389 if (!mdev->fpga || !MLX5_CAP_GEN(mdev, fpga))
390 return false;
391
392 if (MLX5_CAP_FPGA(mdev, ieee_vendor_id) !=
393 MLX5_FPGA_CAP_SANDBOX_VENDOR_ID_MLNX)
394 return false;
395
396 if (MLX5_CAP_FPGA(mdev, sandbox_product_id) !=
397 MLX5_FPGA_CAP_SANDBOX_PRODUCT_ID_TLS)
398 return false;
399
400 if (MLX5_CAP_FPGA(mdev, sandbox_product_version) != 0)
401 return false;
402
403 return true;
404 }
405
406 static int mlx5_fpga_tls_get_caps(struct mlx5_fpga_device *fdev,
407 u32 *p_caps)
408 {
409 int err, cap_size = MLX5_ST_SZ_BYTES(tls_extended_cap);
410 u32 caps = 0;
411 void *buf;
412
413 buf = kzalloc(cap_size, GFP_KERNEL);
414 if (!buf)
415 return -ENOMEM;
416
417 err = mlx5_fpga_get_sbu_caps(fdev, cap_size, buf);
418 if (err)
419 goto out;
420
421 if (MLX5_GET(tls_extended_cap, buf, tx))
422 caps |= MLX5_ACCEL_TLS_TX;
423 if (MLX5_GET(tls_extended_cap, buf, rx))
424 caps |= MLX5_ACCEL_TLS_RX;
425 if (MLX5_GET(tls_extended_cap, buf, tls_v12))
426 caps |= MLX5_ACCEL_TLS_V12;
427 if (MLX5_GET(tls_extended_cap, buf, tls_v13))
428 caps |= MLX5_ACCEL_TLS_V13;
429 if (MLX5_GET(tls_extended_cap, buf, lro))
430 caps |= MLX5_ACCEL_TLS_LRO;
431 if (MLX5_GET(tls_extended_cap, buf, ipv6))
432 caps |= MLX5_ACCEL_TLS_IPV6;
433
434 if (MLX5_GET(tls_extended_cap, buf, aes_gcm_128))
435 caps |= MLX5_ACCEL_TLS_AES_GCM128;
436 if (MLX5_GET(tls_extended_cap, buf, aes_gcm_256))
437 caps |= MLX5_ACCEL_TLS_AES_GCM256;
438
439 *p_caps = caps;
440 err = 0;
441 out:
442 kfree(buf);
443 return err;
444 }
445
446 int mlx5_fpga_tls_init(struct mlx5_core_dev *mdev)
447 {
448 struct mlx5_fpga_device *fdev = mdev->fpga;
449 struct mlx5_fpga_conn_attr init_attr = {0};
450 struct mlx5_fpga_conn *conn;
451 struct mlx5_fpga_tls *tls;
452 int err = 0;
453
454 if (!mlx5_fpga_is_tls_device(mdev) || !fdev)
455 return 0;
456
457 tls = kzalloc(sizeof(*tls), GFP_KERNEL);
458 if (!tls)
459 return -ENOMEM;
460
461 err = mlx5_fpga_tls_get_caps(fdev, &tls->caps);
462 if (err)
463 goto error;
464
465 if (!(tls->caps & (MLX5_ACCEL_TLS_V12 | MLX5_ACCEL_TLS_AES_GCM128))) {
466 err = -ENOTSUPP;
467 goto error;
468 }
469
470 init_attr.rx_size = SBU_QP_QUEUE_SIZE;
471 init_attr.tx_size = SBU_QP_QUEUE_SIZE;
472 init_attr.recv_cb = mlx5_fpga_tls_hw_qp_recv_cb;
473 init_attr.cb_arg = fdev;
474 conn = mlx5_fpga_sbu_conn_create(fdev, &init_attr);
475 if (IS_ERR(conn)) {
476 err = PTR_ERR(conn);
477 mlx5_fpga_err(fdev, "Error creating TLS command connection %d\n",
478 err);
479 goto error;
480 }
481
482 tls->conn = conn;
483 spin_lock_init(&tls->pending_cmds_lock);
484 INIT_LIST_HEAD(&tls->pending_cmds);
485
486 idr_init(&tls->tx_idr);
487 idr_init(&tls->rx_idr);
488 spin_lock_init(&tls->tx_idr_spinlock);
489 spin_lock_init(&tls->rx_idr_spinlock);
490 fdev->tls = tls;
491 return 0;
492
493 error:
494 kfree(tls);
495 return err;
496 }
497
498 void mlx5_fpga_tls_cleanup(struct mlx5_core_dev *mdev)
499 {
500 struct mlx5_fpga_device *fdev = mdev->fpga;
501
502 if (!fdev || !fdev->tls)
503 return;
504
505 mlx5_fpga_sbu_conn_destroy(fdev->tls->conn);
506 kfree(fdev->tls);
507 fdev->tls = NULL;
508 }
509
510 static void mlx5_fpga_tls_set_aes_gcm128_ctx(void *cmd,
511 struct tls_crypto_info *info,
512 __be64 *rcd_sn)
513 {
514 struct tls12_crypto_info_aes_gcm_128 *crypto_info =
515 (struct tls12_crypto_info_aes_gcm_128 *)info;
516
517 memcpy(MLX5_ADDR_OF(tls_cmd, cmd, tls_rcd_sn), crypto_info->rec_seq,
518 TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
519
520 memcpy(MLX5_ADDR_OF(tls_cmd, cmd, tls_implicit_iv),
521 crypto_info->salt, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
522 memcpy(MLX5_ADDR_OF(tls_cmd, cmd, encryption_key),
523 crypto_info->key, TLS_CIPHER_AES_GCM_128_KEY_SIZE);
524
525
526 memcpy(MLX5_ADDR_OF(tls_cmd, cmd, encryption_key) +
527 TLS_CIPHER_AES_GCM_128_KEY_SIZE,
528 crypto_info->key, TLS_CIPHER_AES_GCM_128_KEY_SIZE);
529
530 MLX5_SET(tls_cmd, cmd, alg, MLX5_TLS_ALG_AES_GCM_128);
531 }
532
533 static int mlx5_fpga_tls_set_key_material(void *cmd, u32 caps,
534 struct tls_crypto_info *crypto_info)
535 {
536 __be64 rcd_sn;
537
538 switch (crypto_info->cipher_type) {
539 case TLS_CIPHER_AES_GCM_128:
540 if (!(caps & MLX5_ACCEL_TLS_AES_GCM128))
541 return -EINVAL;
542 mlx5_fpga_tls_set_aes_gcm128_ctx(cmd, crypto_info, &rcd_sn);
543 break;
544 default:
545 return -EINVAL;
546 }
547
548 return 0;
549 }
550
551 static int _mlx5_fpga_tls_add_flow(struct mlx5_core_dev *mdev, void *flow,
552 struct tls_crypto_info *crypto_info,
553 u32 swid, u32 tcp_sn)
554 {
555 u32 caps = mlx5_fpga_tls_device_caps(mdev);
556 struct mlx5_setup_stream_context *ctx;
557 int ret = -ENOMEM;
558 size_t cmd_size;
559 void *cmd;
560
561 cmd_size = MLX5_TLS_COMMAND_SIZE + sizeof(*ctx);
562 ctx = kzalloc(cmd_size, GFP_KERNEL);
563 if (!ctx)
564 goto out;
565
566 cmd = ctx + 1;
567 ret = mlx5_fpga_tls_set_key_material(cmd, caps, crypto_info);
568 if (ret)
569 goto free_ctx;
570
571 mlx5_fpga_tls_flow_to_cmd(flow, cmd);
572
573 MLX5_SET(tls_cmd, cmd, swid, swid);
574 MLX5_SET(tls_cmd, cmd, tcp_sn, tcp_sn);
575
576 return mlx5_fpga_tls_setup_stream_cmd(mdev, ctx);
577
578 free_ctx:
579 kfree(ctx);
580 out:
581 return ret;
582 }
583
584 int mlx5_fpga_tls_add_flow(struct mlx5_core_dev *mdev, void *flow,
585 struct tls_crypto_info *crypto_info,
586 u32 start_offload_tcp_sn, u32 *p_swid,
587 bool direction_sx)
588 {
589 struct mlx5_fpga_tls *tls = mdev->fpga->tls;
590 int ret = -ENOMEM;
591 u32 swid;
592
593 if (direction_sx)
594 ret = mlx5_fpga_tls_alloc_swid(&tls->tx_idr,
595 &tls->tx_idr_spinlock, flow);
596 else
597 ret = mlx5_fpga_tls_alloc_swid(&tls->rx_idr,
598 &tls->rx_idr_spinlock, flow);
599
600 if (ret < 0)
601 return ret;
602
603 swid = ret;
604 MLX5_SET(tls_flow, flow, direction_sx, direction_sx ? 1 : 0);
605
606 ret = _mlx5_fpga_tls_add_flow(mdev, flow, crypto_info, swid,
607 start_offload_tcp_sn);
608 if (ret && ret != -EINTR)
609 goto free_swid;
610
611 *p_swid = swid;
612 return 0;
613 free_swid:
614 if (direction_sx)
615 mlx5_fpga_tls_release_swid(&tls->tx_idr,
616 &tls->tx_idr_spinlock, swid);
617 else
618 mlx5_fpga_tls_release_swid(&tls->rx_idr,
619 &tls->rx_idr_spinlock, swid);
620
621 return ret;
622 }