blob: bd791470adf8bffedd23c7c00ec03a709432f050 [file] [log] [blame]
developer4f0d2ba2023-08-21 17:33:25 +08001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2023 MediaTek Inc.
4 *
5 * Author: Chris.Chou <chris.chou@mediatek.com>
6 * Ren-Ting Wang <ren-ting.wang@mediatek.com>
7 */
8
9#include <linux/bitops.h>
10
11#include <mtk_eth_soc.h>
12#include <mtk_hnat/hnat.h>
13#include <mtk_hnat/nf_hnat_mtk.h>
14
15#include <pce/cdrt.h>
16#include <pce/cls.h>
17#include <pce/netsys.h>
18
19#include <crypto-eip/ddk/configs/cs_hwpal_ext.h>
20#include <crypto-eip/ddk/kit/iotoken/iotoken.h>
21#include <crypto-eip/ddk/kit/iotoken/iotoken_ext.h>
22
23#include "crypto-eip/crypto-eip.h"
24#include "crypto-eip/ddk-wrapper.h"
25#include "crypto-eip/internal.h"
26
27static LIST_HEAD(xfrm_params_head);
28
29static void mtk_xfrm_offload_cdrt_tear_down(struct mtk_xfrm_params *xfrm_params)
30{
31 memset(&xfrm_params->cdrt->desc, 0, sizeof(struct cdrt_desc));
32
33 mtk_pce_cdrt_entry_write(xfrm_params->cdrt);
34}
35
36static int mtk_xfrm_offload_cdrt_setup(struct mtk_xfrm_params *xfrm_params)
37{
38 struct cdrt_desc *cdesc = &xfrm_params->cdrt->desc;
39
40 cdesc->desc1.common.type = 3;
41 cdesc->desc1.token_len = 48;
42 cdesc->desc1.p_tr[0] = __pa(xfrm_params->p_tr) | 2;
43
44 cdesc->desc2.hw_srv = 2;
45 cdesc->desc2.allow_pad = 1;
46 cdesc->desc2.strip_pad = 1;
47
48 return mtk_pce_cdrt_entry_write(xfrm_params->cdrt);
49}
50
51static int mtk_xfrm_offload_cls_entry_setup(struct mtk_xfrm_params *xfrm_params)
52{
53 struct cls_entry esp_cls_entry = {
54 .entry = xfrm_params->cdrt->idx + 10, /* TODO: need update */
55 .cdesc = {
56 .fport = 0x3,
57 .tport_idx = 0x2,
58 .cdrt_idx = xfrm_params->cdrt->idx,
59
60 .l4_udp_hdr_nez_m = 0x1,
61 .l4_udp_hdr_nez = 0x1,
62 .l4_hdr_usr_data_m = 0xffffffff,
63 .l4_hdr_usr_data = be32_to_cpu(xfrm_params->xs->id.spi),
64 .l4_valid_m = 0x3,
65 .l4_valid = 0x3,
66 .l4_dport_m = 0x0,
67 .l4_dport = 0x0,
68 .tag_m = 0x3,
69 .tag = 0x1,
70 .dip_match_m = 0x0,
71 .dip_match = 0x0,
72 .l4_type_m = 0xff,
73 .l4_type = 0x32,
74 },
75 };
76
77 return mtk_pce_cls_entry_register(&esp_cls_entry);
78}
79
80static void mtk_xfrm_offload_context_tear_down(struct mtk_xfrm_params *xfrm_params)
81{
82 mtk_xfrm_offload_cdrt_tear_down(xfrm_params);
83
84 /* TODO: free context */
85 devm_kfree(crypto_dev, xfrm_params->p_tr);
86
87 /* TODO: transform record tear down */
88}
89
90static int mtk_xfrm_offload_context_setup(struct mtk_xfrm_params *xfrm_params)
91{
92 u32 *tr;
93 int ret;
94
95 xfrm_params->p_tr = devm_kcalloc(crypto_dev, sizeof(u32),
96 TRANSFORM_RECORD_LEN, GFP_KERNEL);
97 if (unlikely(!xfrm_params->p_tr))
98 return -ENOMEM;
99
100 switch (xfrm_params->xs->outer_mode.encap) {
101 case XFRM_MODE_TUNNEL:
102 tr = mtk_ddk_tr_ipsec_build(xfrm_params, SAB_IPSEC_TUNNEL);
103 break;
104 case XFRM_MODE_TRANSPORT:
105 tr = mtk_ddk_tr_ipsec_build(xfrm_params, SAB_IPSEC_TRANSPORT);
106 break;
107 default:
108 ret = -ENOMEM;
109 goto err_out;
110 }
111
112 if (!tr) {
113 ret = -EINVAL;
114 goto err_out;
115 }
116
117 memcpy(xfrm_params->p_tr, tr, sizeof(u32) * TRANSFORM_RECORD_LEN);
118
119 /* TODO: free tr */
120
121 return mtk_xfrm_offload_cdrt_setup(xfrm_params);
122
123err_out:
124 devm_kfree(crypto_dev, xfrm_params->p_tr);
125
126 return ret;
127}
128
129static int mtk_xfrm_offload_state_add_outbound(struct xfrm_state *xs,
130 struct mtk_xfrm_params *xfrm_params)
131{
132 int ret;
133
134 xfrm_params->cdrt = mtk_pce_cdrt_entry_alloc(CDRT_ENCRYPT);
135 if (IS_ERR(xfrm_params->cdrt))
136 return PTR_ERR(xfrm_params->cdrt);
137
138 xfrm_params->dir = SAB_DIRECTION_OUTBOUND;
139
140 ret = mtk_xfrm_offload_context_setup(xfrm_params);
141 if (ret)
142 goto free_cdrt;
143
144 return ret;
145
146free_cdrt:
147 mtk_pce_cdrt_entry_free(xfrm_params->cdrt);
148
149 return ret;
150}
151
152static int mtk_xfrm_offload_state_add_inbound(struct xfrm_state *xs,
153 struct mtk_xfrm_params *xfrm_params)
154{
155 int ret;
156
157 xfrm_params->cdrt = mtk_pce_cdrt_entry_alloc(CDRT_DECRYPT);
158 if (IS_ERR(xfrm_params->cdrt))
159 return PTR_ERR(xfrm_params->cdrt);
160
161 xfrm_params->dir = SAB_DIRECTION_INBOUND;
162
163 ret = mtk_xfrm_offload_context_setup(xfrm_params);
164 if (ret)
165 goto free_cdrt;
166
167 ret = mtk_xfrm_offload_cls_entry_setup(xfrm_params);
168 if (ret)
169 goto tear_down_context;
170
171 return ret;
172
173tear_down_context:
174 mtk_xfrm_offload_context_tear_down(xfrm_params);
175
176free_cdrt:
177 mtk_pce_cdrt_entry_free(xfrm_params->cdrt);
178
179 return ret;
180}
181
182int mtk_xfrm_offload_state_add(struct xfrm_state *xs)
183{
184 struct mtk_xfrm_params *xfrm_params;
185 int ret = 0;
186
187 /* TODO: maybe support IPv6 in the future? */
188 if (xs->props.family != AF_INET) {
189 CRYPTO_NOTICE("Only IPv4 xfrm states may be offloaded\n");
190 return -EINVAL;
191 }
192
193 /* only support ESP right now */
194 if (xs->id.proto != IPPROTO_ESP) {
195 CRYPTO_NOTICE("Unsupported protocol 0x%04x\n", xs->id.proto);
196 return -EINVAL;
197 }
198
199 /* only support tunnel mode or transport mode */
200 if (!(xs->outer_mode.encap == XFRM_MODE_TUNNEL
201 || xs->outer_mode.encap == XFRM_MODE_TRANSPORT))
202 return -EINVAL;
203
204 xfrm_params = devm_kzalloc(crypto_dev,
205 sizeof(struct mtk_xfrm_params),
206 GFP_KERNEL);
207 if (!xfrm_params)
208 return -ENOMEM;
209
210 xfrm_params->xs = xs;
211 INIT_LIST_HEAD(&xfrm_params->node);
212
213 if (xs->xso.flags & XFRM_OFFLOAD_INBOUND)
214 /* rx path */
215 ret = mtk_xfrm_offload_state_add_inbound(xs, xfrm_params);
216 else
217 /* tx path */
218 ret = mtk_xfrm_offload_state_add_outbound(xs, xfrm_params);
219
220 if (ret) {
221 devm_kfree(crypto_dev, xfrm_params);
222 goto out;
223 }
224
225 xs->xso.offload_handle = (unsigned long)xfrm_params;
226 list_add_tail(&xfrm_params->node, &xfrm_params_head);
227out:
228 return ret;
229}
230
231void mtk_xfrm_offload_state_delete(struct xfrm_state *xs)
232{
233}
234
235void mtk_xfrm_offload_state_free(struct xfrm_state *xs)
236{
237 struct mtk_xfrm_params *xfrm_params;
238
239 if (!xs->xso.offload_handle)
240 return;
241
242 xfrm_params = (struct mtk_xfrm_params *)xs->xso.offload_handle;
243
244 list_del(&xfrm_params->node);
245
246 if (xs->xso.flags & XFRM_OFFLOAD_INBOUND)
247 mtk_pce_cdrt_entry_free(xfrm_params->cdrt);
248
249 mtk_xfrm_offload_context_tear_down(xfrm_params);
250
251 mtk_pce_cdrt_entry_free(xfrm_params->cdrt);
252
253 devm_kfree(crypto_dev, xfrm_params);
254}
255
256void mtk_xfrm_offload_state_tear_down(void)
257{
258 struct mtk_xfrm_params *xfrm_params, *tmp;
259
260 list_for_each_entry_safe(xfrm_params, tmp, &xfrm_params_head, node)
261 mtk_xfrm_offload_state_free(xfrm_params->xs);
262}
263
264int mtk_xfrm_offload_policy_add(struct xfrm_policy *xp)
265{
266 return 0;
267}
268
269bool mtk_xfrm_offload_ok(struct sk_buff *skb,
270 struct xfrm_state *xs)
271{
272 struct mtk_xfrm_params *xfrm_params;
273
274 xfrm_params = (struct mtk_xfrm_params *)xs->xso.offload_handle;
275 skb_hnat_cdrt(skb) = xfrm_params->cdrt->idx;
276
277 return false;
278}