1 /* Applied Micro X-Gene SoC Ethernet Classifier structures 2 * 3 * Copyright (c) 2016, Applied Micro Circuits Corporation 4 * Authors: Khuong Dinh <kdinh@apm.com> 5 * Tanmay Inamdar <tinamdar@apm.com> 6 * Iyappan Subramanian <isubramanian@apm.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 #include "xgene_enet_main.h" 23 24 /* interfaces to convert structures to HW recognized bit formats */ 25 static void xgene_cle_sband_to_hw(u8 frag, enum xgene_cle_prot_version ver, 26 enum xgene_cle_prot_type type, u32 len, 27 u32 *reg) 28 { 29 *reg = SET_VAL(SB_IPFRAG, frag) | 30 SET_VAL(SB_IPPROT, type) | 31 SET_VAL(SB_IPVER, ver) | 32 SET_VAL(SB_HDRLEN, len); 33 } 34 35 static void xgene_cle_idt_to_hw(struct xgene_enet_pdata *pdata, 36 u32 dstqid, u32 fpsel, 37 u32 nfpsel, u32 *idt_reg) 38 { 39 if (pdata->enet_id == XGENE_ENET1) { 40 *idt_reg = SET_VAL(IDT_DSTQID, dstqid) | 41 SET_VAL(IDT_FPSEL1, fpsel) | 42 SET_VAL(IDT_NFPSEL1, nfpsel); 43 } else { 44 *idt_reg = SET_VAL(IDT_DSTQID, dstqid) | 45 SET_VAL(IDT_FPSEL, fpsel) | 46 SET_VAL(IDT_NFPSEL, nfpsel); 47 } 48 } 49 50 static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata *pdata, 51 struct xgene_cle_dbptr *dbptr, u32 *buf) 52 { 53 buf[0] = SET_VAL(CLE_DROP, dbptr->drop); 54 buf[4] = SET_VAL(CLE_FPSEL, dbptr->fpsel) | 55 SET_VAL(CLE_NFPSEL, dbptr->nxtfpsel) | 56 SET_VAL(CLE_DSTQIDL, dbptr->dstqid); 57 58 buf[5] = SET_VAL(CLE_DSTQIDH, (u32)dbptr->dstqid >> CLE_DSTQIDL_LEN) | 59 SET_VAL(CLE_PRIORITY, dbptr->cle_priority); 60 } 61 62 static void xgene_cle_kn_to_hw(struct xgene_cle_ptree_kn *kn, u32 *buf) 63 { 64 u32 i, j = 0; 65 u32 data; 66 67 buf[j++] = SET_VAL(CLE_TYPE, kn->node_type); 68 for (i = 0; i < kn->num_keys; i++) { 69 struct xgene_cle_ptree_key *key = &kn->key[i]; 70 71 if (!(i % 2)) { 72 buf[j] = SET_VAL(CLE_KN_PRIO, key->priority) | 73 SET_VAL(CLE_KN_RPTR, key->result_pointer); 74 } else { 75 data = SET_VAL(CLE_KN_PRIO, key->priority) | 76 SET_VAL(CLE_KN_RPTR, key->result_pointer); 77 buf[j++] |= (data << 16); 78 } 79 } 80 } 81 82 static void xgene_cle_dn_to_hw(const struct xgene_cle_ptree_ewdn *dn, 83 u32 *buf, u32 jb) 84 { 85 const struct xgene_cle_ptree_branch *br; 86 u32 i, j = 0; 87 u32 npp; 88 89 buf[j++] = SET_VAL(CLE_DN_TYPE, dn->node_type) | 90 SET_VAL(CLE_DN_LASTN, dn->last_node) | 91 SET_VAL(CLE_DN_HLS, dn->hdr_len_store) | 92 SET_VAL(CLE_DN_EXT, dn->hdr_extn) | 93 SET_VAL(CLE_DN_BSTOR, dn->byte_store) | 94 SET_VAL(CLE_DN_SBSTOR, dn->search_byte_store) | 95 SET_VAL(CLE_DN_RPTR, dn->result_pointer); 96 97 for (i = 0; i < dn->num_branches; i++) { 98 br = &dn->branch[i]; 99 npp = br->next_packet_pointer; 100 101 if ((br->jump_rel == JMP_ABS) && (npp < CLE_PKTRAM_SIZE)) 102 npp += jb; 103 104 buf[j++] = SET_VAL(CLE_BR_VALID, br->valid) | 105 SET_VAL(CLE_BR_NPPTR, npp) | 106 SET_VAL(CLE_BR_JB, br->jump_bw) | 107 SET_VAL(CLE_BR_JR, br->jump_rel) | 108 SET_VAL(CLE_BR_OP, br->operation) | 109 SET_VAL(CLE_BR_NNODE, br->next_node) | 110 SET_VAL(CLE_BR_NBR, br->next_branch); 111 112 buf[j++] = SET_VAL(CLE_BR_DATA, br->data) | 113 SET_VAL(CLE_BR_MASK, br->mask); 114 } 115 } 116 117 static int xgene_cle_poll_cmd_done(void __iomem *base, 118 enum xgene_cle_cmd_type cmd) 119 { 120 u32 status, loop = 10; 121 int ret = -EBUSY; 122 123 while (loop--) { 124 status = ioread32(base + INDCMD_STATUS); 125 if (status & cmd) { 126 ret = 0; 127 break; 128 } 129 usleep_range(1000, 2000); 130 } 131 132 return ret; 133 } 134 135 static int xgene_cle_dram_wr(struct xgene_enet_cle *cle, u32 *data, u8 nregs, 136 u32 index, enum xgene_cle_dram_type type, 137 enum xgene_cle_cmd_type cmd) 138 { 139 enum xgene_cle_parser parser = cle->active_parser; 140 void __iomem *base = cle->base; 141 u32 i, j, ind_addr; 142 u8 port, nparsers; 143 int ret = 0; 144 145 /* PTREE_RAM onwards, DRAM regions are common for all parsers */ 146 nparsers = (type >= PTREE_RAM) ? 1 : cle->parsers; 147 148 for (i = 0; i < nparsers; i++) { 149 port = i; 150 if ((type < PTREE_RAM) && (parser != PARSER_ALL)) 151 port = parser; 152 153 ind_addr = XGENE_CLE_DRAM(type + (port * 4)) | index; 154 iowrite32(ind_addr, base + INDADDR); 155 for (j = 0; j < nregs; j++) 156 iowrite32(data[j], base + DATA_RAM0 + (j * 4)); 157 iowrite32(cmd, base + INDCMD); 158 159 ret = xgene_cle_poll_cmd_done(base, cmd); 160 if (ret) 161 break; 162 } 163 164 return ret; 165 } 166 167 static void xgene_cle_enable_ptree(struct xgene_enet_pdata *pdata, 168 struct xgene_enet_cle *cle) 169 { 170 struct xgene_cle_ptree *ptree = &cle->ptree; 171 void __iomem *addr, *base = cle->base; 172 u32 offset = CLE_PORT_OFFSET; 173 u32 i; 174 175 /* 1G port has to advance 4 bytes and 10G has to advance 8 bytes */ 176 ptree->start_pkt += cle->jump_bytes; 177 for (i = 0; i < cle->parsers; i++) { 178 if (cle->active_parser != PARSER_ALL) 179 addr = base + cle->active_parser * offset; 180 else 181 addr = base + (i * offset); 182 183 iowrite32(ptree->start_node & 0x3fff, addr + SNPTR0); 184 iowrite32(ptree->start_pkt & 0x1ff, addr + SPPTR0); 185 } 186 } 187 188 static int xgene_cle_setup_dbptr(struct xgene_enet_pdata *pdata, 189 struct xgene_enet_cle *cle) 190 { 191 struct xgene_cle_ptree *ptree = &cle->ptree; 192 u32 buf[CLE_DRAM_REGS]; 193 u32 i; 194 int ret; 195 196 memset(buf, 0, sizeof(buf)); 197 for (i = 0; i < ptree->num_dbptr; i++) { 198 xgene_cle_dbptr_to_hw(pdata, &ptree->dbptr[i], buf); 199 ret = xgene_cle_dram_wr(cle, buf, 6, i + ptree->start_dbptr, 200 DB_RAM, CLE_CMD_WR); 201 if (ret) 202 return ret; 203 } 204 205 return 0; 206 } 207 208 static const struct xgene_cle_ptree_ewdn xgene_init_ptree_dn[] = { 209 { 210 /* PKT_TYPE_NODE */ 211 .node_type = EWDN, 212 .last_node = 0, 213 .hdr_len_store = 1, 214 .hdr_extn = NO_BYTE, 215 .byte_store = NO_BYTE, 216 .search_byte_store = NO_BYTE, 217 .result_pointer = DB_RES_DROP, 218 .num_branches = 2, 219 .branch = { 220 { 221 /* IPV4 */ 222 .valid = 1, 223 .next_packet_pointer = 22, 224 .jump_bw = JMP_FW, 225 .jump_rel = JMP_ABS, 226 .operation = EQT, 227 .next_node = PKT_PROT_NODE, 228 .next_branch = 0, 229 .data = 0x8, 230 .mask = 0x0 231 }, 232 { 233 .valid = 0, 234 .next_packet_pointer = 262, 235 .jump_bw = JMP_FW, 236 .jump_rel = JMP_ABS, 237 .operation = EQT, 238 .next_node = LAST_NODE, 239 .next_branch = 0, 240 .data = 0x0, 241 .mask = 0xffff 242 } 243 }, 244 }, 245 { 246 /* PKT_PROT_NODE */ 247 .node_type = EWDN, 248 .last_node = 0, 249 .hdr_len_store = 1, 250 .hdr_extn = NO_BYTE, 251 .byte_store = NO_BYTE, 252 .search_byte_store = NO_BYTE, 253 .result_pointer = DB_RES_DROP, 254 .num_branches = 3, 255 .branch = { 256 { 257 /* TCP */ 258 .valid = 1, 259 .next_packet_pointer = 26, 260 .jump_bw = JMP_FW, 261 .jump_rel = JMP_ABS, 262 .operation = EQT, 263 .next_node = RSS_IPV4_TCP_NODE, 264 .next_branch = 0, 265 .data = 0x0600, 266 .mask = 0x00ff 267 }, 268 { 269 /* UDP */ 270 .valid = 1, 271 .next_packet_pointer = 26, 272 .jump_bw = JMP_FW, 273 .jump_rel = JMP_ABS, 274 .operation = EQT, 275 .next_node = RSS_IPV4_UDP_NODE, 276 .next_branch = 0, 277 .data = 0x1100, 278 .mask = 0x00ff 279 }, 280 { 281 .valid = 0, 282 .next_packet_pointer = 26, 283 .jump_bw = JMP_FW, 284 .jump_rel = JMP_ABS, 285 .operation = EQT, 286 .next_node = RSS_IPV4_OTHERS_NODE, 287 .next_branch = 0, 288 .data = 0x0, 289 .mask = 0xffff 290 } 291 } 292 }, 293 { 294 /* RSS_IPV4_TCP_NODE */ 295 .node_type = EWDN, 296 .last_node = 0, 297 .hdr_len_store = 1, 298 .hdr_extn = NO_BYTE, 299 .byte_store = NO_BYTE, 300 .search_byte_store = BOTH_BYTES, 301 .result_pointer = DB_RES_DROP, 302 .num_branches = 6, 303 .branch = { 304 { 305 /* SRC IPV4 B01 */ 306 .valid = 0, 307 .next_packet_pointer = 28, 308 .jump_bw = JMP_FW, 309 .jump_rel = JMP_ABS, 310 .operation = EQT, 311 .next_node = RSS_IPV4_TCP_NODE, 312 .next_branch = 1, 313 .data = 0x0, 314 .mask = 0xffff 315 }, 316 { 317 /* SRC IPV4 B23 */ 318 .valid = 0, 319 .next_packet_pointer = 30, 320 .jump_bw = JMP_FW, 321 .jump_rel = JMP_ABS, 322 .operation = EQT, 323 .next_node = RSS_IPV4_TCP_NODE, 324 .next_branch = 2, 325 .data = 0x0, 326 .mask = 0xffff 327 }, 328 { 329 /* DST IPV4 B01 */ 330 .valid = 0, 331 .next_packet_pointer = 32, 332 .jump_bw = JMP_FW, 333 .jump_rel = JMP_ABS, 334 .operation = EQT, 335 .next_node = RSS_IPV4_TCP_NODE, 336 .next_branch = 3, 337 .data = 0x0, 338 .mask = 0xffff 339 }, 340 { 341 /* DST IPV4 B23 */ 342 .valid = 0, 343 .next_packet_pointer = 34, 344 .jump_bw = JMP_FW, 345 .jump_rel = JMP_ABS, 346 .operation = EQT, 347 .next_node = RSS_IPV4_TCP_NODE, 348 .next_branch = 4, 349 .data = 0x0, 350 .mask = 0xffff 351 }, 352 { 353 /* TCP SRC Port */ 354 .valid = 0, 355 .next_packet_pointer = 36, 356 .jump_bw = JMP_FW, 357 .jump_rel = JMP_ABS, 358 .operation = EQT, 359 .next_node = RSS_IPV4_TCP_NODE, 360 .next_branch = 5, 361 .data = 0x0, 362 .mask = 0xffff 363 }, 364 { 365 /* TCP DST Port */ 366 .valid = 0, 367 .next_packet_pointer = 256, 368 .jump_bw = JMP_FW, 369 .jump_rel = JMP_ABS, 370 .operation = EQT, 371 .next_node = LAST_NODE, 372 .next_branch = 0, 373 .data = 0x0, 374 .mask = 0xffff 375 } 376 } 377 }, 378 { 379 /* RSS_IPV4_UDP_NODE */ 380 .node_type = EWDN, 381 .last_node = 0, 382 .hdr_len_store = 1, 383 .hdr_extn = NO_BYTE, 384 .byte_store = NO_BYTE, 385 .search_byte_store = BOTH_BYTES, 386 .result_pointer = DB_RES_DROP, 387 .num_branches = 6, 388 .branch = { 389 { 390 /* SRC IPV4 B01 */ 391 .valid = 0, 392 .next_packet_pointer = 28, 393 .jump_bw = JMP_FW, 394 .jump_rel = JMP_ABS, 395 .operation = EQT, 396 .next_node = RSS_IPV4_UDP_NODE, 397 .next_branch = 1, 398 .data = 0x0, 399 .mask = 0xffff 400 }, 401 { 402 /* SRC IPV4 B23 */ 403 .valid = 0, 404 .next_packet_pointer = 30, 405 .jump_bw = JMP_FW, 406 .jump_rel = JMP_ABS, 407 .operation = EQT, 408 .next_node = RSS_IPV4_UDP_NODE, 409 .next_branch = 2, 410 .data = 0x0, 411 .mask = 0xffff 412 }, 413 { 414 /* DST IPV4 B01 */ 415 .valid = 0, 416 .next_packet_pointer = 32, 417 .jump_bw = JMP_FW, 418 .jump_rel = JMP_ABS, 419 .operation = EQT, 420 .next_node = RSS_IPV4_UDP_NODE, 421 .next_branch = 3, 422 .data = 0x0, 423 .mask = 0xffff 424 }, 425 { 426 /* DST IPV4 B23 */ 427 .valid = 0, 428 .next_packet_pointer = 34, 429 .jump_bw = JMP_FW, 430 .jump_rel = JMP_ABS, 431 .operation = EQT, 432 .next_node = RSS_IPV4_UDP_NODE, 433 .next_branch = 4, 434 .data = 0x0, 435 .mask = 0xffff 436 }, 437 { 438 /* TCP SRC Port */ 439 .valid = 0, 440 .next_packet_pointer = 36, 441 .jump_bw = JMP_FW, 442 .jump_rel = JMP_ABS, 443 .operation = EQT, 444 .next_node = RSS_IPV4_UDP_NODE, 445 .next_branch = 5, 446 .data = 0x0, 447 .mask = 0xffff 448 }, 449 { 450 /* TCP DST Port */ 451 .valid = 0, 452 .next_packet_pointer = 258, 453 .jump_bw = JMP_FW, 454 .jump_rel = JMP_ABS, 455 .operation = EQT, 456 .next_node = LAST_NODE, 457 .next_branch = 0, 458 .data = 0x0, 459 .mask = 0xffff 460 } 461 } 462 }, 463 { 464 /* RSS_IPV4_OTHERS_NODE */ 465 .node_type = EWDN, 466 .last_node = 0, 467 .hdr_len_store = 1, 468 .hdr_extn = NO_BYTE, 469 .byte_store = NO_BYTE, 470 .search_byte_store = BOTH_BYTES, 471 .result_pointer = DB_RES_DROP, 472 .num_branches = 6, 473 .branch = { 474 { 475 /* SRC IPV4 B01 */ 476 .valid = 0, 477 .next_packet_pointer = 28, 478 .jump_bw = JMP_FW, 479 .jump_rel = JMP_ABS, 480 .operation = EQT, 481 .next_node = RSS_IPV4_OTHERS_NODE, 482 .next_branch = 1, 483 .data = 0x0, 484 .mask = 0xffff 485 }, 486 { 487 /* SRC IPV4 B23 */ 488 .valid = 0, 489 .next_packet_pointer = 30, 490 .jump_bw = JMP_FW, 491 .jump_rel = JMP_ABS, 492 .operation = EQT, 493 .next_node = RSS_IPV4_OTHERS_NODE, 494 .next_branch = 2, 495 .data = 0x0, 496 .mask = 0xffff 497 }, 498 { 499 /* DST IPV4 B01 */ 500 .valid = 0, 501 .next_packet_pointer = 32, 502 .jump_bw = JMP_FW, 503 .jump_rel = JMP_ABS, 504 .operation = EQT, 505 .next_node = RSS_IPV4_OTHERS_NODE, 506 .next_branch = 3, 507 .data = 0x0, 508 .mask = 0xffff 509 }, 510 { 511 /* DST IPV4 B23 */ 512 .valid = 0, 513 .next_packet_pointer = 34, 514 .jump_bw = JMP_FW, 515 .jump_rel = JMP_ABS, 516 .operation = EQT, 517 .next_node = RSS_IPV4_OTHERS_NODE, 518 .next_branch = 4, 519 .data = 0x0, 520 .mask = 0xffff 521 }, 522 { 523 /* TCP SRC Port */ 524 .valid = 0, 525 .next_packet_pointer = 36, 526 .jump_bw = JMP_FW, 527 .jump_rel = JMP_ABS, 528 .operation = EQT, 529 .next_node = RSS_IPV4_OTHERS_NODE, 530 .next_branch = 5, 531 .data = 0x0, 532 .mask = 0xffff 533 }, 534 { 535 /* TCP DST Port */ 536 .valid = 0, 537 .next_packet_pointer = 260, 538 .jump_bw = JMP_FW, 539 .jump_rel = JMP_ABS, 540 .operation = EQT, 541 .next_node = LAST_NODE, 542 .next_branch = 0, 543 .data = 0x0, 544 .mask = 0xffff 545 } 546 } 547 }, 548 549 { 550 /* LAST NODE */ 551 .node_type = EWDN, 552 .last_node = 1, 553 .hdr_len_store = 1, 554 .hdr_extn = NO_BYTE, 555 .byte_store = NO_BYTE, 556 .search_byte_store = NO_BYTE, 557 .result_pointer = DB_RES_DROP, 558 .num_branches = 1, 559 .branch = { 560 { 561 .valid = 0, 562 .next_packet_pointer = 0, 563 .jump_bw = JMP_FW, 564 .jump_rel = JMP_ABS, 565 .operation = EQT, 566 .next_node = MAX_NODES, 567 .next_branch = 0, 568 .data = 0, 569 .mask = 0xffff 570 } 571 } 572 } 573 }; 574 575 static int xgene_cle_setup_node(struct xgene_enet_pdata *pdata, 576 struct xgene_enet_cle *cle) 577 { 578 struct xgene_cle_ptree *ptree = &cle->ptree; 579 const struct xgene_cle_ptree_ewdn *dn = xgene_init_ptree_dn; 580 int num_dn = ARRAY_SIZE(xgene_init_ptree_dn); 581 struct xgene_cle_ptree_kn *kn = ptree->kn; 582 u32 buf[CLE_DRAM_REGS]; 583 int i, j, ret; 584 585 memset(buf, 0, sizeof(buf)); 586 for (i = 0; i < num_dn; i++) { 587 xgene_cle_dn_to_hw(&dn[i], buf, cle->jump_bytes); 588 ret = xgene_cle_dram_wr(cle, buf, 17, i + ptree->start_node, 589 PTREE_RAM, CLE_CMD_WR); 590 if (ret) 591 return ret; 592 } 593 594 /* continue node index for key node */ 595 memset(buf, 0, sizeof(buf)); 596 for (j = i; j < (ptree->num_kn + num_dn); j++) { 597 xgene_cle_kn_to_hw(&kn[j - num_dn], buf); 598 ret = xgene_cle_dram_wr(cle, buf, 17, j + ptree->start_node, 599 PTREE_RAM, CLE_CMD_WR); 600 if (ret) 601 return ret; 602 } 603 604 return 0; 605 } 606 607 static int xgene_cle_setup_ptree(struct xgene_enet_pdata *pdata, 608 struct xgene_enet_cle *cle) 609 { 610 int ret; 611 612 ret = xgene_cle_setup_node(pdata, cle); 613 if (ret) 614 return ret; 615 616 ret = xgene_cle_setup_dbptr(pdata, cle); 617 if (ret) 618 return ret; 619 620 xgene_cle_enable_ptree(pdata, cle); 621 622 return 0; 623 } 624 625 static void xgene_cle_setup_def_dbptr(struct xgene_enet_pdata *pdata, 626 struct xgene_enet_cle *enet_cle, 627 struct xgene_cle_dbptr *dbptr, 628 u32 index, u8 priority) 629 { 630 void __iomem *base = enet_cle->base; 631 void __iomem *base_addr; 632 u32 buf[CLE_DRAM_REGS]; 633 u32 def_cls, offset; 634 u32 i, j; 635 636 memset(buf, 0, sizeof(buf)); 637 xgene_cle_dbptr_to_hw(pdata, dbptr, buf); 638 639 for (i = 0; i < enet_cle->parsers; i++) { 640 if (enet_cle->active_parser != PARSER_ALL) { 641 offset = enet_cle->active_parser * 642 CLE_PORT_OFFSET; 643 } else { 644 offset = i * CLE_PORT_OFFSET; 645 } 646 647 base_addr = base + DFCLSRESDB00 + offset; 648 for (j = 0; j < 6; j++) 649 iowrite32(buf[j], base_addr + (j * 4)); 650 651 def_cls = ((priority & 0x7) << 10) | (index & 0x3ff); 652 iowrite32(def_cls, base + DFCLSRESDBPTR0 + offset); 653 } 654 } 655 656 static int xgene_cle_set_rss_sband(struct xgene_enet_cle *cle) 657 { 658 u32 idx = CLE_PKTRAM_SIZE / sizeof(u32); 659 u32 mac_hdr_len = ETH_HLEN; 660 u32 sband, reg = 0; 661 u32 ipv4_ihl = 5; 662 u32 hdr_len; 663 int ret; 664 665 /* Sideband: IPV4/TCP packets */ 666 hdr_len = (mac_hdr_len << 5) | ipv4_ihl; 667 xgene_cle_sband_to_hw(0, XGENE_CLE_IPV4, XGENE_CLE_TCP, hdr_len, ®); 668 sband = reg; 669 670 /* Sideband: IPv4/UDP packets */ 671 hdr_len = (mac_hdr_len << 5) | ipv4_ihl; 672 xgene_cle_sband_to_hw(1, XGENE_CLE_IPV4, XGENE_CLE_UDP, hdr_len, ®); 673 sband |= (reg << 16); 674 675 ret = xgene_cle_dram_wr(cle, &sband, 1, idx, PKT_RAM, CLE_CMD_WR); 676 if (ret) 677 return ret; 678 679 /* Sideband: IPv4/RAW packets */ 680 hdr_len = (mac_hdr_len << 5) | ipv4_ihl; 681 xgene_cle_sband_to_hw(0, XGENE_CLE_IPV4, XGENE_CLE_OTHER, 682 hdr_len, ®); 683 sband = reg; 684 685 /* Sideband: Ethernet II/RAW packets */ 686 hdr_len = (mac_hdr_len << 5); 687 xgene_cle_sband_to_hw(0, XGENE_CLE_IPV4, XGENE_CLE_OTHER, 688 hdr_len, ®); 689 sband |= (reg << 16); 690 691 ret = xgene_cle_dram_wr(cle, &sband, 1, idx + 1, PKT_RAM, CLE_CMD_WR); 692 if (ret) 693 return ret; 694 695 return 0; 696 } 697 698 static int xgene_cle_set_rss_skeys(struct xgene_enet_cle *cle) 699 { 700 u32 secret_key_ipv4[4]; /* 16 Bytes*/ 701 int ret = 0; 702 703 get_random_bytes(secret_key_ipv4, 16); 704 ret = xgene_cle_dram_wr(cle, secret_key_ipv4, 4, 0, 705 RSS_IPV4_HASH_SKEY, CLE_CMD_WR); 706 return ret; 707 } 708 709 static int xgene_cle_set_rss_idt(struct xgene_enet_pdata *pdata) 710 { 711 u32 fpsel, dstqid, nfpsel, idt_reg, idx; 712 int i, ret = 0; 713 u16 pool_id; 714 715 for (i = 0; i < XGENE_CLE_IDT_ENTRIES; i++) { 716 idx = i % pdata->rxq_cnt; 717 pool_id = pdata->rx_ring[idx]->buf_pool->id; 718 fpsel = xgene_enet_get_fpsel(pool_id); 719 dstqid = xgene_enet_dst_ring_num(pdata->rx_ring[idx]); 720 nfpsel = 0; 721 if (pdata->rx_ring[idx]->page_pool) { 722 pool_id = pdata->rx_ring[idx]->page_pool->id; 723 nfpsel = xgene_enet_get_fpsel(pool_id); 724 } 725 726 idt_reg = 0; 727 xgene_cle_idt_to_hw(pdata, dstqid, fpsel, nfpsel, &idt_reg); 728 ret = xgene_cle_dram_wr(&pdata->cle, &idt_reg, 1, i, 729 RSS_IDT, CLE_CMD_WR); 730 if (ret) 731 return ret; 732 } 733 734 ret = xgene_cle_set_rss_skeys(&pdata->cle); 735 if (ret) 736 return ret; 737 738 return 0; 739 } 740 741 static int xgene_cle_setup_rss(struct xgene_enet_pdata *pdata) 742 { 743 struct xgene_enet_cle *cle = &pdata->cle; 744 void __iomem *base = cle->base; 745 u32 offset, val = 0; 746 int i, ret = 0; 747 748 offset = CLE_PORT_OFFSET; 749 for (i = 0; i < cle->parsers; i++) { 750 if (cle->active_parser != PARSER_ALL) 751 offset = cle->active_parser * CLE_PORT_OFFSET; 752 else 753 offset = i * CLE_PORT_OFFSET; 754 755 /* enable RSS */ 756 val = (RSS_IPV4_12B << 1) | 0x1; 757 writel(val, base + RSS_CTRL0 + offset); 758 } 759 760 /* setup sideband data */ 761 ret = xgene_cle_set_rss_sband(cle); 762 if (ret) 763 return ret; 764 765 /* setup indirection table */ 766 ret = xgene_cle_set_rss_idt(pdata); 767 if (ret) 768 return ret; 769 770 return 0; 771 } 772 773 static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata) 774 { 775 struct xgene_enet_cle *enet_cle = &pdata->cle; 776 u32 def_qid, def_fpsel, def_nxtfpsel, pool_id; 777 struct xgene_cle_dbptr dbptr[DB_MAX_PTRS]; 778 struct xgene_cle_ptree *ptree; 779 struct xgene_cle_ptree_kn kn; 780 int ret; 781 782 if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII) 783 return -EINVAL; 784 785 ptree = &enet_cle->ptree; 786 ptree->start_pkt = 12; /* Ethertype */ 787 788 ret = xgene_cle_setup_rss(pdata); 789 if (ret) { 790 netdev_err(pdata->ndev, "RSS initialization failed\n"); 791 return ret; 792 } 793 794 def_qid = xgene_enet_dst_ring_num(pdata->rx_ring[0]); 795 pool_id = pdata->rx_ring[0]->buf_pool->id; 796 def_fpsel = xgene_enet_get_fpsel(pool_id); 797 def_nxtfpsel = 0; 798 if (pdata->rx_ring[0]->page_pool) { 799 pool_id = pdata->rx_ring[0]->page_pool->id; 800 def_nxtfpsel = xgene_enet_get_fpsel(pool_id); 801 } 802 803 memset(dbptr, 0, sizeof(struct xgene_cle_dbptr) * DB_MAX_PTRS); 804 dbptr[DB_RES_ACCEPT].fpsel = def_fpsel; 805 dbptr[DB_RES_ACCEPT].nxtfpsel = def_nxtfpsel; 806 dbptr[DB_RES_ACCEPT].dstqid = def_qid; 807 dbptr[DB_RES_ACCEPT].cle_priority = 1; 808 809 dbptr[DB_RES_DEF].fpsel = def_fpsel; 810 dbptr[DB_RES_DEF].nxtfpsel = def_nxtfpsel; 811 dbptr[DB_RES_DEF].dstqid = def_qid; 812 dbptr[DB_RES_DEF].cle_priority = 7; 813 xgene_cle_setup_def_dbptr(pdata, enet_cle, &dbptr[DB_RES_DEF], 814 DB_RES_ACCEPT, 7); 815 816 dbptr[DB_RES_DROP].drop = 1; 817 818 memset(&kn, 0, sizeof(kn)); 819 kn.node_type = KN; 820 kn.num_keys = 1; 821 kn.key[0].priority = 0; 822 kn.key[0].result_pointer = DB_RES_ACCEPT; 823 824 ptree->kn = &kn; 825 ptree->dbptr = dbptr; 826 ptree->num_kn = 1; 827 ptree->num_dbptr = DB_MAX_PTRS; 828 829 return xgene_cle_setup_ptree(pdata, enet_cle); 830 } 831 832 const struct xgene_cle_ops xgene_cle3in_ops = { 833 .cle_init = xgene_enet_cle_init, 834 }; 835