Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

eth: fbnic: Add support to write TCE TCAM entries

Add support to redirect host-to-BMC traffic by writing MACDA entries
from the RPC (RX Parser and Classifier) to TCE-TCAM. The TCE TCAM is a
small L2 destination TCAM which is placed at the end of the TX path (TCE).

Unlike other NICs, where BMC diversion is typically handled by firmware,
for fbnic, firmware does not touch anything related to the host; hence,
the host uses TCE TCAM to divert BMC traffic.

Currently, we lack metadata to track where addresses have been written
in the TCAM, except for the last entry written. To address this issue,
we start at the opposite end of the table in each pass, so that adding
or deleting entries does not affect the availability of all entries,
assuming there is no significant reordering of entries.

Signed-off-by: Mohsin Bashir <mohsin.bashr@gmail.com>
Link: https://patch.msgid.link/20241104031300.1330657-1-mohsin.bashr@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Mohsin Bashir and committed by
Paolo Abeni
90c940ff 9907cda9

+136
+1
drivers/net/ethernet/meta/fbnic/fbnic.h
··· 48 48 struct fbnic_act_tcam act_tcam[FBNIC_RPC_TCAM_ACT_NUM_ENTRIES]; 49 49 struct fbnic_mac_addr mac_addr[FBNIC_RPC_TCAM_MACDA_NUM_ENTRIES]; 50 50 u8 mac_addr_boundary; 51 + u8 tce_tcam_last; 51 52 52 53 /* Number of TCQs/RCQs available on hardware */ 53 54 u16 max_num_queues;
+20
drivers/net/ethernet/meta/fbnic/fbnic_csr.h
··· 397 397 #define FBNIC_TCE_DROP_CTRL_TTI_FRM_DROP_EN CSR_BIT(1) 398 398 #define FBNIC_TCE_DROP_CTRL_TTI_TBI_DROP_EN CSR_BIT(2) 399 399 400 + #define FBNIC_TCE_TCAM_IDX2DEST_MAP 0x0404A /* 0x10128 */ 401 + #define FBNIC_TCE_TCAM_IDX2DEST_MAP_DEST_ID_0 CSR_GENMASK(3, 0) 402 + enum { 403 + FBNIC_TCE_TCAM_DEST_MAC = 1, 404 + FBNIC_TCE_TCAM_DEST_BMC = 2, 405 + FBNIC_TCE_TCAM_DEST_FW = 4, 406 + }; 407 + 400 408 #define FBNIC_TCE_TXB_TX_BMC_Q_CTRL 0x0404B /* 0x1012c */ 401 409 #define FBNIC_TCE_TXB_BMC_DWRR_CTRL 0x0404C /* 0x10130 */ 402 410 #define FBNIC_TCE_TXB_BMC_DWRR_CTRL_QUANTUM0 CSR_GENMASK(7, 0) ··· 414 406 0x0404E /* 0x10138 */ 415 407 #define FBNIC_TCE_TXB_BMC_DWRR_CTRL_EXT 0x0404F /* 0x1013c */ 416 408 #define FBNIC_CSR_END_TCE 0x04050 /* CSR section delimiter */ 409 + 410 + /* TCE RAM registers */ 411 + #define FBNIC_CSR_START_TCE_RAM 0x04200 /* CSR section delimiter */ 412 + #define FBNIC_TCE_RAM_TCAM(m, n) \ 413 + (0x04200 + 0x8 * (n) + (m)) /* 0x10800 + 32*n + 4*m */ 414 + #define FBNIC_TCE_RAM_TCAM_MASK CSR_GENMASK(15, 0) 415 + #define FBNIC_TCE_RAM_TCAM_VALUE CSR_GENMASK(31, 16) 416 + #define FBNIC_TCE_RAM_TCAM3(n) (0x04218 + (n)) /* 0x010860 + 4*n */ 417 + #define FBNIC_TCE_RAM_TCAM3_DEST_MASK CSR_GENMASK(5, 3) 418 + #define FBNIC_TCE_RAM_TCAM3_MCQ_MASK CSR_BIT(7) 419 + #define FBNIC_TCE_RAM_TCAM3_VALIDATE CSR_BIT(31) 420 + #define FBNIC_CSR_END_TCE_RAM 0x0421F /* CSR section delimiter */ 417 421 418 422 /* TMI registers */ 419 423 #define FBNIC_CSR_START_TMI 0x04400 /* CSR section delimiter */
+1
drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
··· 273 273 /* Write updates to hardware */ 274 274 fbnic_write_rules(fbd); 275 275 fbnic_write_macda(fbd); 276 + fbnic_write_tce_tcam(fbd); 276 277 } 277 278 278 279 static void fbnic_set_rx_mode(struct net_device *netdev)
+110
drivers/net/ethernet/meta/fbnic/fbnic_rpc.c
··· 587 587 wr32(fbd, FBNIC_RPC_TCAM_ACT(idx, i), 0); 588 588 } 589 589 590 + static void fbnic_clear_tce_tcam_entry(struct fbnic_dev *fbd, unsigned int idx) 591 + { 592 + int i; 593 + 594 + /* Invalidate entry and clear addr state info */ 595 + for (i = 0; i <= FBNIC_TCE_TCAM_WORD_LEN; i++) 596 + wr32(fbd, FBNIC_TCE_RAM_TCAM(idx, i), 0); 597 + } 598 + 599 + static void fbnic_write_tce_tcam_dest(struct fbnic_dev *fbd, unsigned int idx, 600 + struct fbnic_mac_addr *mac_addr) 601 + { 602 + u32 dest = FBNIC_TCE_TCAM_DEST_BMC; 603 + u32 idx2dest_map; 604 + 605 + if (is_multicast_ether_addr(mac_addr->value.addr8)) 606 + dest |= FBNIC_TCE_TCAM_DEST_MAC; 607 + 608 + idx2dest_map = rd32(fbd, FBNIC_TCE_TCAM_IDX2DEST_MAP); 609 + idx2dest_map &= ~(FBNIC_TCE_TCAM_IDX2DEST_MAP_DEST_ID_0 << (4 * idx)); 610 + idx2dest_map |= dest << (4 * idx); 611 + 612 + wr32(fbd, FBNIC_TCE_TCAM_IDX2DEST_MAP, idx2dest_map); 613 + } 614 + 615 + static void fbnic_write_tce_tcam_entry(struct fbnic_dev *fbd, unsigned int idx, 616 + struct fbnic_mac_addr *mac_addr) 617 + { 618 + __be16 *mask, *value; 619 + int i; 620 + 621 + mask = &mac_addr->mask.addr16[FBNIC_TCE_TCAM_WORD_LEN - 1]; 622 + value = &mac_addr->value.addr16[FBNIC_TCE_TCAM_WORD_LEN - 1]; 623 + 624 + for (i = 0; i < FBNIC_TCE_TCAM_WORD_LEN; i++) 625 + wr32(fbd, FBNIC_TCE_RAM_TCAM(idx, i), 626 + FIELD_PREP(FBNIC_TCE_RAM_TCAM_MASK, ntohs(*mask--)) | 627 + FIELD_PREP(FBNIC_TCE_RAM_TCAM_VALUE, ntohs(*value--))); 628 + 629 + wrfl(fbd); 630 + 631 + wr32(fbd, FBNIC_TCE_RAM_TCAM3(idx), FBNIC_TCE_RAM_TCAM3_MCQ_MASK | 632 + FBNIC_TCE_RAM_TCAM3_DEST_MASK | 633 + FBNIC_TCE_RAM_TCAM3_VALIDATE); 634 + } 635 + 636 + static void __fbnic_write_tce_tcam_rev(struct fbnic_dev *fbd) 637 + { 638 + int tcam_idx = FBNIC_TCE_TCAM_NUM_ENTRIES; 639 + int mac_idx; 640 + 641 + for (mac_idx = ARRAY_SIZE(fbd->mac_addr); mac_idx--;) { 642 + struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[mac_idx]; 643 + 644 + /* Verify BMC bit is set */ 645 + if (!test_bit(FBNIC_MAC_ADDR_T_BMC, mac_addr->act_tcam)) 646 + continue; 647 + 648 + if (!tcam_idx) { 649 + dev_err(fbd->dev, "TCE TCAM overflow\n"); 650 + return; 651 + } 652 + 653 + tcam_idx--; 654 + fbnic_write_tce_tcam_dest(fbd, tcam_idx, mac_addr); 655 + fbnic_write_tce_tcam_entry(fbd, tcam_idx, mac_addr); 656 + } 657 + 658 + while (tcam_idx) 659 + fbnic_clear_tce_tcam_entry(fbd, --tcam_idx); 660 + 661 + fbd->tce_tcam_last = tcam_idx; 662 + } 663 + 664 + static void __fbnic_write_tce_tcam(struct fbnic_dev *fbd) 665 + { 666 + int tcam_idx = 0; 667 + int mac_idx; 668 + 669 + for (mac_idx = 0; mac_idx < ARRAY_SIZE(fbd->mac_addr); mac_idx++) { 670 + struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[mac_idx]; 671 + 672 + /* Verify BMC bit is set */ 673 + if (!test_bit(FBNIC_MAC_ADDR_T_BMC, mac_addr->act_tcam)) 674 + continue; 675 + 676 + if (tcam_idx == FBNIC_TCE_TCAM_NUM_ENTRIES) { 677 + dev_err(fbd->dev, "TCE TCAM overflow\n"); 678 + return; 679 + } 680 + 681 + fbnic_write_tce_tcam_dest(fbd, tcam_idx, mac_addr); 682 + fbnic_write_tce_tcam_entry(fbd, tcam_idx, mac_addr); 683 + tcam_idx++; 684 + } 685 + 686 + while (tcam_idx < FBNIC_TCE_TCAM_NUM_ENTRIES) 687 + fbnic_clear_tce_tcam_entry(fbd, tcam_idx++); 688 + 689 + fbd->tce_tcam_last = tcam_idx; 690 + } 691 + 692 + void fbnic_write_tce_tcam(struct fbnic_dev *fbd) 693 + { 694 + if (fbd->tce_tcam_last) 695 + __fbnic_write_tce_tcam_rev(fbd); 696 + else 697 + __fbnic_write_tce_tcam(fbd); 698 + } 699 + 590 700 void fbnic_clear_rules(struct fbnic_dev *fbd) 591 701 { 592 702 u32 dest = FIELD_PREP(FBNIC_RPC_ACT_TBL0_DEST_MASK,
+4
drivers/net/ethernet/meta/fbnic/fbnic_rpc.h
··· 35 35 #define FBNIC_RPC_TCAM_ACT_WORD_LEN 11 36 36 #define FBNIC_RPC_TCAM_ACT_NUM_ENTRIES 64 37 37 38 + #define FBNIC_TCE_TCAM_WORD_LEN 3 39 + #define FBNIC_TCE_TCAM_NUM_ENTRIES 8 40 + 38 41 struct fbnic_mac_addr { 39 42 union { 40 43 unsigned char addr8[ETH_ALEN]; ··· 189 186 190 187 void fbnic_clear_rules(struct fbnic_dev *fbd); 191 188 void fbnic_write_rules(struct fbnic_dev *fbd); 189 + void fbnic_write_tce_tcam(struct fbnic_dev *fbd); 192 190 #endif /* _FBNIC_RPC_H_ */