1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later |
2 | /* |
3 | * Copyright 2017 NXP |
4 | */ |
5 | |
6 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
7 | |
8 | #include <linux/slab.h> |
9 | |
10 | #include "fman_keygen.h" |
11 | |
12 | /* Maximum number of HW Ports */ |
13 | #define FMAN_MAX_NUM_OF_HW_PORTS 64 |
14 | |
15 | /* Maximum number of KeyGen Schemes */ |
16 | #define FM_KG_MAX_NUM_OF_SCHEMES 32 |
17 | |
18 | /* Number of generic KeyGen Generic Extract Command Registers */ |
19 | #define FM_KG_NUM_OF_GENERIC_REGS 8 |
20 | |
21 | /* Dummy port ID */ |
22 | #define DUMMY_PORT_ID 0 |
23 | |
24 | /* Select Scheme Value Register */ |
25 | #define KG_SCH_DEF_USE_KGSE_DV_0 2 |
26 | #define KG_SCH_DEF_USE_KGSE_DV_1 3 |
27 | |
28 | /* Registers Shifting values */ |
29 | #define FM_KG_KGAR_NUM_SHIFT 16 |
30 | #define KG_SCH_DEF_L4_PORT_SHIFT 8 |
31 | #define KG_SCH_DEF_IP_ADDR_SHIFT 18 |
32 | #define KG_SCH_HASH_CONFIG_SHIFT_SHIFT 24 |
33 | |
34 | /* KeyGen Registers bit field masks: */ |
35 | |
36 | /* Enable bit field mask for KeyGen General Configuration Register */ |
37 | #define FM_KG_KGGCR_EN 0x80000000 |
38 | |
39 | /* KeyGen Global Registers bit field masks */ |
40 | #define FM_KG_KGAR_GO 0x80000000 |
41 | #define FM_KG_KGAR_READ 0x40000000 |
42 | #define FM_KG_KGAR_WRITE 0x00000000 |
43 | #define FM_KG_KGAR_SEL_SCHEME_ENTRY 0x00000000 |
44 | #define FM_KG_KGAR_SCM_WSEL_UPDATE_CNT 0x00008000 |
45 | |
46 | #define FM_KG_KGAR_ERR 0x20000000 |
47 | #define FM_KG_KGAR_SEL_CLS_PLAN_ENTRY 0x01000000 |
48 | #define FM_KG_KGAR_SEL_PORT_ENTRY 0x02000000 |
49 | #define FM_KG_KGAR_SEL_PORT_WSEL_SP 0x00008000 |
50 | #define FM_KG_KGAR_SEL_PORT_WSEL_CPP 0x00004000 |
51 | |
52 | /* Error events exceptions */ |
53 | #define FM_EX_KG_DOUBLE_ECC 0x80000000 |
54 | #define FM_EX_KG_KEYSIZE_OVERFLOW 0x40000000 |
55 | |
56 | /* Scheme Registers bit field masks */ |
57 | #define KG_SCH_MODE_EN 0x80000000 |
58 | #define KG_SCH_VSP_NO_KSP_EN 0x80000000 |
59 | #define KG_SCH_HASH_CONFIG_SYM 0x40000000 |
60 | |
61 | /* Known Protocol field codes */ |
62 | #define KG_SCH_KN_PORT_ID 0x80000000 |
63 | #define KG_SCH_KN_MACDST 0x40000000 |
64 | #define KG_SCH_KN_MACSRC 0x20000000 |
65 | #define KG_SCH_KN_TCI1 0x10000000 |
66 | #define KG_SCH_KN_TCI2 0x08000000 |
67 | #define KG_SCH_KN_ETYPE 0x04000000 |
68 | #define KG_SCH_KN_PPPSID 0x02000000 |
69 | #define KG_SCH_KN_PPPID 0x01000000 |
70 | #define KG_SCH_KN_MPLS1 0x00800000 |
71 | #define KG_SCH_KN_MPLS2 0x00400000 |
72 | #define KG_SCH_KN_MPLS_LAST 0x00200000 |
73 | #define KG_SCH_KN_IPSRC1 0x00100000 |
74 | #define KG_SCH_KN_IPDST1 0x00080000 |
75 | #define KG_SCH_KN_PTYPE1 0x00040000 |
76 | #define KG_SCH_KN_IPTOS_TC1 0x00020000 |
77 | #define KG_SCH_KN_IPV6FL1 0x00010000 |
78 | #define KG_SCH_KN_IPSRC2 0x00008000 |
79 | #define KG_SCH_KN_IPDST2 0x00004000 |
80 | #define KG_SCH_KN_PTYPE2 0x00002000 |
81 | #define KG_SCH_KN_IPTOS_TC2 0x00001000 |
82 | #define KG_SCH_KN_IPV6FL2 0x00000800 |
83 | #define KG_SCH_KN_GREPTYPE 0x00000400 |
84 | #define KG_SCH_KN_IPSEC_SPI 0x00000200 |
85 | #define KG_SCH_KN_IPSEC_NH 0x00000100 |
86 | #define KG_SCH_KN_IPPID 0x00000080 |
87 | #define KG_SCH_KN_L4PSRC 0x00000004 |
88 | #define KG_SCH_KN_L4PDST 0x00000002 |
89 | #define KG_SCH_KN_TFLG 0x00000001 |
90 | |
91 | /* NIA values */ |
92 | #define NIA_ENG_BMI 0x00500000 |
93 | #define NIA_BMI_AC_ENQ_FRAME 0x00000002 |
94 | #define ENQUEUE_KG_DFLT_NIA (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME) |
95 | |
96 | /* Hard-coded configuration: |
97 | * These values are used as hard-coded values for KeyGen configuration |
98 | * and they replace user selections for this hard-coded version |
99 | */ |
100 | |
101 | /* Hash distribution shift */ |
102 | #define DEFAULT_HASH_DIST_FQID_SHIFT 0 |
103 | |
104 | /* Hash shift */ |
105 | #define DEFAULT_HASH_SHIFT 0 |
106 | |
107 | /* Symmetric hash usage: |
108 | * Warning: |
109 | * - the value for symmetric hash usage must be in accordance with hash |
110 | * key defined below |
111 | * - according to tests performed, spreading is not working if symmetric |
112 | * hash is set on true |
113 | * So ultimately symmetric hash functionality should be always disabled: |
114 | */ |
115 | #define DEFAULT_SYMMETRIC_HASH false |
116 | |
117 | /* Hash Key extraction fields: */ |
118 | #define \ |
119 | (KG_SCH_KN_IPSRC1 | KG_SCH_KN_IPDST1 | \ |
120 | KG_SCH_KN_L4PSRC | KG_SCH_KN_L4PDST | \ |
121 | KG_SCH_KN_IPSEC_SPI) |
122 | |
123 | /* Default values to be used as hash key in case IPv4 or L4 (TCP, UDP) |
124 | * don't exist in the frame |
125 | */ |
126 | /* Default IPv4 address */ |
127 | #define DEFAULT_HASH_KEY_IPv4_ADDR 0x0A0A0A0A |
128 | /* Default L4 port */ |
129 | #define DEFAULT_HASH_KEY_L4_PORT 0x0B0B0B0B |
130 | |
131 | /* KeyGen Memory Mapped Registers: */ |
132 | |
133 | /* Scheme Configuration RAM Registers */ |
134 | struct fman_kg_scheme_regs { |
135 | u32 kgse_mode; /* 0x100: MODE */ |
136 | u32 kgse_ekfc; /* 0x104: Extract Known Fields Command */ |
137 | u32 kgse_ekdv; /* 0x108: Extract Known Default Value */ |
138 | u32 kgse_bmch; /* 0x10C: Bit Mask Command High */ |
139 | u32 kgse_bmcl; /* 0x110: Bit Mask Command Low */ |
140 | u32 kgse_fqb; /* 0x114: Frame Queue Base */ |
141 | u32 kgse_hc; /* 0x118: Hash Command */ |
142 | u32 kgse_ppc; /* 0x11C: Policer Profile Command */ |
143 | u32 kgse_gec[FM_KG_NUM_OF_GENERIC_REGS]; |
144 | /* 0x120: Generic Extract Command */ |
145 | u32 kgse_spc; |
146 | /* 0x140: KeyGen Scheme Entry Statistic Packet Counter */ |
147 | u32 kgse_dv0; /* 0x144: KeyGen Scheme Entry Default Value 0 */ |
148 | u32 kgse_dv1; /* 0x148: KeyGen Scheme Entry Default Value 1 */ |
149 | u32 kgse_ccbs; |
150 | /* 0x14C: KeyGen Scheme Entry Coarse Classification Bit*/ |
151 | u32 kgse_mv; /* 0x150: KeyGen Scheme Entry Match vector */ |
152 | u32 kgse_om; /* 0x154: KeyGen Scheme Entry Operation Mode bits */ |
153 | u32 kgse_vsp; |
154 | /* 0x158: KeyGen Scheme Entry Virtual Storage Profile */ |
155 | }; |
156 | |
157 | /* Port Partition Configuration Registers */ |
158 | struct fman_kg_pe_regs { |
159 | u32 fmkg_pe_sp; /* 0x100: KeyGen Port entry Scheme Partition */ |
160 | u32 fmkg_pe_cpp; |
161 | /* 0x104: KeyGen Port Entry Classification Plan Partition */ |
162 | }; |
163 | |
164 | /* General Configuration and Status Registers |
165 | * Global Statistic Counters |
166 | * KeyGen Global Registers |
167 | */ |
168 | struct fman_kg_regs { |
169 | u32 fmkg_gcr; /* 0x000: KeyGen General Configuration Register */ |
170 | u32 res004; /* 0x004: Reserved */ |
171 | u32 res008; /* 0x008: Reserved */ |
172 | u32 fmkg_eer; /* 0x00C: KeyGen Error Event Register */ |
173 | u32 fmkg_eeer; /* 0x010: KeyGen Error Event Enable Register */ |
174 | u32 res014; /* 0x014: Reserved */ |
175 | u32 res018; /* 0x018: Reserved */ |
176 | u32 fmkg_seer; /* 0x01C: KeyGen Scheme Error Event Register */ |
177 | u32 fmkg_seeer; /* 0x020: KeyGen Scheme Error Event Enable Register */ |
178 | u32 fmkg_gsr; /* 0x024: KeyGen Global Status Register */ |
179 | u32 fmkg_tpc; /* 0x028: Total Packet Counter Register */ |
180 | u32 fmkg_serc; /* 0x02C: Soft Error Capture Register */ |
181 | u32 res030[4]; /* 0x030: Reserved */ |
182 | u32 fmkg_fdor; /* 0x034: Frame Data Offset Register */ |
183 | u32 fmkg_gdv0r; /* 0x038: Global Default Value Register 0 */ |
184 | u32 fmkg_gdv1r; /* 0x03C: Global Default Value Register 1 */ |
185 | u32 res04c[6]; /* 0x040: Reserved */ |
186 | u32 fmkg_feer; /* 0x044: Force Error Event Register */ |
187 | u32 res068[38]; /* 0x048: Reserved */ |
188 | union { |
189 | u32 fmkg_indirect[63]; /* 0x100: Indirect Access Registers */ |
190 | struct fman_kg_scheme_regs fmkg_sch; /* Scheme Registers */ |
191 | struct fman_kg_pe_regs fmkg_pe; /* Port Partition Registers */ |
192 | }; |
193 | u32 fmkg_ar; /* 0x1FC: KeyGen Action Register */ |
194 | }; |
195 | |
196 | /* KeyGen Scheme data */ |
197 | struct keygen_scheme { |
198 | bool used; /* Specifies if this scheme is used */ |
199 | u8 hw_port_id; |
200 | /* Hardware port ID |
201 | * schemes sharing between multiple ports is not |
202 | * currently supported |
203 | * so we have only one port id bound to a scheme |
204 | */ |
205 | u32 base_fqid; |
206 | /* Base FQID: |
207 | * Must be between 1 and 2^24-1 |
208 | * If hash is used and an even distribution is |
209 | * expected according to hash_fqid_count, |
210 | * base_fqid must be aligned to hash_fqid_count |
211 | */ |
212 | u32 hash_fqid_count; |
213 | /* FQ range for hash distribution: |
214 | * Must be a power of 2 |
215 | * Represents the range of queues for spreading |
216 | */ |
217 | bool use_hashing; /* Usage of Hashing and spreading over FQ */ |
218 | bool symmetric_hash; /* Symmetric Hash option usage */ |
219 | u8 hashShift; |
220 | /* Hash result right shift. |
221 | * Select the 24 bits out of the 64 hash result. |
222 | * 0 means using the 24 LSB's, otherwise |
223 | * use the 24 LSB's after shifting right |
224 | */ |
225 | u32 match_vector; /* Match Vector */ |
226 | }; |
227 | |
228 | /* KeyGen driver data */ |
229 | struct fman_keygen { |
230 | struct keygen_scheme schemes[FM_KG_MAX_NUM_OF_SCHEMES]; |
231 | /* Array of schemes */ |
232 | struct fman_kg_regs __iomem *keygen_regs; /* KeyGen registers */ |
233 | }; |
234 | |
235 | /* keygen_write_ar_wait |
236 | * |
237 | * Write Action Register with specified value, wait for GO bit field to be |
238 | * idle and then read the error |
239 | * |
240 | * regs: KeyGen registers |
241 | * fmkg_ar: Action Register value |
242 | * |
243 | * Return: Zero for success or error code in case of failure |
244 | */ |
245 | static int keygen_write_ar_wait(struct fman_kg_regs __iomem *regs, u32 fmkg_ar) |
246 | { |
247 | iowrite32be(fmkg_ar, ®s->fmkg_ar); |
248 | |
249 | /* Wait for GO bit field to be idle */ |
250 | while (fmkg_ar & FM_KG_KGAR_GO) |
251 | fmkg_ar = ioread32be(®s->fmkg_ar); |
252 | |
253 | if (fmkg_ar & FM_KG_KGAR_ERR) |
254 | return -EINVAL; |
255 | |
256 | return 0; |
257 | } |
258 | |
259 | /* build_ar_scheme |
260 | * |
261 | * Build Action Register value for scheme settings |
262 | * |
263 | * scheme_id: Scheme ID |
264 | * update_counter: update scheme counter |
265 | * write: true for action to write the scheme or false for read action |
266 | * |
267 | * Return: AR value |
268 | */ |
269 | static u32 build_ar_scheme(u8 scheme_id, bool update_counter, bool write) |
270 | { |
271 | u32 rw = (u32)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ); |
272 | |
273 | return (u32)(FM_KG_KGAR_GO | |
274 | rw | |
275 | FM_KG_KGAR_SEL_SCHEME_ENTRY | |
276 | DUMMY_PORT_ID | |
277 | ((u32)scheme_id << FM_KG_KGAR_NUM_SHIFT) | |
278 | (update_counter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT : 0)); |
279 | } |
280 | |
281 | /* build_ar_bind_scheme |
282 | * |
283 | * Build Action Register value for port binding to schemes |
284 | * |
285 | * hwport_id: HW Port ID |
286 | * write: true for action to write the bind or false for read action |
287 | * |
288 | * Return: AR value |
289 | */ |
290 | static u32 build_ar_bind_scheme(u8 hwport_id, bool write) |
291 | { |
292 | u32 rw = write ? (u32)FM_KG_KGAR_WRITE : (u32)FM_KG_KGAR_READ; |
293 | |
294 | return (u32)(FM_KG_KGAR_GO | |
295 | rw | |
296 | FM_KG_KGAR_SEL_PORT_ENTRY | |
297 | hwport_id | |
298 | FM_KG_KGAR_SEL_PORT_WSEL_SP); |
299 | } |
300 | |
301 | /* keygen_write_sp |
302 | * |
303 | * Write Scheme Partition Register with specified value |
304 | * |
305 | * regs: KeyGen Registers |
306 | * sp: Scheme Partition register value |
307 | * add: true to add a scheme partition or false to clear |
308 | * |
309 | * Return: none |
310 | */ |
311 | static void keygen_write_sp(struct fman_kg_regs __iomem *regs, u32 sp, bool add) |
312 | { |
313 | u32 tmp; |
314 | |
315 | tmp = ioread32be(®s->fmkg_pe.fmkg_pe_sp); |
316 | |
317 | if (add) |
318 | tmp |= sp; |
319 | else |
320 | tmp &= ~sp; |
321 | |
322 | iowrite32be(tmp, ®s->fmkg_pe.fmkg_pe_sp); |
323 | } |
324 | |
325 | /* build_ar_bind_cls_plan |
326 | * |
327 | * Build Action Register value for Classification Plan |
328 | * |
329 | * hwport_id: HW Port ID |
330 | * write: true for action to write the CP or false for read action |
331 | * |
332 | * Return: AR value |
333 | */ |
334 | static u32 build_ar_bind_cls_plan(u8 hwport_id, bool write) |
335 | { |
336 | u32 rw = write ? (u32)FM_KG_KGAR_WRITE : (u32)FM_KG_KGAR_READ; |
337 | |
338 | return (u32)(FM_KG_KGAR_GO | |
339 | rw | |
340 | FM_KG_KGAR_SEL_PORT_ENTRY | |
341 | hwport_id | |
342 | FM_KG_KGAR_SEL_PORT_WSEL_CPP); |
343 | } |
344 | |
345 | /* keygen_write_cpp |
346 | * |
347 | * Write Classification Plan Partition Register with specified value |
348 | * |
349 | * regs: KeyGen Registers |
350 | * cpp: CPP register value |
351 | * |
352 | * Return: none |
353 | */ |
354 | static void keygen_write_cpp(struct fman_kg_regs __iomem *regs, u32 cpp) |
355 | { |
356 | iowrite32be(cpp, ®s->fmkg_pe.fmkg_pe_cpp); |
357 | } |
358 | |
359 | /* keygen_write_scheme |
360 | * |
361 | * Write all Schemes Registers with specified values |
362 | * |
363 | * regs: KeyGen Registers |
364 | * scheme_id: Scheme ID |
365 | * scheme_regs: Scheme registers values desired to be written |
366 | * update_counter: update scheme counter |
367 | * |
368 | * Return: Zero for success or error code in case of failure |
369 | */ |
370 | static int keygen_write_scheme(struct fman_kg_regs __iomem *regs, u8 scheme_id, |
371 | struct fman_kg_scheme_regs *scheme_regs, |
372 | bool update_counter) |
373 | { |
374 | u32 ar_reg; |
375 | int err, i; |
376 | |
377 | /* Write indirect scheme registers */ |
378 | iowrite32be(scheme_regs->kgse_mode, ®s->fmkg_sch.kgse_mode); |
379 | iowrite32be(scheme_regs->kgse_ekfc, ®s->fmkg_sch.kgse_ekfc); |
380 | iowrite32be(scheme_regs->kgse_ekdv, ®s->fmkg_sch.kgse_ekdv); |
381 | iowrite32be(scheme_regs->kgse_bmch, ®s->fmkg_sch.kgse_bmch); |
382 | iowrite32be(scheme_regs->kgse_bmcl, ®s->fmkg_sch.kgse_bmcl); |
383 | iowrite32be(scheme_regs->kgse_fqb, ®s->fmkg_sch.kgse_fqb); |
384 | iowrite32be(scheme_regs->kgse_hc, ®s->fmkg_sch.kgse_hc); |
385 | iowrite32be(scheme_regs->kgse_ppc, ®s->fmkg_sch.kgse_ppc); |
386 | iowrite32be(scheme_regs->kgse_spc, ®s->fmkg_sch.kgse_spc); |
387 | iowrite32be(scheme_regs->kgse_dv0, ®s->fmkg_sch.kgse_dv0); |
388 | iowrite32be(scheme_regs->kgse_dv1, ®s->fmkg_sch.kgse_dv1); |
389 | iowrite32be(scheme_regs->kgse_ccbs, ®s->fmkg_sch.kgse_ccbs); |
390 | iowrite32be(scheme_regs->kgse_mv, ®s->fmkg_sch.kgse_mv); |
391 | iowrite32be(scheme_regs->kgse_om, ®s->fmkg_sch.kgse_om); |
392 | iowrite32be(scheme_regs->kgse_vsp, ®s->fmkg_sch.kgse_vsp); |
393 | |
394 | for (i = 0 ; i < FM_KG_NUM_OF_GENERIC_REGS ; i++) |
395 | iowrite32be(scheme_regs->kgse_gec[i], |
396 | ®s->fmkg_sch.kgse_gec[i]); |
397 | |
398 | /* Write AR (Action register) */ |
399 | ar_reg = build_ar_scheme(scheme_id, update_counter, write: true); |
400 | err = keygen_write_ar_wait(regs, fmkg_ar: ar_reg); |
401 | if (err != 0) { |
402 | pr_err("Writing Action Register failed\n" ); |
403 | return err; |
404 | } |
405 | |
406 | return err; |
407 | } |
408 | |
409 | /* get_free_scheme_id |
410 | * |
411 | * Find the first free scheme available to be used |
412 | * |
413 | * keygen: KeyGen handle |
414 | * scheme_id: pointer to scheme id |
415 | * |
416 | * Return: 0 on success, -EINVAL when the are no available free schemes |
417 | */ |
418 | static int get_free_scheme_id(struct fman_keygen *keygen, u8 *scheme_id) |
419 | { |
420 | u8 i; |
421 | |
422 | for (i = 0; i < FM_KG_MAX_NUM_OF_SCHEMES; i++) |
423 | if (!keygen->schemes[i].used) { |
424 | *scheme_id = i; |
425 | return 0; |
426 | } |
427 | |
428 | return -EINVAL; |
429 | } |
430 | |
431 | /* get_scheme |
432 | * |
433 | * Provides the scheme for specified ID |
434 | * |
435 | * keygen: KeyGen handle |
436 | * scheme_id: Scheme ID |
437 | * |
438 | * Return: handle to required scheme |
439 | */ |
440 | static struct keygen_scheme *get_scheme(struct fman_keygen *keygen, |
441 | u8 scheme_id) |
442 | { |
443 | if (scheme_id >= FM_KG_MAX_NUM_OF_SCHEMES) |
444 | return NULL; |
445 | return &keygen->schemes[scheme_id]; |
446 | } |
447 | |
448 | /* keygen_bind_port_to_schemes |
449 | * |
450 | * Bind the port to schemes |
451 | * |
452 | * keygen: KeyGen handle |
453 | * scheme_id: id of the scheme to bind to |
454 | * bind: true to bind the port or false to unbind it |
455 | * |
456 | * Return: Zero for success or error code in case of failure |
457 | */ |
458 | static int keygen_bind_port_to_schemes(struct fman_keygen *keygen, |
459 | u8 scheme_id, |
460 | bool bind) |
461 | { |
462 | struct fman_kg_regs __iomem *keygen_regs = keygen->keygen_regs; |
463 | struct keygen_scheme *scheme; |
464 | u32 ar_reg; |
465 | u32 schemes_vector = 0; |
466 | int err; |
467 | |
468 | scheme = get_scheme(keygen, scheme_id); |
469 | if (!scheme) { |
470 | pr_err("Requested Scheme does not exist\n" ); |
471 | return -EINVAL; |
472 | } |
473 | if (!scheme->used) { |
474 | pr_err("Cannot bind port to an invalid scheme\n" ); |
475 | return -EINVAL; |
476 | } |
477 | |
478 | schemes_vector |= 1 << (31 - scheme_id); |
479 | |
480 | ar_reg = build_ar_bind_scheme(hwport_id: scheme->hw_port_id, write: false); |
481 | err = keygen_write_ar_wait(regs: keygen_regs, fmkg_ar: ar_reg); |
482 | if (err != 0) { |
483 | pr_err("Reading Action Register failed\n" ); |
484 | return err; |
485 | } |
486 | |
487 | keygen_write_sp(regs: keygen_regs, sp: schemes_vector, add: bind); |
488 | |
489 | ar_reg = build_ar_bind_scheme(hwport_id: scheme->hw_port_id, write: true); |
490 | err = keygen_write_ar_wait(regs: keygen_regs, fmkg_ar: ar_reg); |
491 | if (err != 0) { |
492 | pr_err("Writing Action Register failed\n" ); |
493 | return err; |
494 | } |
495 | |
496 | return 0; |
497 | } |
498 | |
499 | /* keygen_scheme_setup |
500 | * |
501 | * Setup the scheme according to required configuration |
502 | * |
503 | * keygen: KeyGen handle |
504 | * scheme_id: scheme ID |
505 | * enable: true to enable scheme or false to disable it |
506 | * |
507 | * Return: Zero for success or error code in case of failure |
508 | */ |
509 | static int keygen_scheme_setup(struct fman_keygen *keygen, u8 scheme_id, |
510 | bool enable) |
511 | { |
512 | struct fman_kg_regs __iomem *keygen_regs = keygen->keygen_regs; |
513 | struct fman_kg_scheme_regs scheme_regs; |
514 | struct keygen_scheme *scheme; |
515 | u32 tmp_reg; |
516 | int err; |
517 | |
518 | scheme = get_scheme(keygen, scheme_id); |
519 | if (!scheme) { |
520 | pr_err("Requested Scheme does not exist\n" ); |
521 | return -EINVAL; |
522 | } |
523 | if (enable && scheme->used) { |
524 | pr_err("The requested Scheme is already used\n" ); |
525 | return -EINVAL; |
526 | } |
527 | |
528 | /* Clear scheme registers */ |
529 | memset(&scheme_regs, 0, sizeof(struct fman_kg_scheme_regs)); |
530 | |
531 | /* Setup all scheme registers: */ |
532 | tmp_reg = 0; |
533 | |
534 | if (enable) { |
535 | /* Enable Scheme */ |
536 | tmp_reg |= KG_SCH_MODE_EN; |
537 | /* Enqueue frame NIA */ |
538 | tmp_reg |= ENQUEUE_KG_DFLT_NIA; |
539 | } |
540 | |
541 | scheme_regs.kgse_mode = tmp_reg; |
542 | |
543 | scheme_regs.kgse_mv = scheme->match_vector; |
544 | |
545 | /* Scheme don't override StorageProfile: |
546 | * valid only for DPAA_VERSION >= 11 |
547 | */ |
548 | scheme_regs.kgse_vsp = KG_SCH_VSP_NO_KSP_EN; |
549 | |
550 | /* Configure Hard-Coded Rx Hashing: */ |
551 | |
552 | if (scheme->use_hashing) { |
553 | /* configure kgse_ekfc */ |
554 | scheme_regs.kgse_ekfc = DEFAULT_HASH_KEY_EXTRACT_FIELDS; |
555 | |
556 | /* configure kgse_ekdv */ |
557 | tmp_reg = 0; |
558 | tmp_reg |= (KG_SCH_DEF_USE_KGSE_DV_0 << |
559 | KG_SCH_DEF_IP_ADDR_SHIFT); |
560 | tmp_reg |= (KG_SCH_DEF_USE_KGSE_DV_1 << |
561 | KG_SCH_DEF_L4_PORT_SHIFT); |
562 | scheme_regs.kgse_ekdv = tmp_reg; |
563 | |
564 | /* configure kgse_dv0 */ |
565 | scheme_regs.kgse_dv0 = DEFAULT_HASH_KEY_IPv4_ADDR; |
566 | /* configure kgse_dv1 */ |
567 | scheme_regs.kgse_dv1 = DEFAULT_HASH_KEY_L4_PORT; |
568 | |
569 | /* configure kgse_hc */ |
570 | tmp_reg = 0; |
571 | tmp_reg |= ((scheme->hash_fqid_count - 1) << |
572 | DEFAULT_HASH_DIST_FQID_SHIFT); |
573 | tmp_reg |= scheme->hashShift << KG_SCH_HASH_CONFIG_SHIFT_SHIFT; |
574 | |
575 | if (scheme->symmetric_hash) { |
576 | /* Normally extraction key should be verified if |
577 | * complies with symmetric hash |
578 | * But because extraction is hard-coded, we are sure |
579 | * the key is symmetric |
580 | */ |
581 | tmp_reg |= KG_SCH_HASH_CONFIG_SYM; |
582 | } |
583 | scheme_regs.kgse_hc = tmp_reg; |
584 | } else { |
585 | scheme_regs.kgse_ekfc = 0; |
586 | scheme_regs.kgse_hc = 0; |
587 | scheme_regs.kgse_ekdv = 0; |
588 | scheme_regs.kgse_dv0 = 0; |
589 | scheme_regs.kgse_dv1 = 0; |
590 | } |
591 | |
592 | /* configure kgse_fqb: Scheme FQID base */ |
593 | tmp_reg = 0; |
594 | tmp_reg |= scheme->base_fqid; |
595 | scheme_regs.kgse_fqb = tmp_reg; |
596 | |
597 | /* features not used by hard-coded configuration */ |
598 | scheme_regs.kgse_bmch = 0; |
599 | scheme_regs.kgse_bmcl = 0; |
600 | scheme_regs.kgse_spc = 0; |
601 | |
602 | /* Write scheme registers */ |
603 | err = keygen_write_scheme(regs: keygen_regs, scheme_id, scheme_regs: &scheme_regs, update_counter: true); |
604 | if (err != 0) { |
605 | pr_err("Writing scheme registers failed\n" ); |
606 | return err; |
607 | } |
608 | |
609 | /* Update used field for Scheme */ |
610 | scheme->used = enable; |
611 | |
612 | return 0; |
613 | } |
614 | |
615 | /* keygen_init |
616 | * |
617 | * KeyGen initialization: |
618 | * Initializes and enables KeyGen, allocate driver memory, setup registers, |
619 | * clear port bindings, invalidate all schemes |
620 | * |
621 | * keygen_regs: KeyGen registers base address |
622 | * |
623 | * Return: Handle to KeyGen driver |
624 | */ |
625 | struct fman_keygen *keygen_init(struct fman_kg_regs __iomem *keygen_regs) |
626 | { |
627 | struct fman_keygen *keygen; |
628 | u32 ar; |
629 | int i; |
630 | |
631 | /* Allocate memory for KeyGen driver */ |
632 | keygen = kzalloc(size: sizeof(*keygen), GFP_KERNEL); |
633 | if (!keygen) |
634 | return NULL; |
635 | |
636 | keygen->keygen_regs = keygen_regs; |
637 | |
638 | /* KeyGen initialization (for Master partition): |
639 | * Setup KeyGen registers |
640 | */ |
641 | iowrite32be(ENQUEUE_KG_DFLT_NIA, &keygen_regs->fmkg_gcr); |
642 | |
643 | iowrite32be(FM_EX_KG_DOUBLE_ECC | FM_EX_KG_KEYSIZE_OVERFLOW, |
644 | &keygen_regs->fmkg_eer); |
645 | |
646 | iowrite32be(0, &keygen_regs->fmkg_fdor); |
647 | iowrite32be(0, &keygen_regs->fmkg_gdv0r); |
648 | iowrite32be(0, &keygen_regs->fmkg_gdv1r); |
649 | |
650 | /* Clear binding between ports to schemes and classification plans |
651 | * so that all ports are not bound to any scheme/classification plan |
652 | */ |
653 | for (i = 0; i < FMAN_MAX_NUM_OF_HW_PORTS; i++) { |
654 | /* Clear all pe sp schemes registers */ |
655 | keygen_write_sp(regs: keygen_regs, sp: 0xffffffff, add: false); |
656 | ar = build_ar_bind_scheme(hwport_id: i, write: true); |
657 | keygen_write_ar_wait(regs: keygen_regs, fmkg_ar: ar); |
658 | |
659 | /* Clear all pe cpp classification plans registers */ |
660 | keygen_write_cpp(regs: keygen_regs, cpp: 0); |
661 | ar = build_ar_bind_cls_plan(hwport_id: i, write: true); |
662 | keygen_write_ar_wait(regs: keygen_regs, fmkg_ar: ar); |
663 | } |
664 | |
665 | /* Enable all scheme interrupts */ |
666 | iowrite32be(0xFFFFFFFF, &keygen_regs->fmkg_seer); |
667 | iowrite32be(0xFFFFFFFF, &keygen_regs->fmkg_seeer); |
668 | |
669 | /* Enable KyeGen */ |
670 | iowrite32be(ioread32be(&keygen_regs->fmkg_gcr) | FM_KG_KGGCR_EN, |
671 | &keygen_regs->fmkg_gcr); |
672 | |
673 | return keygen; |
674 | } |
675 | EXPORT_SYMBOL(keygen_init); |
676 | |
677 | /* keygen_port_hashing_init |
678 | * |
679 | * Initializes a port for Rx Hashing with specified configuration parameters |
680 | * |
681 | * keygen: KeyGen handle |
682 | * hw_port_id: HW Port ID |
683 | * hash_base_fqid: Hashing Base FQID used for spreading |
684 | * hash_size: Hashing size |
685 | * |
686 | * Return: Zero for success or error code in case of failure |
687 | */ |
688 | int keygen_port_hashing_init(struct fman_keygen *keygen, u8 hw_port_id, |
689 | u32 hash_base_fqid, u32 hash_size) |
690 | { |
691 | struct keygen_scheme *scheme; |
692 | u8 scheme_id; |
693 | int err; |
694 | |
695 | /* Validate Scheme configuration parameters */ |
696 | if (hash_base_fqid == 0 || (hash_base_fqid & ~0x00FFFFFF)) { |
697 | pr_err("Base FQID must be between 1 and 2^24-1\n" ); |
698 | return -EINVAL; |
699 | } |
700 | if (hash_size == 0 || (hash_size & (hash_size - 1)) != 0) { |
701 | pr_err("Hash size must be power of two\n" ); |
702 | return -EINVAL; |
703 | } |
704 | |
705 | /* Find a free scheme */ |
706 | err = get_free_scheme_id(keygen, scheme_id: &scheme_id); |
707 | if (err) { |
708 | pr_err("The maximum number of available Schemes has been exceeded\n" ); |
709 | return -EINVAL; |
710 | } |
711 | |
712 | /* Create and configure Hard-Coded Scheme: */ |
713 | |
714 | scheme = get_scheme(keygen, scheme_id); |
715 | if (!scheme) { |
716 | pr_err("Requested Scheme does not exist\n" ); |
717 | return -EINVAL; |
718 | } |
719 | if (scheme->used) { |
720 | pr_err("The requested Scheme is already used\n" ); |
721 | return -EINVAL; |
722 | } |
723 | |
724 | /* Clear all scheme fields because the scheme may have been |
725 | * previously used |
726 | */ |
727 | memset(scheme, 0, sizeof(struct keygen_scheme)); |
728 | |
729 | /* Setup scheme: */ |
730 | scheme->hw_port_id = hw_port_id; |
731 | scheme->use_hashing = true; |
732 | scheme->base_fqid = hash_base_fqid; |
733 | scheme->hash_fqid_count = hash_size; |
734 | scheme->symmetric_hash = DEFAULT_SYMMETRIC_HASH; |
735 | scheme->hashShift = DEFAULT_HASH_SHIFT; |
736 | |
737 | /* All Schemes in hard-coded configuration |
738 | * are Indirect Schemes |
739 | */ |
740 | scheme->match_vector = 0; |
741 | |
742 | err = keygen_scheme_setup(keygen, scheme_id, enable: true); |
743 | if (err != 0) { |
744 | pr_err("Scheme setup failed\n" ); |
745 | return err; |
746 | } |
747 | |
748 | /* Bind Rx port to Scheme */ |
749 | err = keygen_bind_port_to_schemes(keygen, scheme_id, bind: true); |
750 | if (err != 0) { |
751 | pr_err("Binding port to schemes failed\n" ); |
752 | return err; |
753 | } |
754 | |
755 | return 0; |
756 | } |
757 | EXPORT_SYMBOL(keygen_port_hashing_init); |
758 | |