diff options
Diffstat (limited to 'drivers/net/ethernet/meta')
-rw-r--r-- | drivers/net/ethernet/meta/fbnic/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/meta/fbnic/fbnic.h | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/meta/fbnic/fbnic_csr.c | 148 | ||||
-rw-r--r-- | drivers/net/ethernet/meta/fbnic/fbnic_csr.h | 36 | ||||
-rw-r--r-- | drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c | 17 | ||||
-rw-r--r-- | drivers/net/ethernet/meta/fbnic/fbnic_netdev.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/meta/fbnic/fbnic_rpc.c | 110 | ||||
-rw-r--r-- | drivers/net/ethernet/meta/fbnic/fbnic_rpc.h | 4 |
8 files changed, 322 insertions, 1 deletions
diff --git a/drivers/net/ethernet/meta/fbnic/Makefile b/drivers/net/ethernet/meta/fbnic/Makefile index cadd4dac6620..425e8b801265 100644 --- a/drivers/net/ethernet/meta/fbnic/Makefile +++ b/drivers/net/ethernet/meta/fbnic/Makefile @@ -7,7 +7,8 @@ obj-$(CONFIG_FBNIC) += fbnic.o -fbnic-y := fbnic_devlink.o \ +fbnic-y := fbnic_csr.o \ + fbnic_devlink.o \ fbnic_ethtool.o \ fbnic_fw.o \ fbnic_hw_stats.o \ diff --git a/drivers/net/ethernet/meta/fbnic/fbnic.h b/drivers/net/ethernet/meta/fbnic/fbnic.h index fec567c8fe4a..98870cb2b689 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic.h @@ -48,6 +48,7 @@ struct fbnic_dev { struct fbnic_act_tcam act_tcam[FBNIC_RPC_TCAM_ACT_NUM_ENTRIES]; struct fbnic_mac_addr mac_addr[FBNIC_RPC_TCAM_MACDA_NUM_ENTRIES]; u8 mac_addr_boundary; + u8 tce_tcam_last; /* Number of TCQs/RCQs available on hardware */ u16 max_num_queues; @@ -155,6 +156,9 @@ int fbnic_alloc_irqs(struct fbnic_dev *fbd); void fbnic_get_fw_ver_commit_str(struct fbnic_dev *fbd, char *fw_version, const size_t str_sz); +void fbnic_csr_get_regs(struct fbnic_dev *fbd, u32 *data, u32 *regs_version); +int fbnic_csr_regs_len(struct fbnic_dev *fbd); + enum fbnic_boards { fbnic_board_asic }; diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_csr.c b/drivers/net/ethernet/meta/fbnic/fbnic_csr.c new file mode 100644 index 000000000000..2118901b25e9 --- /dev/null +++ b/drivers/net/ethernet/meta/fbnic/fbnic_csr.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) Meta Platforms, Inc. and affiliates. */ + +#include "fbnic.h" + +#define FBNIC_BOUNDS(section) { \ + .start = FBNIC_CSR_START_##section, \ + .end = FBNIC_CSR_END_##section + 1, \ +} + +struct fbnic_csr_bounds { + u32 start; + u32 end; +}; + +static const struct fbnic_csr_bounds fbnic_csr_sects[] = { + FBNIC_BOUNDS(INTR), + FBNIC_BOUNDS(INTR_CQ), + FBNIC_BOUNDS(QM_TX), + FBNIC_BOUNDS(QM_RX), + FBNIC_BOUNDS(TCE), + FBNIC_BOUNDS(TCE_RAM), + FBNIC_BOUNDS(TMI), + FBNIC_BOUNDS(PTP), + FBNIC_BOUNDS(RXB), + FBNIC_BOUNDS(RPC), + FBNIC_BOUNDS(FAB), + FBNIC_BOUNDS(MASTER), + FBNIC_BOUNDS(PCS), + FBNIC_BOUNDS(RSFEC), + FBNIC_BOUNDS(MAC_MAC), + FBNIC_BOUNDS(SIG), + FBNIC_BOUNDS(PUL_USER), + FBNIC_BOUNDS(QUEUE), + FBNIC_BOUNDS(RPC_RAM), +}; + +#define FBNIC_RPC_TCAM_ACT_DW_PER_ENTRY 14 +#define FBNIC_RPC_TCAM_ACT_NUM_ENTRIES 64 + +#define FBNIC_RPC_TCAM_MACDA_DW_PER_ENTRY 4 +#define FBNIC_RPC_TCAM_MACDA_NUM_ENTRIES 32 + +#define FBNIC_RPC_TCAM_OUTER_IPSRC_DW_PER_ENTRY 9 +#define FBNIC_RPC_TCAM_OUTER_IPSRC_NUM_ENTRIES 8 + +#define FBNIC_RPC_TCAM_OUTER_IPDST_DW_PER_ENTRY 9 +#define FBNIC_RPC_TCAM_OUTER_IPDST_NUM_ENTRIES 8 + +#define FBNIC_RPC_TCAM_IPSRC_DW_PER_ENTRY 9 +#define FBNIC_RPC_TCAM_IPSRC_NUM_ENTRIES 8 + +#define FBNIC_RPC_TCAM_IPDST_DW_PER_ENTRY 9 +#define FBNIC_RPC_TCAM_IPDST_NUM_ENTRIES 8 + +#define FBNIC_RPC_RSS_TBL_DW_PER_ENTRY 2 +#define FBNIC_RPC_RSS_TBL_NUM_ENTRIES 256 + +static void fbnic_csr_get_regs_rpc_ram(struct fbnic_dev *fbd, u32 **data_p) +{ + u32 start = FBNIC_CSR_START_RPC_RAM; + u32 end = FBNIC_CSR_END_RPC_RAM; + u32 *data = *data_p; + u32 i, j; + + *(data++) = start; + *(data++) = end - 1; + + /* FBNIC_RPC_TCAM_ACT */ + for (i = 0; i < FBNIC_RPC_TCAM_ACT_NUM_ENTRIES; i++) { + for (j = 0; j < FBNIC_RPC_TCAM_ACT_DW_PER_ENTRY; j++) + *(data++) = rd32(fbd, FBNIC_RPC_TCAM_ACT(i, j)); + } + + /* FBNIC_RPC_TCAM_MACDA */ + for (i = 0; i < FBNIC_RPC_TCAM_MACDA_NUM_ENTRIES; i++) { + for (j = 0; j < FBNIC_RPC_TCAM_MACDA_DW_PER_ENTRY; j++) + *(data++) = rd32(fbd, FBNIC_RPC_TCAM_MACDA(i, j)); + } + + /* FBNIC_RPC_TCAM_OUTER_IPSRC */ + for (i = 0; i < FBNIC_RPC_TCAM_OUTER_IPSRC_NUM_ENTRIES; i++) { + for (j = 0; j < FBNIC_RPC_TCAM_OUTER_IPSRC_DW_PER_ENTRY; j++) + *(data++) = rd32(fbd, FBNIC_RPC_TCAM_OUTER_IPSRC(i, j)); + } + + /* FBNIC_RPC_TCAM_OUTER_IPDST */ + for (i = 0; i < FBNIC_RPC_TCAM_OUTER_IPDST_NUM_ENTRIES; i++) { + for (j = 0; j < FBNIC_RPC_TCAM_OUTER_IPDST_DW_PER_ENTRY; j++) + *(data++) = rd32(fbd, FBNIC_RPC_TCAM_OUTER_IPDST(i, j)); + } + + /* FBNIC_RPC_TCAM_IPSRC */ + for (i = 0; i < FBNIC_RPC_TCAM_IPSRC_NUM_ENTRIES; i++) { + for (j = 0; j < FBNIC_RPC_TCAM_IPSRC_DW_PER_ENTRY; j++) + *(data++) = rd32(fbd, FBNIC_RPC_TCAM_IPSRC(i, j)); + } + + /* FBNIC_RPC_TCAM_IPDST */ + for (i = 0; i < FBNIC_RPC_TCAM_IPDST_NUM_ENTRIES; i++) { + for (j = 0; j < FBNIC_RPC_TCAM_IPDST_DW_PER_ENTRY; j++) + *(data++) = rd32(fbd, FBNIC_RPC_TCAM_IPDST(i, j)); + } + + /* FBNIC_RPC_RSS_TBL */ + for (i = 0; i < FBNIC_RPC_RSS_TBL_NUM_ENTRIES; i++) { + for (j = 0; j < FBNIC_RPC_RSS_TBL_DW_PER_ENTRY; j++) + *(data++) = rd32(fbd, FBNIC_RPC_RSS_TBL(i, j)); + } + + *data_p = data; +} + +void fbnic_csr_get_regs(struct fbnic_dev *fbd, u32 *data, u32 *regs_version) +{ + const struct fbnic_csr_bounds *bound; + u32 *start = data; + int i, j; + + *regs_version = 1u; + + /* Skip RPC_RAM section which cannot be dumped linearly */ + for (i = 0, bound = fbnic_csr_sects; + i < ARRAY_SIZE(fbnic_csr_sects) - 1; i++, ++bound) { + *(data++) = bound->start; + *(data++) = bound->end - 1; + for (j = bound->start; j < bound->end; j++) + *(data++) = rd32(fbd, j); + } + + /* Dump the RPC_RAM as special case registers */ + fbnic_csr_get_regs_rpc_ram(fbd, &data); + + WARN_ON(data - start != fbnic_csr_regs_len(fbd)); +} + +int fbnic_csr_regs_len(struct fbnic_dev *fbd) +{ + int i, len = 0; + + /* Dump includes start and end information of each section + * which results in an offset of 2 + */ + for (i = 0; i < ARRAY_SIZE(fbnic_csr_sects); i++) + len += fbnic_csr_sects[i].end - fbnic_csr_sects[i].start + 2; + + return len; +} diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h b/drivers/net/ethernet/meta/fbnic/fbnic_csr.h index 79cdd231d327..f9a531ce9e17 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_csr.h @@ -397,6 +397,14 @@ enum { #define FBNIC_TCE_DROP_CTRL_TTI_FRM_DROP_EN CSR_BIT(1) #define FBNIC_TCE_DROP_CTRL_TTI_TBI_DROP_EN CSR_BIT(2) +#define FBNIC_TCE_TCAM_IDX2DEST_MAP 0x0404A /* 0x10128 */ +#define FBNIC_TCE_TCAM_IDX2DEST_MAP_DEST_ID_0 CSR_GENMASK(3, 0) +enum { + FBNIC_TCE_TCAM_DEST_MAC = 1, + FBNIC_TCE_TCAM_DEST_BMC = 2, + FBNIC_TCE_TCAM_DEST_FW = 4, +}; + #define FBNIC_TCE_TXB_TX_BMC_Q_CTRL 0x0404B /* 0x1012c */ #define FBNIC_TCE_TXB_BMC_DWRR_CTRL 0x0404C /* 0x10130 */ #define FBNIC_TCE_TXB_BMC_DWRR_CTRL_QUANTUM0 CSR_GENMASK(7, 0) @@ -407,6 +415,18 @@ enum { #define FBNIC_TCE_TXB_BMC_DWRR_CTRL_EXT 0x0404F /* 0x1013c */ #define FBNIC_CSR_END_TCE 0x04050 /* CSR section delimiter */ +/* TCE RAM registers */ +#define FBNIC_CSR_START_TCE_RAM 0x04200 /* CSR section delimiter */ +#define FBNIC_TCE_RAM_TCAM(m, n) \ + (0x04200 + 0x8 * (n) + (m)) /* 0x10800 + 32*n + 4*m */ +#define FBNIC_TCE_RAM_TCAM_MASK CSR_GENMASK(15, 0) +#define FBNIC_TCE_RAM_TCAM_VALUE CSR_GENMASK(31, 16) +#define FBNIC_TCE_RAM_TCAM3(n) (0x04218 + (n)) /* 0x010860 + 4*n */ +#define FBNIC_TCE_RAM_TCAM3_DEST_MASK CSR_GENMASK(5, 3) +#define FBNIC_TCE_RAM_TCAM3_MCQ_MASK CSR_BIT(7) +#define FBNIC_TCE_RAM_TCAM3_VALIDATE CSR_BIT(31) +#define FBNIC_CSR_END_TCE_RAM 0x0421F /* CSR section delimiter */ + /* TMI registers */ #define FBNIC_CSR_START_TMI 0x04400 /* CSR section delimiter */ #define FBNIC_TMI_SOP_PROT_CTRL 0x04400 /* 0x11000 */ @@ -645,6 +665,15 @@ enum { #define FBNIC_RPC_TCAM_MACDA_VALUE CSR_GENMASK(15, 0) #define FBNIC_RPC_TCAM_MACDA_MASK CSR_GENMASK(31, 16) +#define FBNIC_RPC_TCAM_OUTER_IPSRC(m, n)\ + (0x08c00 + 0x08 * (n) + (m)) /* 0x023000 + 32*n + 4*m */ +#define FBNIC_RPC_TCAM_OUTER_IPDST(m, n)\ + (0x08c48 + 0x08 * (n) + (m)) /* 0x023120 + 32*n + 4*m */ +#define FBNIC_RPC_TCAM_IPSRC(m, n)\ + (0x08c90 + 0x08 * (n) + (m)) /* 0x023240 + 32*n + 4*m */ +#define FBNIC_RPC_TCAM_IPDST(m, n)\ + (0x08cd8 + 0x08 * (n) + (m)) /* 0x023360 + 32*n + 4*m */ + #define FBNIC_RPC_RSS_TBL(n, m) \ (0x08d20 + 0x100 * (n) + (m)) /* 0x023480 + 1024*n + 4*m */ #define FBNIC_RPC_RSS_TBL_COUNT 2 @@ -663,6 +692,13 @@ enum { #define FBNIC_MASTER_SPARE_0 0x0C41B /* 0x3106c */ #define FBNIC_CSR_END_MASTER 0x0C452 /* CSR section delimiter */ +/* MAC PCS registers */ +#define FBNIC_CSR_START_PCS 0x10000 /* CSR section delimiter */ +#define FBNIC_CSR_END_PCS 0x10668 /* CSR section delimiter */ + +#define FBNIC_CSR_START_RSFEC 0x10800 /* CSR section delimiter */ +#define FBNIC_CSR_END_RSFEC 0x108c8 /* CSR section delimiter */ + /* MAC MAC registers (ASIC only) */ #define FBNIC_CSR_START_MAC_MAC 0x11000 /* CSR section delimiter */ #define FBNIC_MAC_COMMAND_CONFIG 0x11002 /* 0x44008 */ diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c index 1117d5a32867..354b5397815f 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c @@ -116,8 +116,25 @@ static void fbnic_get_ts_stats(struct net_device *netdev, } } +static void fbnic_get_regs(struct net_device *netdev, + struct ethtool_regs *regs, void *data) +{ + struct fbnic_net *fbn = netdev_priv(netdev); + + fbnic_csr_get_regs(fbn->fbd, data, ®s->version); +} + +static int fbnic_get_regs_len(struct net_device *netdev) +{ + struct fbnic_net *fbn = netdev_priv(netdev); + + return fbnic_csr_regs_len(fbn->fbd) * sizeof(u32); +} + static const struct ethtool_ops fbnic_ethtool_ops = { .get_drvinfo = fbnic_get_drvinfo, + .get_regs_len = fbnic_get_regs_len, + .get_regs = fbnic_get_regs, .get_ts_info = fbnic_get_ts_info, .get_ts_stats = fbnic_get_ts_stats, .get_eth_mac_stats = fbnic_get_eth_mac_stats, diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c index c08798fad203..fc7d80db5fa6 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c @@ -273,6 +273,7 @@ void __fbnic_set_rx_mode(struct net_device *netdev) /* Write updates to hardware */ fbnic_write_rules(fbd); fbnic_write_macda(fbd); + fbnic_write_tce_tcam(fbd); } static void fbnic_set_rx_mode(struct net_device *netdev) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c b/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c index 337b8b3aef2f..908c098cd59e 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c @@ -587,6 +587,116 @@ static void fbnic_clear_act_tcam(struct fbnic_dev *fbd, unsigned int idx) wr32(fbd, FBNIC_RPC_TCAM_ACT(idx, i), 0); } +static void fbnic_clear_tce_tcam_entry(struct fbnic_dev *fbd, unsigned int idx) +{ + int i; + + /* Invalidate entry and clear addr state info */ + for (i = 0; i <= FBNIC_TCE_TCAM_WORD_LEN; i++) + wr32(fbd, FBNIC_TCE_RAM_TCAM(idx, i), 0); +} + +static void fbnic_write_tce_tcam_dest(struct fbnic_dev *fbd, unsigned int idx, + struct fbnic_mac_addr *mac_addr) +{ + u32 dest = FBNIC_TCE_TCAM_DEST_BMC; + u32 idx2dest_map; + + if (is_multicast_ether_addr(mac_addr->value.addr8)) + dest |= FBNIC_TCE_TCAM_DEST_MAC; + + idx2dest_map = rd32(fbd, FBNIC_TCE_TCAM_IDX2DEST_MAP); + idx2dest_map &= ~(FBNIC_TCE_TCAM_IDX2DEST_MAP_DEST_ID_0 << (4 * idx)); + idx2dest_map |= dest << (4 * idx); + + wr32(fbd, FBNIC_TCE_TCAM_IDX2DEST_MAP, idx2dest_map); +} + +static void fbnic_write_tce_tcam_entry(struct fbnic_dev *fbd, unsigned int idx, + struct fbnic_mac_addr *mac_addr) +{ + __be16 *mask, *value; + int i; + + mask = &mac_addr->mask.addr16[FBNIC_TCE_TCAM_WORD_LEN - 1]; + value = &mac_addr->value.addr16[FBNIC_TCE_TCAM_WORD_LEN - 1]; + + for (i = 0; i < FBNIC_TCE_TCAM_WORD_LEN; i++) + wr32(fbd, FBNIC_TCE_RAM_TCAM(idx, i), + FIELD_PREP(FBNIC_TCE_RAM_TCAM_MASK, ntohs(*mask--)) | + FIELD_PREP(FBNIC_TCE_RAM_TCAM_VALUE, ntohs(*value--))); + + wrfl(fbd); + + wr32(fbd, FBNIC_TCE_RAM_TCAM3(idx), FBNIC_TCE_RAM_TCAM3_MCQ_MASK | + FBNIC_TCE_RAM_TCAM3_DEST_MASK | + FBNIC_TCE_RAM_TCAM3_VALIDATE); +} + +static void __fbnic_write_tce_tcam_rev(struct fbnic_dev *fbd) +{ + int tcam_idx = FBNIC_TCE_TCAM_NUM_ENTRIES; + int mac_idx; + + for (mac_idx = ARRAY_SIZE(fbd->mac_addr); mac_idx--;) { + struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[mac_idx]; + + /* Verify BMC bit is set */ + if (!test_bit(FBNIC_MAC_ADDR_T_BMC, mac_addr->act_tcam)) + continue; + + if (!tcam_idx) { + dev_err(fbd->dev, "TCE TCAM overflow\n"); + return; + } + + tcam_idx--; + fbnic_write_tce_tcam_dest(fbd, tcam_idx, mac_addr); + fbnic_write_tce_tcam_entry(fbd, tcam_idx, mac_addr); + } + + while (tcam_idx) + fbnic_clear_tce_tcam_entry(fbd, --tcam_idx); + + fbd->tce_tcam_last = tcam_idx; +} + +static void __fbnic_write_tce_tcam(struct fbnic_dev *fbd) +{ + int tcam_idx = 0; + int mac_idx; + + for (mac_idx = 0; mac_idx < ARRAY_SIZE(fbd->mac_addr); mac_idx++) { + struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[mac_idx]; + + /* Verify BMC bit is set */ + if (!test_bit(FBNIC_MAC_ADDR_T_BMC, mac_addr->act_tcam)) + continue; + + if (tcam_idx == FBNIC_TCE_TCAM_NUM_ENTRIES) { + dev_err(fbd->dev, "TCE TCAM overflow\n"); + return; + } + + fbnic_write_tce_tcam_dest(fbd, tcam_idx, mac_addr); + fbnic_write_tce_tcam_entry(fbd, tcam_idx, mac_addr); + tcam_idx++; + } + + while (tcam_idx < FBNIC_TCE_TCAM_NUM_ENTRIES) + fbnic_clear_tce_tcam_entry(fbd, tcam_idx++); + + fbd->tce_tcam_last = tcam_idx; +} + +void fbnic_write_tce_tcam(struct fbnic_dev *fbd) +{ + if (fbd->tce_tcam_last) + __fbnic_write_tce_tcam_rev(fbd); + else + __fbnic_write_tce_tcam(fbd); +} + void fbnic_clear_rules(struct fbnic_dev *fbd) { u32 dest = FIELD_PREP(FBNIC_RPC_ACT_TBL0_DEST_MASK, diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_rpc.h b/drivers/net/ethernet/meta/fbnic/fbnic_rpc.h index d62935f722a2..0d8285fa5b45 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_rpc.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_rpc.h @@ -35,6 +35,9 @@ enum { #define FBNIC_RPC_TCAM_ACT_WORD_LEN 11 #define FBNIC_RPC_TCAM_ACT_NUM_ENTRIES 64 +#define FBNIC_TCE_TCAM_WORD_LEN 3 +#define FBNIC_TCE_TCAM_NUM_ENTRIES 8 + struct fbnic_mac_addr { union { unsigned char addr8[ETH_ALEN]; @@ -186,4 +189,5 @@ static inline int __fbnic_mc_unsync(struct fbnic_mac_addr *mac_addr) void fbnic_clear_rules(struct fbnic_dev *fbd); void fbnic_write_rules(struct fbnic_dev *fbd); +void fbnic_write_tce_tcam(struct fbnic_dev *fbd); #endif /* _FBNIC_RPC_H_ */ |