1 /*
2  * Copyright (c) 2018 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 
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 	/* There is no guarantee on the order between the TX completion
51 	 * and the command response.
52 	 * The TX completion is going to touch cmd->buf even in
53 	 * the case of successful transmission.
54 	 * So instead of requiring separate allocations for cmd
55 	 * and cmd->buf we've decided to use a reference counter
56 	 */
57 	refcount_t ref;
58 	struct mlx5_fpga_dma_buf buf;
59 	mlx5_fpga_tls_command_complete complete;
60 };
61 
62 static void
mlx5_fpga_tls_put_command_ctx(struct mlx5_fpga_tls_command_context * ctx)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 
mlx5_fpga_tls_cmd_complete(struct mlx5_fpga_device * fdev,struct mlx5_fpga_dma_buf * resp)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 
mlx5_fpga_cmd_send_complete(struct mlx5_fpga_conn * conn,struct mlx5_fpga_device * fdev,struct mlx5_fpga_dma_buf * buf,u8 status)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 
mlx5_fpga_tls_cmd_send(struct mlx5_fpga_device * fdev,struct mlx5_fpga_tls_command_context * cmd,mlx5_fpga_tls_command_complete complete)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 	/* mlx5_fpga_sbu_conn_sendmsg is called under pending_cmds_lock
113 	 * to make sure commands are inserted to the tls->pending_cmds list
114 	 * and the command QP in the same order.
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 /* Start of context identifiers range (inclusive) */
125 #define SWID_START	0
126 /* End of context identifiers range (exclusive) */
127 #define SWID_END	BIT(24)
128 
mlx5_fpga_tls_alloc_swid(struct idr * idr,spinlock_t * idr_spinlock,void * ptr)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 	/* TLS metadata format is 1 byte for syndrome followed
136 	 * by 3 bytes of swid (software ID)
137 	 * swid must not exceed 3 bytes.
138 	 * See tls_rxtx.c:insert_pet() for details
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 
mlx5_fpga_tls_release_swid(struct idr * idr,spinlock_t * idr_spinlock,u32 swid)151 static void mlx5_fpga_tls_release_swid(struct idr *idr,
152 				       spinlock_t *idr_spinlock, u32 swid)
153 {
154 	unsigned long flags;
155 
156 	spin_lock_irqsave(idr_spinlock, flags);
157 	idr_remove(idr, swid);
158 	spin_unlock_irqrestore(idr_spinlock, flags);
159 }
160 
mlx_tls_kfree_complete(struct mlx5_fpga_conn * conn,struct mlx5_fpga_device * fdev,struct mlx5_fpga_dma_buf * buf,u8 status)161 static void mlx_tls_kfree_complete(struct mlx5_fpga_conn *conn,
162 				   struct mlx5_fpga_device *fdev,
163 				   struct mlx5_fpga_dma_buf *buf, u8 status)
164 {
165 	kfree(buf);
166 }
167 
168 struct mlx5_teardown_stream_context {
169 	struct mlx5_fpga_tls_command_context cmd;
170 	u32 swid;
171 };
172 
173 static void
mlx5_fpga_tls_teardown_completion(struct mlx5_fpga_conn * conn,struct mlx5_fpga_device * fdev,struct mlx5_fpga_tls_command_context * cmd,struct mlx5_fpga_dma_buf * resp)174 mlx5_fpga_tls_teardown_completion(struct mlx5_fpga_conn *conn,
175 				  struct mlx5_fpga_device *fdev,
176 				  struct mlx5_fpga_tls_command_context *cmd,
177 				  struct mlx5_fpga_dma_buf *resp)
178 {
179 	struct mlx5_teardown_stream_context *ctx =
180 		    container_of(cmd, struct mlx5_teardown_stream_context, cmd);
181 
182 	if (resp) {
183 		u32 syndrome = MLX5_GET(tls_resp, resp->sg[0].data, syndrome);
184 
185 		if (syndrome)
186 			mlx5_fpga_err(fdev,
187 				      "Teardown stream failed with syndrome = %d",
188 				      syndrome);
189 		else if (MLX5_GET(tls_cmd, cmd->buf.sg[0].data, direction_sx))
190 			mlx5_fpga_tls_release_swid(&fdev->tls->tx_idr,
191 						   &fdev->tls->tx_idr_spinlock,
192 						   ctx->swid);
193 		else
194 			mlx5_fpga_tls_release_swid(&fdev->tls->rx_idr,
195 						   &fdev->tls->rx_idr_spinlock,
196 						   ctx->swid);
197 	}
198 	mlx5_fpga_tls_put_command_ctx(cmd);
199 }
200 
mlx5_fpga_tls_flow_to_cmd(void * flow,void * cmd)201 static void mlx5_fpga_tls_flow_to_cmd(void *flow, void *cmd)
202 {
203 	memcpy(MLX5_ADDR_OF(tls_cmd, cmd, src_port), flow,
204 	       MLX5_BYTE_OFF(tls_flow, ipv6));
205 
206 	MLX5_SET(tls_cmd, cmd, ipv6, MLX5_GET(tls_flow, flow, ipv6));
207 	MLX5_SET(tls_cmd, cmd, direction_sx,
208 		 MLX5_GET(tls_flow, flow, direction_sx));
209 }
210 
mlx5_fpga_tls_resync_rx(struct mlx5_core_dev * mdev,u32 handle,u32 seq,u64 rcd_sn)211 int mlx5_fpga_tls_resync_rx(struct mlx5_core_dev *mdev, u32 handle, u32 seq,
212 			    u64 rcd_sn)
213 {
214 	struct mlx5_fpga_dma_buf *buf;
215 	int size = sizeof(*buf) + MLX5_TLS_COMMAND_SIZE;
216 	void *flow;
217 	void *cmd;
218 	int ret;
219 
220 	buf = kzalloc(size, GFP_ATOMIC);
221 	if (!buf)
222 		return -ENOMEM;
223 
224 	cmd = (buf + 1);
225 
226 	rcu_read_lock();
227 	flow = idr_find(&mdev->fpga->tls->rx_idr, ntohl(handle));
228 	rcu_read_unlock();
229 	mlx5_fpga_tls_flow_to_cmd(flow, cmd);
230 
231 	MLX5_SET(tls_cmd, cmd, swid, ntohl(handle));
232 	MLX5_SET64(tls_cmd, cmd, tls_rcd_sn, be64_to_cpu(rcd_sn));
233 	MLX5_SET(tls_cmd, cmd, tcp_sn, seq);
234 	MLX5_SET(tls_cmd, cmd, command_type, CMD_RESYNC_RX);
235 
236 	buf->sg[0].data = cmd;
237 	buf->sg[0].size = MLX5_TLS_COMMAND_SIZE;
238 	buf->complete = mlx_tls_kfree_complete;
239 
240 	ret = mlx5_fpga_sbu_conn_sendmsg(mdev->fpga->tls->conn, buf);
241 
242 	return ret;
243 }
244 
mlx5_fpga_tls_send_teardown_cmd(struct mlx5_core_dev * mdev,void * flow,u32 swid,gfp_t flags)245 static void mlx5_fpga_tls_send_teardown_cmd(struct mlx5_core_dev *mdev,
246 					    void *flow, u32 swid, gfp_t flags)
247 {
248 	struct mlx5_teardown_stream_context *ctx;
249 	struct mlx5_fpga_dma_buf *buf;
250 	void *cmd;
251 
252 	ctx = kzalloc(sizeof(*ctx) + MLX5_TLS_COMMAND_SIZE, flags);
253 	if (!ctx)
254 		return;
255 
256 	buf = &ctx->cmd.buf;
257 	cmd = (ctx + 1);
258 	MLX5_SET(tls_cmd, cmd, command_type, CMD_TEARDOWN_STREAM);
259 	MLX5_SET(tls_cmd, cmd, swid, swid);
260 
261 	mlx5_fpga_tls_flow_to_cmd(flow, cmd);
262 	kfree(flow);
263 
264 	buf->sg[0].data = cmd;
265 	buf->sg[0].size = MLX5_TLS_COMMAND_SIZE;
266 
267 	ctx->swid = swid;
268 	mlx5_fpga_tls_cmd_send(mdev->fpga, &ctx->cmd,
269 			       mlx5_fpga_tls_teardown_completion);
270 }
271 
mlx5_fpga_tls_del_flow(struct mlx5_core_dev * mdev,u32 swid,gfp_t flags,bool direction_sx)272 void mlx5_fpga_tls_del_flow(struct mlx5_core_dev *mdev, u32 swid,
273 			    gfp_t flags, bool direction_sx)
274 {
275 	struct mlx5_fpga_tls *tls = mdev->fpga->tls;
276 	void *flow;
277 
278 	rcu_read_lock();
279 	if (direction_sx)
280 		flow = idr_find(&tls->tx_idr, swid);
281 	else
282 		flow = idr_find(&tls->rx_idr, swid);
283 
284 	rcu_read_unlock();
285 
286 	if (!flow) {
287 		mlx5_fpga_err(mdev->fpga, "No flow information for swid %u\n",
288 			      swid);
289 		return;
290 	}
291 
292 	mlx5_fpga_tls_send_teardown_cmd(mdev, flow, swid, flags);
293 }
294 
295 enum mlx5_fpga_setup_stream_status {
296 	MLX5_FPGA_CMD_PENDING,
297 	MLX5_FPGA_CMD_SEND_FAILED,
298 	MLX5_FPGA_CMD_RESPONSE_RECEIVED,
299 	MLX5_FPGA_CMD_ABANDONED,
300 };
301 
302 struct mlx5_setup_stream_context {
303 	struct mlx5_fpga_tls_command_context cmd;
304 	atomic_t status;
305 	u32 syndrome;
306 	struct completion comp;
307 };
308 
309 static void
mlx5_fpga_tls_setup_completion(struct mlx5_fpga_conn * conn,struct mlx5_fpga_device * fdev,struct mlx5_fpga_tls_command_context * cmd,struct mlx5_fpga_dma_buf * resp)310 mlx5_fpga_tls_setup_completion(struct mlx5_fpga_conn *conn,
311 			       struct mlx5_fpga_device *fdev,
312 			       struct mlx5_fpga_tls_command_context *cmd,
313 			       struct mlx5_fpga_dma_buf *resp)
314 {
315 	struct mlx5_setup_stream_context *ctx =
316 	    container_of(cmd, struct mlx5_setup_stream_context, cmd);
317 	int status = MLX5_FPGA_CMD_SEND_FAILED;
318 	void *tls_cmd = ctx + 1;
319 
320 	/* If we failed to send to command resp == NULL */
321 	if (resp) {
322 		ctx->syndrome = MLX5_GET(tls_resp, resp->sg[0].data, syndrome);
323 		status = MLX5_FPGA_CMD_RESPONSE_RECEIVED;
324 	}
325 
326 	status = atomic_xchg_release(&ctx->status, status);
327 	if (likely(status != MLX5_FPGA_CMD_ABANDONED)) {
328 		complete(&ctx->comp);
329 		return;
330 	}
331 
332 	mlx5_fpga_err(fdev, "Command was abandoned, syndrome = %u\n",
333 		      ctx->syndrome);
334 
335 	if (!ctx->syndrome) {
336 		/* The process was killed while waiting for the context to be
337 		 * added, and the add completed successfully.
338 		 * We need to destroy the HW context, and we can't can't reuse
339 		 * the command context because we might not have received
340 		 * the tx completion yet.
341 		 */
342 		mlx5_fpga_tls_del_flow(fdev->mdev,
343 				       MLX5_GET(tls_cmd, tls_cmd, swid),
344 				       GFP_ATOMIC,
345 				       MLX5_GET(tls_cmd, tls_cmd,
346 						direction_sx));
347 	}
348 
349 	mlx5_fpga_tls_put_command_ctx(cmd);
350 }
351 
mlx5_fpga_tls_setup_stream_cmd(struct mlx5_core_dev * mdev,struct mlx5_setup_stream_context * ctx)352 static int mlx5_fpga_tls_setup_stream_cmd(struct mlx5_core_dev *mdev,
353 					  struct mlx5_setup_stream_context *ctx)
354 {
355 	struct mlx5_fpga_dma_buf *buf;
356 	void *cmd = ctx + 1;
357 	int status, ret = 0;
358 
359 	buf = &ctx->cmd.buf;
360 	buf->sg[0].data = cmd;
361 	buf->sg[0].size = MLX5_TLS_COMMAND_SIZE;
362 	MLX5_SET(tls_cmd, cmd, command_type, CMD_SETUP_STREAM);
363 
364 	init_completion(&ctx->comp);
365 	atomic_set(&ctx->status, MLX5_FPGA_CMD_PENDING);
366 	ctx->syndrome = -1;
367 
368 	mlx5_fpga_tls_cmd_send(mdev->fpga, &ctx->cmd,
369 			       mlx5_fpga_tls_setup_completion);
370 	wait_for_completion_killable(&ctx->comp);
371 
372 	status = atomic_xchg_acquire(&ctx->status, MLX5_FPGA_CMD_ABANDONED);
373 	if (unlikely(status == MLX5_FPGA_CMD_PENDING))
374 	/* ctx is going to be released in mlx5_fpga_tls_setup_completion */
375 		return -EINTR;
376 
377 	if (unlikely(ctx->syndrome))
378 		ret = -ENOMEM;
379 
380 	mlx5_fpga_tls_put_command_ctx(&ctx->cmd);
381 	return ret;
382 }
383 
mlx5_fpga_tls_hw_qp_recv_cb(void * cb_arg,struct mlx5_fpga_dma_buf * buf)384 static void mlx5_fpga_tls_hw_qp_recv_cb(void *cb_arg,
385 					struct mlx5_fpga_dma_buf *buf)
386 {
387 	struct mlx5_fpga_device *fdev = (struct mlx5_fpga_device *)cb_arg;
388 
389 	mlx5_fpga_tls_cmd_complete(fdev, buf);
390 }
391 
mlx5_fpga_is_tls_device(struct mlx5_core_dev * mdev)392 bool mlx5_fpga_is_tls_device(struct mlx5_core_dev *mdev)
393 {
394 	if (!mdev->fpga || !MLX5_CAP_GEN(mdev, fpga))
395 		return false;
396 
397 	if (MLX5_CAP_FPGA(mdev, ieee_vendor_id) !=
398 	    MLX5_FPGA_CAP_SANDBOX_VENDOR_ID_MLNX)
399 		return false;
400 
401 	if (MLX5_CAP_FPGA(mdev, sandbox_product_id) !=
402 	    MLX5_FPGA_CAP_SANDBOX_PRODUCT_ID_TLS)
403 		return false;
404 
405 	if (MLX5_CAP_FPGA(mdev, sandbox_product_version) != 0)
406 		return false;
407 
408 	return true;
409 }
410 
mlx5_fpga_tls_get_caps(struct mlx5_fpga_device * fdev,u32 * p_caps)411 static int mlx5_fpga_tls_get_caps(struct mlx5_fpga_device *fdev,
412 				  u32 *p_caps)
413 {
414 	int err, cap_size = MLX5_ST_SZ_BYTES(tls_extended_cap);
415 	u32 caps = 0;
416 	void *buf;
417 
418 	buf = kzalloc(cap_size, GFP_KERNEL);
419 	if (!buf)
420 		return -ENOMEM;
421 
422 	err = mlx5_fpga_get_sbu_caps(fdev, cap_size, buf);
423 	if (err)
424 		goto out;
425 
426 	if (MLX5_GET(tls_extended_cap, buf, tx))
427 		caps |= MLX5_ACCEL_TLS_TX;
428 	if (MLX5_GET(tls_extended_cap, buf, rx))
429 		caps |= MLX5_ACCEL_TLS_RX;
430 	if (MLX5_GET(tls_extended_cap, buf, tls_v12))
431 		caps |= MLX5_ACCEL_TLS_V12;
432 	if (MLX5_GET(tls_extended_cap, buf, tls_v13))
433 		caps |= MLX5_ACCEL_TLS_V13;
434 	if (MLX5_GET(tls_extended_cap, buf, lro))
435 		caps |= MLX5_ACCEL_TLS_LRO;
436 	if (MLX5_GET(tls_extended_cap, buf, ipv6))
437 		caps |= MLX5_ACCEL_TLS_IPV6;
438 
439 	if (MLX5_GET(tls_extended_cap, buf, aes_gcm_128))
440 		caps |= MLX5_ACCEL_TLS_AES_GCM128;
441 	if (MLX5_GET(tls_extended_cap, buf, aes_gcm_256))
442 		caps |= MLX5_ACCEL_TLS_AES_GCM256;
443 
444 	*p_caps = caps;
445 	err = 0;
446 out:
447 	kfree(buf);
448 	return err;
449 }
450 
mlx5_fpga_tls_init(struct mlx5_core_dev * mdev)451 int mlx5_fpga_tls_init(struct mlx5_core_dev *mdev)
452 {
453 	struct mlx5_fpga_device *fdev = mdev->fpga;
454 	struct mlx5_fpga_conn_attr init_attr = {0};
455 	struct mlx5_fpga_conn *conn;
456 	struct mlx5_fpga_tls *tls;
457 	int err = 0;
458 
459 	if (!mlx5_fpga_is_tls_device(mdev) || !fdev)
460 		return 0;
461 
462 	tls = kzalloc(sizeof(*tls), GFP_KERNEL);
463 	if (!tls)
464 		return -ENOMEM;
465 
466 	err = mlx5_fpga_tls_get_caps(fdev, &tls->caps);
467 	if (err)
468 		goto error;
469 
470 	if (!(tls->caps & (MLX5_ACCEL_TLS_V12 | MLX5_ACCEL_TLS_AES_GCM128))) {
471 		err = -ENOTSUPP;
472 		goto error;
473 	}
474 
475 	init_attr.rx_size = SBU_QP_QUEUE_SIZE;
476 	init_attr.tx_size = SBU_QP_QUEUE_SIZE;
477 	init_attr.recv_cb = mlx5_fpga_tls_hw_qp_recv_cb;
478 	init_attr.cb_arg = fdev;
479 	conn = mlx5_fpga_sbu_conn_create(fdev, &init_attr);
480 	if (IS_ERR(conn)) {
481 		err = PTR_ERR(conn);
482 		mlx5_fpga_err(fdev, "Error creating TLS command connection %d\n",
483 			      err);
484 		goto error;
485 	}
486 
487 	tls->conn = conn;
488 	spin_lock_init(&tls->pending_cmds_lock);
489 	INIT_LIST_HEAD(&tls->pending_cmds);
490 
491 	idr_init(&tls->tx_idr);
492 	idr_init(&tls->rx_idr);
493 	spin_lock_init(&tls->tx_idr_spinlock);
494 	spin_lock_init(&tls->rx_idr_spinlock);
495 	fdev->tls = tls;
496 	return 0;
497 
498 error:
499 	kfree(tls);
500 	return err;
501 }
502 
mlx5_fpga_tls_cleanup(struct mlx5_core_dev * mdev)503 void mlx5_fpga_tls_cleanup(struct mlx5_core_dev *mdev)
504 {
505 	struct mlx5_fpga_device *fdev = mdev->fpga;
506 
507 	if (!fdev || !fdev->tls)
508 		return;
509 
510 	mlx5_fpga_sbu_conn_destroy(fdev->tls->conn);
511 	kfree(fdev->tls);
512 	fdev->tls = NULL;
513 }
514 
mlx5_fpga_tls_set_aes_gcm128_ctx(void * cmd,struct tls_crypto_info * info,__be64 * rcd_sn)515 static void mlx5_fpga_tls_set_aes_gcm128_ctx(void *cmd,
516 					     struct tls_crypto_info *info,
517 					     __be64 *rcd_sn)
518 {
519 	struct tls12_crypto_info_aes_gcm_128 *crypto_info =
520 	    (struct tls12_crypto_info_aes_gcm_128 *)info;
521 
522 	memcpy(MLX5_ADDR_OF(tls_cmd, cmd, tls_rcd_sn), crypto_info->rec_seq,
523 	       TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
524 
525 	memcpy(MLX5_ADDR_OF(tls_cmd, cmd, tls_implicit_iv),
526 	       crypto_info->salt, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
527 	memcpy(MLX5_ADDR_OF(tls_cmd, cmd, encryption_key),
528 	       crypto_info->key, TLS_CIPHER_AES_GCM_128_KEY_SIZE);
529 
530 	/* in AES-GCM 128 we need to write the key twice */
531 	memcpy(MLX5_ADDR_OF(tls_cmd, cmd, encryption_key) +
532 		   TLS_CIPHER_AES_GCM_128_KEY_SIZE,
533 	       crypto_info->key, TLS_CIPHER_AES_GCM_128_KEY_SIZE);
534 
535 	MLX5_SET(tls_cmd, cmd, alg, MLX5_TLS_ALG_AES_GCM_128);
536 }
537 
mlx5_fpga_tls_set_key_material(void * cmd,u32 caps,struct tls_crypto_info * crypto_info)538 static int mlx5_fpga_tls_set_key_material(void *cmd, u32 caps,
539 					  struct tls_crypto_info *crypto_info)
540 {
541 	__be64 rcd_sn;
542 
543 	switch (crypto_info->cipher_type) {
544 	case TLS_CIPHER_AES_GCM_128:
545 		if (!(caps & MLX5_ACCEL_TLS_AES_GCM128))
546 			return -EINVAL;
547 		mlx5_fpga_tls_set_aes_gcm128_ctx(cmd, crypto_info, &rcd_sn);
548 		break;
549 	default:
550 		return -EINVAL;
551 	}
552 
553 	return 0;
554 }
555 
_mlx5_fpga_tls_add_flow(struct mlx5_core_dev * mdev,void * flow,struct tls_crypto_info * crypto_info,u32 swid,u32 tcp_sn)556 static int _mlx5_fpga_tls_add_flow(struct mlx5_core_dev *mdev, void *flow,
557 				   struct tls_crypto_info *crypto_info,
558 				   u32 swid, u32 tcp_sn)
559 {
560 	u32 caps = mlx5_fpga_tls_device_caps(mdev);
561 	struct mlx5_setup_stream_context *ctx;
562 	int ret = -ENOMEM;
563 	size_t cmd_size;
564 	void *cmd;
565 
566 	cmd_size = MLX5_TLS_COMMAND_SIZE + sizeof(*ctx);
567 	ctx = kzalloc(cmd_size, GFP_KERNEL);
568 	if (!ctx)
569 		goto out;
570 
571 	cmd = ctx + 1;
572 	ret = mlx5_fpga_tls_set_key_material(cmd, caps, crypto_info);
573 	if (ret)
574 		goto free_ctx;
575 
576 	mlx5_fpga_tls_flow_to_cmd(flow, cmd);
577 
578 	MLX5_SET(tls_cmd, cmd, swid, swid);
579 	MLX5_SET(tls_cmd, cmd, tcp_sn, tcp_sn);
580 
581 	return mlx5_fpga_tls_setup_stream_cmd(mdev, ctx);
582 
583 free_ctx:
584 	kfree(ctx);
585 out:
586 	return ret;
587 }
588 
mlx5_fpga_tls_add_flow(struct mlx5_core_dev * mdev,void * flow,struct tls_crypto_info * crypto_info,u32 start_offload_tcp_sn,u32 * p_swid,bool direction_sx)589 int mlx5_fpga_tls_add_flow(struct mlx5_core_dev *mdev, void *flow,
590 			   struct tls_crypto_info *crypto_info,
591 			   u32 start_offload_tcp_sn, u32 *p_swid,
592 			   bool direction_sx)
593 {
594 	struct mlx5_fpga_tls *tls = mdev->fpga->tls;
595 	int ret = -ENOMEM;
596 	u32 swid;
597 
598 	if (direction_sx)
599 		ret = mlx5_fpga_tls_alloc_swid(&tls->tx_idr,
600 					       &tls->tx_idr_spinlock, flow);
601 	else
602 		ret = mlx5_fpga_tls_alloc_swid(&tls->rx_idr,
603 					       &tls->rx_idr_spinlock, flow);
604 
605 	if (ret < 0)
606 		return ret;
607 
608 	swid = ret;
609 	MLX5_SET(tls_flow, flow, direction_sx, direction_sx ? 1 : 0);
610 
611 	ret = _mlx5_fpga_tls_add_flow(mdev, flow, crypto_info, swid,
612 				      start_offload_tcp_sn);
613 	if (ret && ret != -EINTR)
614 		goto free_swid;
615 
616 	*p_swid = swid;
617 	return 0;
618 free_swid:
619 	if (direction_sx)
620 		mlx5_fpga_tls_release_swid(&tls->tx_idr,
621 					   &tls->tx_idr_spinlock, swid);
622 	else
623 		mlx5_fpga_tls_release_swid(&tls->rx_idr,
624 					   &tls->rx_idr_spinlock, swid);
625 
626 	return ret;
627 }
628