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