| // SPDX-License-Identifier: GPL-2.0 |
| /* Marvell RVU Admin Function driver |
| * |
| * Copyright (C) 2019 Marvell. |
| * |
| */ |
| |
| #ifdef CONFIG_DEBUG_FS |
| |
| #include <linux/fs.h> |
| #include <linux/debugfs.h> |
| #include <linux/module.h> |
| #include <linux/pci.h> |
| |
| #include "rvu_struct.h" |
| #include "rvu_reg.h" |
| #include "rvu.h" |
| #include "cgx.h" |
| #include "lmac_common.h" |
| #include "npc.h" |
| #include "rvu_npc_hash.h" |
| #include "mcs.h" |
| |
| #define DEBUGFS_DIR_NAME "octeontx2" |
| |
| enum { |
| CGX_STAT0, |
| CGX_STAT1, |
| CGX_STAT2, |
| CGX_STAT3, |
| CGX_STAT4, |
| CGX_STAT5, |
| CGX_STAT6, |
| CGX_STAT7, |
| CGX_STAT8, |
| CGX_STAT9, |
| CGX_STAT10, |
| CGX_STAT11, |
| CGX_STAT12, |
| CGX_STAT13, |
| CGX_STAT14, |
| CGX_STAT15, |
| CGX_STAT16, |
| CGX_STAT17, |
| CGX_STAT18, |
| }; |
| |
| /* NIX TX stats */ |
| enum nix_stat_lf_tx { |
| TX_UCAST = 0x0, |
| TX_BCAST = 0x1, |
| TX_MCAST = 0x2, |
| TX_DROP = 0x3, |
| TX_OCTS = 0x4, |
| TX_STATS_ENUM_LAST, |
| }; |
| |
| /* NIX RX stats */ |
| enum nix_stat_lf_rx { |
| RX_OCTS = 0x0, |
| RX_UCAST = 0x1, |
| RX_BCAST = 0x2, |
| RX_MCAST = 0x3, |
| RX_DROP = 0x4, |
| RX_DROP_OCTS = 0x5, |
| RX_FCS = 0x6, |
| RX_ERR = 0x7, |
| RX_DRP_BCAST = 0x8, |
| RX_DRP_MCAST = 0x9, |
| RX_DRP_L3BCAST = 0xa, |
| RX_DRP_L3MCAST = 0xb, |
| RX_STATS_ENUM_LAST, |
| }; |
| |
| static char *cgx_rx_stats_fields[] = { |
| [CGX_STAT0] = "Received packets", |
| [CGX_STAT1] = "Octets of received packets", |
| [CGX_STAT2] = "Received PAUSE packets", |
| [CGX_STAT3] = "Received PAUSE and control packets", |
| [CGX_STAT4] = "Filtered DMAC0 (NIX-bound) packets", |
| [CGX_STAT5] = "Filtered DMAC0 (NIX-bound) octets", |
| [CGX_STAT6] = "Packets dropped due to RX FIFO full", |
| [CGX_STAT7] = "Octets dropped due to RX FIFO full", |
| [CGX_STAT8] = "Error packets", |
| [CGX_STAT9] = "Filtered DMAC1 (NCSI-bound) packets", |
| [CGX_STAT10] = "Filtered DMAC1 (NCSI-bound) octets", |
| [CGX_STAT11] = "NCSI-bound packets dropped", |
| [CGX_STAT12] = "NCSI-bound octets dropped", |
| }; |
| |
| static char *cgx_tx_stats_fields[] = { |
| [CGX_STAT0] = "Packets dropped due to excessive collisions", |
| [CGX_STAT1] = "Packets dropped due to excessive deferral", |
| [CGX_STAT2] = "Multiple collisions before successful transmission", |
| [CGX_STAT3] = "Single collisions before successful transmission", |
| [CGX_STAT4] = "Total octets sent on the interface", |
| [CGX_STAT5] = "Total frames sent on the interface", |
| [CGX_STAT6] = "Packets sent with an octet count < 64", |
| [CGX_STAT7] = "Packets sent with an octet count == 64", |
| [CGX_STAT8] = "Packets sent with an octet count of 65-127", |
| [CGX_STAT9] = "Packets sent with an octet count of 128-255", |
| [CGX_STAT10] = "Packets sent with an octet count of 256-511", |
| [CGX_STAT11] = "Packets sent with an octet count of 512-1023", |
| [CGX_STAT12] = "Packets sent with an octet count of 1024-1518", |
| [CGX_STAT13] = "Packets sent with an octet count of > 1518", |
| [CGX_STAT14] = "Packets sent to a broadcast DMAC", |
| [CGX_STAT15] = "Packets sent to the multicast DMAC", |
| [CGX_STAT16] = "Transmit underflow and were truncated", |
| [CGX_STAT17] = "Control/PAUSE packets sent", |
| }; |
| |
| static char *rpm_rx_stats_fields[] = { |
| "Octets of received packets", |
| "Octets of received packets with out error", |
| "Received packets with alignment errors", |
| "Control/PAUSE packets received", |
| "Packets received with Frame too long Errors", |
| "Packets received with a1nrange length Errors", |
| "Received packets", |
| "Packets received with FrameCheckSequenceErrors", |
| "Packets received with VLAN header", |
| "Error packets", |
| "Packets received with unicast DMAC", |
| "Packets received with multicast DMAC", |
| "Packets received with broadcast DMAC", |
| "Dropped packets", |
| "Total frames received on interface", |
| "Packets received with an octet count < 64", |
| "Packets received with an octet count == 64", |
| "Packets received with an octet count of 65-127", |
| "Packets received with an octet count of 128-255", |
| "Packets received with an octet count of 256-511", |
| "Packets received with an octet count of 512-1023", |
| "Packets received with an octet count of 1024-1518", |
| "Packets received with an octet count of > 1518", |
| "Oversized Packets", |
| "Jabber Packets", |
| "Fragmented Packets", |
| "CBFC(class based flow control) pause frames received for class 0", |
| "CBFC pause frames received for class 1", |
| "CBFC pause frames received for class 2", |
| "CBFC pause frames received for class 3", |
| "CBFC pause frames received for class 4", |
| "CBFC pause frames received for class 5", |
| "CBFC pause frames received for class 6", |
| "CBFC pause frames received for class 7", |
| "CBFC pause frames received for class 8", |
| "CBFC pause frames received for class 9", |
| "CBFC pause frames received for class 10", |
| "CBFC pause frames received for class 11", |
| "CBFC pause frames received for class 12", |
| "CBFC pause frames received for class 13", |
| "CBFC pause frames received for class 14", |
| "CBFC pause frames received for class 15", |
| "MAC control packets received", |
| }; |
| |
| static char *rpm_tx_stats_fields[] = { |
| "Total octets sent on the interface", |
| "Total octets transmitted OK", |
| "Control/Pause frames sent", |
| "Total frames transmitted OK", |
| "Total frames sent with VLAN header", |
| "Error Packets", |
| "Packets sent to unicast DMAC", |
| "Packets sent to the multicast DMAC", |
| "Packets sent to a broadcast DMAC", |
| "Packets sent with an octet count == 64", |
| "Packets sent with an octet count of 65-127", |
| "Packets sent with an octet count of 128-255", |
| "Packets sent with an octet count of 256-511", |
| "Packets sent with an octet count of 512-1023", |
| "Packets sent with an octet count of 1024-1518", |
| "Packets sent with an octet count of > 1518", |
| "CBFC(class based flow control) pause frames transmitted for class 0", |
| "CBFC pause frames transmitted for class 1", |
| "CBFC pause frames transmitted for class 2", |
| "CBFC pause frames transmitted for class 3", |
| "CBFC pause frames transmitted for class 4", |
| "CBFC pause frames transmitted for class 5", |
| "CBFC pause frames transmitted for class 6", |
| "CBFC pause frames transmitted for class 7", |
| "CBFC pause frames transmitted for class 8", |
| "CBFC pause frames transmitted for class 9", |
| "CBFC pause frames transmitted for class 10", |
| "CBFC pause frames transmitted for class 11", |
| "CBFC pause frames transmitted for class 12", |
| "CBFC pause frames transmitted for class 13", |
| "CBFC pause frames transmitted for class 14", |
| "CBFC pause frames transmitted for class 15", |
| "MAC control packets sent", |
| "Total frames sent on the interface" |
| }; |
| |
| enum cpt_eng_type { |
| CPT_AE_TYPE = 1, |
| CPT_SE_TYPE = 2, |
| CPT_IE_TYPE = 3, |
| }; |
| |
| #define rvu_dbg_NULL NULL |
| #define rvu_dbg_open_NULL NULL |
| |
| #define RVU_DEBUG_SEQ_FOPS(name, read_op, write_op) \ |
| static int rvu_dbg_open_##name(struct inode *inode, struct file *file) \ |
| { \ |
| return single_open(file, rvu_dbg_##read_op, inode->i_private); \ |
| } \ |
| static const struct file_operations rvu_dbg_##name##_fops = { \ |
| .owner = THIS_MODULE, \ |
| .open = rvu_dbg_open_##name, \ |
| .read = seq_read, \ |
| .write = rvu_dbg_##write_op, \ |
| .llseek = seq_lseek, \ |
| .release = single_release, \ |
| } |
| |
| #define RVU_DEBUG_FOPS(name, read_op, write_op) \ |
| static const struct file_operations rvu_dbg_##name##_fops = { \ |
| .owner = THIS_MODULE, \ |
| .open = simple_open, \ |
| .read = rvu_dbg_##read_op, \ |
| .write = rvu_dbg_##write_op \ |
| } |
| |
| static void print_nix_qsize(struct seq_file *filp, struct rvu_pfvf *pfvf); |
| |
| static int rvu_dbg_mcs_port_stats_display(struct seq_file *filp, void *unused, int dir) |
| { |
| struct mcs *mcs = filp->private; |
| struct mcs_port_stats stats; |
| int lmac; |
| |
| seq_puts(filp, "\n port stats\n"); |
| mutex_lock(&mcs->stats_lock); |
| for_each_set_bit(lmac, &mcs->hw->lmac_bmap, mcs->hw->lmac_cnt) { |
| mcs_get_port_stats(mcs, &stats, lmac, dir); |
| seq_printf(filp, "port%d: Tcam Miss: %lld\n", lmac, stats.tcam_miss_cnt); |
| seq_printf(filp, "port%d: Parser errors: %lld\n", lmac, stats.parser_err_cnt); |
| |
| if (dir == MCS_RX && mcs->hw->mcs_blks > 1) |
| seq_printf(filp, "port%d: Preempt error: %lld\n", lmac, |
| stats.preempt_err_cnt); |
| if (dir == MCS_TX) |
| seq_printf(filp, "port%d: Sectag insert error: %lld\n", lmac, |
| stats.sectag_insert_err_cnt); |
| } |
| mutex_unlock(&mcs->stats_lock); |
| return 0; |
| } |
| |
| static int rvu_dbg_mcs_rx_port_stats_display(struct seq_file *filp, void *unused) |
| { |
| return rvu_dbg_mcs_port_stats_display(filp, unused, MCS_RX); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(mcs_rx_port_stats, mcs_rx_port_stats_display, NULL); |
| |
| static int rvu_dbg_mcs_tx_port_stats_display(struct seq_file *filp, void *unused) |
| { |
| return rvu_dbg_mcs_port_stats_display(filp, unused, MCS_TX); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(mcs_tx_port_stats, mcs_tx_port_stats_display, NULL); |
| |
| static int rvu_dbg_mcs_sa_stats_display(struct seq_file *filp, void *unused, int dir) |
| { |
| struct mcs *mcs = filp->private; |
| struct mcs_sa_stats stats; |
| struct rsrc_bmap *map; |
| int sa_id; |
| |
| if (dir == MCS_TX) { |
| map = &mcs->tx.sa; |
| mutex_lock(&mcs->stats_lock); |
| for_each_set_bit(sa_id, map->bmap, mcs->hw->sa_entries) { |
| seq_puts(filp, "\n TX SA stats\n"); |
| mcs_get_sa_stats(mcs, &stats, sa_id, MCS_TX); |
| seq_printf(filp, "sa%d: Pkts encrypted: %lld\n", sa_id, |
| stats.pkt_encrypt_cnt); |
| |
| seq_printf(filp, "sa%d: Pkts protected: %lld\n", sa_id, |
| stats.pkt_protected_cnt); |
| } |
| mutex_unlock(&mcs->stats_lock); |
| return 0; |
| } |
| |
| /* RX stats */ |
| map = &mcs->rx.sa; |
| mutex_lock(&mcs->stats_lock); |
| for_each_set_bit(sa_id, map->bmap, mcs->hw->sa_entries) { |
| seq_puts(filp, "\n RX SA stats\n"); |
| mcs_get_sa_stats(mcs, &stats, sa_id, MCS_RX); |
| seq_printf(filp, "sa%d: Invalid pkts: %lld\n", sa_id, stats.pkt_invalid_cnt); |
| seq_printf(filp, "sa%d: Pkts no sa error: %lld\n", sa_id, stats.pkt_nosaerror_cnt); |
| seq_printf(filp, "sa%d: Pkts not valid: %lld\n", sa_id, stats.pkt_notvalid_cnt); |
| seq_printf(filp, "sa%d: Pkts ok: %lld\n", sa_id, stats.pkt_ok_cnt); |
| seq_printf(filp, "sa%d: Pkts no sa: %lld\n", sa_id, stats.pkt_nosa_cnt); |
| } |
| mutex_unlock(&mcs->stats_lock); |
| return 0; |
| } |
| |
| static int rvu_dbg_mcs_rx_sa_stats_display(struct seq_file *filp, void *unused) |
| { |
| return rvu_dbg_mcs_sa_stats_display(filp, unused, MCS_RX); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(mcs_rx_sa_stats, mcs_rx_sa_stats_display, NULL); |
| |
| static int rvu_dbg_mcs_tx_sa_stats_display(struct seq_file *filp, void *unused) |
| { |
| return rvu_dbg_mcs_sa_stats_display(filp, unused, MCS_TX); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(mcs_tx_sa_stats, mcs_tx_sa_stats_display, NULL); |
| |
| static int rvu_dbg_mcs_tx_sc_stats_display(struct seq_file *filp, void *unused) |
| { |
| struct mcs *mcs = filp->private; |
| struct mcs_sc_stats stats; |
| struct rsrc_bmap *map; |
| int sc_id; |
| |
| map = &mcs->tx.sc; |
| seq_puts(filp, "\n SC stats\n"); |
| |
| mutex_lock(&mcs->stats_lock); |
| for_each_set_bit(sc_id, map->bmap, mcs->hw->sc_entries) { |
| mcs_get_sc_stats(mcs, &stats, sc_id, MCS_TX); |
| seq_printf(filp, "\n=======sc%d======\n\n", sc_id); |
| seq_printf(filp, "sc%d: Pkts encrypted: %lld\n", sc_id, stats.pkt_encrypt_cnt); |
| seq_printf(filp, "sc%d: Pkts protected: %lld\n", sc_id, stats.pkt_protected_cnt); |
| |
| if (mcs->hw->mcs_blks == 1) { |
| seq_printf(filp, "sc%d: Octets encrypted: %lld\n", sc_id, |
| stats.octet_encrypt_cnt); |
| seq_printf(filp, "sc%d: Octets protected: %lld\n", sc_id, |
| stats.octet_protected_cnt); |
| } |
| } |
| mutex_unlock(&mcs->stats_lock); |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(mcs_tx_sc_stats, mcs_tx_sc_stats_display, NULL); |
| |
| static int rvu_dbg_mcs_rx_sc_stats_display(struct seq_file *filp, void *unused) |
| { |
| struct mcs *mcs = filp->private; |
| struct mcs_sc_stats stats; |
| struct rsrc_bmap *map; |
| int sc_id; |
| |
| map = &mcs->rx.sc; |
| seq_puts(filp, "\n SC stats\n"); |
| |
| mutex_lock(&mcs->stats_lock); |
| for_each_set_bit(sc_id, map->bmap, mcs->hw->sc_entries) { |
| mcs_get_sc_stats(mcs, &stats, sc_id, MCS_RX); |
| seq_printf(filp, "\n=======sc%d======\n\n", sc_id); |
| seq_printf(filp, "sc%d: Cam hits: %lld\n", sc_id, stats.hit_cnt); |
| seq_printf(filp, "sc%d: Invalid pkts: %lld\n", sc_id, stats.pkt_invalid_cnt); |
| seq_printf(filp, "sc%d: Late pkts: %lld\n", sc_id, stats.pkt_late_cnt); |
| seq_printf(filp, "sc%d: Notvalid pkts: %lld\n", sc_id, stats.pkt_notvalid_cnt); |
| seq_printf(filp, "sc%d: Unchecked pkts: %lld\n", sc_id, stats.pkt_unchecked_cnt); |
| |
| if (mcs->hw->mcs_blks > 1) { |
| seq_printf(filp, "sc%d: Delay pkts: %lld\n", sc_id, stats.pkt_delay_cnt); |
| seq_printf(filp, "sc%d: Pkts ok: %lld\n", sc_id, stats.pkt_ok_cnt); |
| } |
| if (mcs->hw->mcs_blks == 1) { |
| seq_printf(filp, "sc%d: Octets decrypted: %lld\n", sc_id, |
| stats.octet_decrypt_cnt); |
| seq_printf(filp, "sc%d: Octets validated: %lld\n", sc_id, |
| stats.octet_validate_cnt); |
| } |
| } |
| mutex_unlock(&mcs->stats_lock); |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(mcs_rx_sc_stats, mcs_rx_sc_stats_display, NULL); |
| |
| static int rvu_dbg_mcs_flowid_stats_display(struct seq_file *filp, void *unused, int dir) |
| { |
| struct mcs *mcs = filp->private; |
| struct mcs_flowid_stats stats; |
| struct rsrc_bmap *map; |
| int flow_id; |
| |
| seq_puts(filp, "\n Flowid stats\n"); |
| |
| if (dir == MCS_RX) |
| map = &mcs->rx.flow_ids; |
| else |
| map = &mcs->tx.flow_ids; |
| |
| mutex_lock(&mcs->stats_lock); |
| for_each_set_bit(flow_id, map->bmap, mcs->hw->tcam_entries) { |
| mcs_get_flowid_stats(mcs, &stats, flow_id, dir); |
| seq_printf(filp, "Flowid%d: Hit:%lld\n", flow_id, stats.tcam_hit_cnt); |
| } |
| mutex_unlock(&mcs->stats_lock); |
| return 0; |
| } |
| |
| static int rvu_dbg_mcs_tx_flowid_stats_display(struct seq_file *filp, void *unused) |
| { |
| return rvu_dbg_mcs_flowid_stats_display(filp, unused, MCS_TX); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(mcs_tx_flowid_stats, mcs_tx_flowid_stats_display, NULL); |
| |
| static int rvu_dbg_mcs_rx_flowid_stats_display(struct seq_file *filp, void *unused) |
| { |
| return rvu_dbg_mcs_flowid_stats_display(filp, unused, MCS_RX); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(mcs_rx_flowid_stats, mcs_rx_flowid_stats_display, NULL); |
| |
| static int rvu_dbg_mcs_tx_secy_stats_display(struct seq_file *filp, void *unused) |
| { |
| struct mcs *mcs = filp->private; |
| struct mcs_secy_stats stats; |
| struct rsrc_bmap *map; |
| int secy_id; |
| |
| map = &mcs->tx.secy; |
| seq_puts(filp, "\n MCS TX secy stats\n"); |
| |
| mutex_lock(&mcs->stats_lock); |
| for_each_set_bit(secy_id, map->bmap, mcs->hw->secy_entries) { |
| mcs_get_tx_secy_stats(mcs, &stats, secy_id); |
| seq_printf(filp, "\n=======Secy%d======\n\n", secy_id); |
| seq_printf(filp, "secy%d: Ctrl bcast pkts: %lld\n", secy_id, |
| stats.ctl_pkt_bcast_cnt); |
| seq_printf(filp, "secy%d: Ctrl Mcast pkts: %lld\n", secy_id, |
| stats.ctl_pkt_mcast_cnt); |
| seq_printf(filp, "secy%d: Ctrl ucast pkts: %lld\n", secy_id, |
| stats.ctl_pkt_ucast_cnt); |
| seq_printf(filp, "secy%d: Ctrl octets: %lld\n", secy_id, stats.ctl_octet_cnt); |
| seq_printf(filp, "secy%d: Unctrl bcast cnt: %lld\n", secy_id, |
| stats.unctl_pkt_bcast_cnt); |
| seq_printf(filp, "secy%d: Unctrl mcast pkts: %lld\n", secy_id, |
| stats.unctl_pkt_mcast_cnt); |
| seq_printf(filp, "secy%d: Unctrl ucast pkts: %lld\n", secy_id, |
| stats.unctl_pkt_ucast_cnt); |
| seq_printf(filp, "secy%d: Unctrl octets: %lld\n", secy_id, stats.unctl_octet_cnt); |
| seq_printf(filp, "secy%d: Octet encrypted: %lld\n", secy_id, |
| stats.octet_encrypted_cnt); |
| seq_printf(filp, "secy%d: octet protected: %lld\n", secy_id, |
| stats.octet_protected_cnt); |
| seq_printf(filp, "secy%d: Pkts on active sa: %lld\n", secy_id, |
| stats.pkt_noactivesa_cnt); |
| seq_printf(filp, "secy%d: Pkts too long: %lld\n", secy_id, stats.pkt_toolong_cnt); |
| seq_printf(filp, "secy%d: Pkts untagged: %lld\n", secy_id, stats.pkt_untagged_cnt); |
| } |
| mutex_unlock(&mcs->stats_lock); |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(mcs_tx_secy_stats, mcs_tx_secy_stats_display, NULL); |
| |
| static int rvu_dbg_mcs_rx_secy_stats_display(struct seq_file *filp, void *unused) |
| { |
| struct mcs *mcs = filp->private; |
| struct mcs_secy_stats stats; |
| struct rsrc_bmap *map; |
| int secy_id; |
| |
| map = &mcs->rx.secy; |
| seq_puts(filp, "\n MCS secy stats\n"); |
| |
| mutex_lock(&mcs->stats_lock); |
| for_each_set_bit(secy_id, map->bmap, mcs->hw->secy_entries) { |
| mcs_get_rx_secy_stats(mcs, &stats, secy_id); |
| seq_printf(filp, "\n=======Secy%d======\n\n", secy_id); |
| seq_printf(filp, "secy%d: Ctrl bcast pkts: %lld\n", secy_id, |
| stats.ctl_pkt_bcast_cnt); |
| seq_printf(filp, "secy%d: Ctrl Mcast pkts: %lld\n", secy_id, |
| stats.ctl_pkt_mcast_cnt); |
| seq_printf(filp, "secy%d: Ctrl ucast pkts: %lld\n", secy_id, |
| stats.ctl_pkt_ucast_cnt); |
| seq_printf(filp, "secy%d: Ctrl octets: %lld\n", secy_id, stats.ctl_octet_cnt); |
| seq_printf(filp, "secy%d: Unctrl bcast cnt: %lld\n", secy_id, |
| stats.unctl_pkt_bcast_cnt); |
| seq_printf(filp, "secy%d: Unctrl mcast pkts: %lld\n", secy_id, |
| stats.unctl_pkt_mcast_cnt); |
| seq_printf(filp, "secy%d: Unctrl ucast pkts: %lld\n", secy_id, |
| stats.unctl_pkt_ucast_cnt); |
| seq_printf(filp, "secy%d: Unctrl octets: %lld\n", secy_id, stats.unctl_octet_cnt); |
| seq_printf(filp, "secy%d: Octet decrypted: %lld\n", secy_id, |
| stats.octet_decrypted_cnt); |
| seq_printf(filp, "secy%d: octet validated: %lld\n", secy_id, |
| stats.octet_validated_cnt); |
| seq_printf(filp, "secy%d: Pkts on disable port: %lld\n", secy_id, |
| stats.pkt_port_disabled_cnt); |
| seq_printf(filp, "secy%d: Octets validated: %lld\n", secy_id, stats.pkt_badtag_cnt); |
| seq_printf(filp, "secy%d: Octets validated: %lld\n", secy_id, stats.pkt_nosa_cnt); |
| seq_printf(filp, "secy%d: Pkts with nosaerror: %lld\n", secy_id, |
| stats.pkt_nosaerror_cnt); |
| seq_printf(filp, "secy%d: Tagged ctrl pkts: %lld\n", secy_id, |
| stats.pkt_tagged_ctl_cnt); |
| seq_printf(filp, "secy%d: Untaged pkts: %lld\n", secy_id, stats.pkt_untaged_cnt); |
| seq_printf(filp, "secy%d: Ctrl pkts: %lld\n", secy_id, stats.pkt_ctl_cnt); |
| if (mcs->hw->mcs_blks > 1) |
| seq_printf(filp, "secy%d: pkts notag: %lld\n", secy_id, |
| stats.pkt_notag_cnt); |
| } |
| mutex_unlock(&mcs->stats_lock); |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(mcs_rx_secy_stats, mcs_rx_secy_stats_display, NULL); |
| |
| static void rvu_dbg_mcs_init(struct rvu *rvu) |
| { |
| struct mcs *mcs; |
| char dname[10]; |
| int i; |
| |
| if (!rvu->mcs_blk_cnt) |
| return; |
| |
| rvu->rvu_dbg.mcs_root = debugfs_create_dir("mcs", rvu->rvu_dbg.root); |
| |
| for (i = 0; i < rvu->mcs_blk_cnt; i++) { |
| mcs = mcs_get_pdata(i); |
| |
| sprintf(dname, "mcs%d", i); |
| rvu->rvu_dbg.mcs = debugfs_create_dir(dname, |
| rvu->rvu_dbg.mcs_root); |
| |
| rvu->rvu_dbg.mcs_rx = debugfs_create_dir("rx_stats", rvu->rvu_dbg.mcs); |
| |
| debugfs_create_file("flowid", 0600, rvu->rvu_dbg.mcs_rx, mcs, |
| &rvu_dbg_mcs_rx_flowid_stats_fops); |
| |
| debugfs_create_file("secy", 0600, rvu->rvu_dbg.mcs_rx, mcs, |
| &rvu_dbg_mcs_rx_secy_stats_fops); |
| |
| debugfs_create_file("sc", 0600, rvu->rvu_dbg.mcs_rx, mcs, |
| &rvu_dbg_mcs_rx_sc_stats_fops); |
| |
| debugfs_create_file("sa", 0600, rvu->rvu_dbg.mcs_rx, mcs, |
| &rvu_dbg_mcs_rx_sa_stats_fops); |
| |
| debugfs_create_file("port", 0600, rvu->rvu_dbg.mcs_rx, mcs, |
| &rvu_dbg_mcs_rx_port_stats_fops); |
| |
| rvu->rvu_dbg.mcs_tx = debugfs_create_dir("tx_stats", rvu->rvu_dbg.mcs); |
| |
| debugfs_create_file("flowid", 0600, rvu->rvu_dbg.mcs_tx, mcs, |
| &rvu_dbg_mcs_tx_flowid_stats_fops); |
| |
| debugfs_create_file("secy", 0600, rvu->rvu_dbg.mcs_tx, mcs, |
| &rvu_dbg_mcs_tx_secy_stats_fops); |
| |
| debugfs_create_file("sc", 0600, rvu->rvu_dbg.mcs_tx, mcs, |
| &rvu_dbg_mcs_tx_sc_stats_fops); |
| |
| debugfs_create_file("sa", 0600, rvu->rvu_dbg.mcs_tx, mcs, |
| &rvu_dbg_mcs_tx_sa_stats_fops); |
| |
| debugfs_create_file("port", 0600, rvu->rvu_dbg.mcs_tx, mcs, |
| &rvu_dbg_mcs_tx_port_stats_fops); |
| } |
| } |
| |
| #define LMT_MAPTBL_ENTRY_SIZE 16 |
| /* Dump LMTST map table */ |
| static ssize_t rvu_dbg_lmtst_map_table_display(struct file *filp, |
| char __user *buffer, |
| size_t count, loff_t *ppos) |
| { |
| struct rvu *rvu = filp->private_data; |
| u64 lmt_addr, val, tbl_base; |
| int pf, vf, num_vfs, hw_vfs; |
| void __iomem *lmt_map_base; |
| int buf_size = 10240; |
| size_t off = 0; |
| int index = 0; |
| char *buf; |
| int ret; |
| |
| /* don't allow partial reads */ |
| if (*ppos != 0) |
| return 0; |
| |
| buf = kzalloc(buf_size, GFP_KERNEL); |
| if (!buf) |
| return -ENOMEM; |
| |
| tbl_base = rvu_read64(rvu, BLKADDR_APR, APR_AF_LMT_MAP_BASE); |
| |
| lmt_map_base = ioremap_wc(tbl_base, 128 * 1024); |
| if (!lmt_map_base) { |
| dev_err(rvu->dev, "Failed to setup lmt map table mapping!!\n"); |
| kfree(buf); |
| return false; |
| } |
| |
| off += scnprintf(&buf[off], buf_size - 1 - off, |
| "\n\t\t\t\t\tLmtst Map Table Entries"); |
| off += scnprintf(&buf[off], buf_size - 1 - off, |
| "\n\t\t\t\t\t======================="); |
| off += scnprintf(&buf[off], buf_size - 1 - off, "\nPcifunc\t\t\t"); |
| off += scnprintf(&buf[off], buf_size - 1 - off, "Table Index\t\t"); |
| off += scnprintf(&buf[off], buf_size - 1 - off, |
| "Lmtline Base (word 0)\t\t"); |
| off += scnprintf(&buf[off], buf_size - 1 - off, |
| "Lmt Map Entry (word 1)"); |
| off += scnprintf(&buf[off], buf_size - 1 - off, "\n"); |
| for (pf = 0; pf < rvu->hw->total_pfs; pf++) { |
| off += scnprintf(&buf[off], buf_size - 1 - off, "PF%d \t\t\t", |
| pf); |
| |
| index = pf * rvu->hw->total_vfs * LMT_MAPTBL_ENTRY_SIZE; |
| off += scnprintf(&buf[off], buf_size - 1 - off, " 0x%llx\t\t", |
| (tbl_base + index)); |
| lmt_addr = readq(lmt_map_base + index); |
| off += scnprintf(&buf[off], buf_size - 1 - off, |
| " 0x%016llx\t\t", lmt_addr); |
| index += 8; |
| val = readq(lmt_map_base + index); |
| off += scnprintf(&buf[off], buf_size - 1 - off, " 0x%016llx\n", |
| val); |
| /* Reading num of VFs per PF */ |
| rvu_get_pf_numvfs(rvu, pf, &num_vfs, &hw_vfs); |
| for (vf = 0; vf < num_vfs; vf++) { |
| index = (pf * rvu->hw->total_vfs * 16) + |
| ((vf + 1) * LMT_MAPTBL_ENTRY_SIZE); |
| off += scnprintf(&buf[off], buf_size - 1 - off, |
| "PF%d:VF%d \t\t", pf, vf); |
| off += scnprintf(&buf[off], buf_size - 1 - off, |
| " 0x%llx\t\t", (tbl_base + index)); |
| lmt_addr = readq(lmt_map_base + index); |
| off += scnprintf(&buf[off], buf_size - 1 - off, |
| " 0x%016llx\t\t", lmt_addr); |
| index += 8; |
| val = readq(lmt_map_base + index); |
| off += scnprintf(&buf[off], buf_size - 1 - off, |
| " 0x%016llx\n", val); |
| } |
| } |
| off += scnprintf(&buf[off], buf_size - 1 - off, "\n"); |
| |
| ret = min(off, count); |
| if (copy_to_user(buffer, buf, ret)) |
| ret = -EFAULT; |
| kfree(buf); |
| |
| iounmap(lmt_map_base); |
| if (ret < 0) |
| return ret; |
| |
| *ppos = ret; |
| return ret; |
| } |
| |
| RVU_DEBUG_FOPS(lmtst_map_table, lmtst_map_table_display, NULL); |
| |
| static void get_lf_str_list(struct rvu_block block, int pcifunc, |
| char *lfs) |
| { |
| int lf = 0, seq = 0, len = 0, prev_lf = block.lf.max; |
| |
| for_each_set_bit(lf, block.lf.bmap, block.lf.max) { |
| if (lf >= block.lf.max) |
| break; |
| |
| if (block.fn_map[lf] != pcifunc) |
| continue; |
| |
| if (lf == prev_lf + 1) { |
| prev_lf = lf; |
| seq = 1; |
| continue; |
| } |
| |
| if (seq) |
| len += sprintf(lfs + len, "-%d,%d", prev_lf, lf); |
| else |
| len += (len ? sprintf(lfs + len, ",%d", lf) : |
| sprintf(lfs + len, "%d", lf)); |
| |
| prev_lf = lf; |
| seq = 0; |
| } |
| |
| if (seq) |
| len += sprintf(lfs + len, "-%d", prev_lf); |
| |
| lfs[len] = '\0'; |
| } |
| |
| static int get_max_column_width(struct rvu *rvu) |
| { |
| int index, pf, vf, lf_str_size = 12, buf_size = 256; |
| struct rvu_block block; |
| u16 pcifunc; |
| char *buf; |
| |
| buf = kzalloc(buf_size, GFP_KERNEL); |
| if (!buf) |
| return -ENOMEM; |
| |
| for (pf = 0; pf < rvu->hw->total_pfs; pf++) { |
| for (vf = 0; vf <= rvu->hw->total_vfs; vf++) { |
| pcifunc = pf << 10 | vf; |
| if (!pcifunc) |
| continue; |
| |
| for (index = 0; index < BLK_COUNT; index++) { |
| block = rvu->hw->block[index]; |
| if (!strlen(block.name)) |
| continue; |
| |
| get_lf_str_list(block, pcifunc, buf); |
| if (lf_str_size <= strlen(buf)) |
| lf_str_size = strlen(buf) + 1; |
| } |
| } |
| } |
| |
| kfree(buf); |
| return lf_str_size; |
| } |
| |
| /* Dumps current provisioning status of all RVU block LFs */ |
| static ssize_t rvu_dbg_rsrc_attach_status(struct file *filp, |
| char __user *buffer, |
| size_t count, loff_t *ppos) |
| { |
| int index, off = 0, flag = 0, len = 0, i = 0; |
| struct rvu *rvu = filp->private_data; |
| int bytes_not_copied = 0; |
| struct rvu_block block; |
| int pf, vf, pcifunc; |
| int buf_size = 2048; |
| int lf_str_size; |
| char *lfs; |
| char *buf; |
| |
| /* don't allow partial reads */ |
| if (*ppos != 0) |
| return 0; |
| |
| buf = kzalloc(buf_size, GFP_KERNEL); |
| if (!buf) |
| return -ENOMEM; |
| |
| /* Get the maximum width of a column */ |
| lf_str_size = get_max_column_width(rvu); |
| |
| lfs = kzalloc(lf_str_size, GFP_KERNEL); |
| if (!lfs) { |
| kfree(buf); |
| return -ENOMEM; |
| } |
| off += scnprintf(&buf[off], buf_size - 1 - off, "%-*s", lf_str_size, |
| "pcifunc"); |
| for (index = 0; index < BLK_COUNT; index++) |
| if (strlen(rvu->hw->block[index].name)) { |
| off += scnprintf(&buf[off], buf_size - 1 - off, |
| "%-*s", lf_str_size, |
| rvu->hw->block[index].name); |
| } |
| |
| off += scnprintf(&buf[off], buf_size - 1 - off, "\n"); |
| bytes_not_copied = copy_to_user(buffer + (i * off), buf, off); |
| if (bytes_not_copied) |
| goto out; |
| |
| i++; |
| *ppos += off; |
| for (pf = 0; pf < rvu->hw->total_pfs; pf++) { |
| for (vf = 0; vf <= rvu->hw->total_vfs; vf++) { |
| off = 0; |
| flag = 0; |
| pcifunc = pf << 10 | vf; |
| if (!pcifunc) |
| continue; |
| |
| if (vf) { |
| sprintf(lfs, "PF%d:VF%d", pf, vf - 1); |
| off = scnprintf(&buf[off], |
| buf_size - 1 - off, |
| "%-*s", lf_str_size, lfs); |
| } else { |
| sprintf(lfs, "PF%d", pf); |
| off = scnprintf(&buf[off], |
| buf_size - 1 - off, |
| "%-*s", lf_str_size, lfs); |
| } |
| |
| for (index = 0; index < BLK_COUNT; index++) { |
| block = rvu->hw->block[index]; |
| if (!strlen(block.name)) |
| continue; |
| len = 0; |
| lfs[len] = '\0'; |
| get_lf_str_list(block, pcifunc, lfs); |
| if (strlen(lfs)) |
| flag = 1; |
| |
| off += scnprintf(&buf[off], buf_size - 1 - off, |
| "%-*s", lf_str_size, lfs); |
| } |
| if (flag) { |
| off += scnprintf(&buf[off], |
| buf_size - 1 - off, "\n"); |
| bytes_not_copied = copy_to_user(buffer + |
| (i * off), |
| buf, off); |
| if (bytes_not_copied) |
| goto out; |
| |
| i++; |
| *ppos += off; |
| } |
| } |
| } |
| |
| out: |
| kfree(lfs); |
| kfree(buf); |
| if (bytes_not_copied) |
| return -EFAULT; |
| |
| return *ppos; |
| } |
| |
| RVU_DEBUG_FOPS(rsrc_status, rsrc_attach_status, NULL); |
| |
| static int rvu_dbg_rvu_pf_cgx_map_display(struct seq_file *filp, void *unused) |
| { |
| struct rvu *rvu = filp->private; |
| struct pci_dev *pdev = NULL; |
| struct mac_ops *mac_ops; |
| char cgx[10], lmac[10]; |
| struct rvu_pfvf *pfvf; |
| int pf, domain, blkid; |
| u8 cgx_id, lmac_id; |
| u16 pcifunc; |
| |
| domain = 2; |
| mac_ops = get_mac_ops(rvu_first_cgx_pdata(rvu)); |
| /* There can be no CGX devices at all */ |
| if (!mac_ops) |
| return 0; |
| seq_printf(filp, "PCI dev\t\tRVU PF Func\tNIX block\t%s\tLMAC\n", |
| mac_ops->name); |
| for (pf = 0; pf < rvu->hw->total_pfs; pf++) { |
| if (!is_pf_cgxmapped(rvu, pf)) |
| continue; |
| |
| pdev = pci_get_domain_bus_and_slot(domain, pf + 1, 0); |
| if (!pdev) |
| continue; |
| |
| cgx[0] = 0; |
| lmac[0] = 0; |
| pcifunc = pf << 10; |
| pfvf = rvu_get_pfvf(rvu, pcifunc); |
| |
| if (pfvf->nix_blkaddr == BLKADDR_NIX0) |
| blkid = 0; |
| else |
| blkid = 1; |
| |
| rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, |
| &lmac_id); |
| sprintf(cgx, "%s%d", mac_ops->name, cgx_id); |
| sprintf(lmac, "LMAC%d", lmac_id); |
| seq_printf(filp, "%s\t0x%x\t\tNIX%d\t\t%s\t%s\n", |
| dev_name(&pdev->dev), pcifunc, blkid, cgx, lmac); |
| |
| pci_dev_put(pdev); |
| } |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(rvu_pf_cgx_map, rvu_pf_cgx_map_display, NULL); |
| |
| static bool rvu_dbg_is_valid_lf(struct rvu *rvu, int blkaddr, int lf, |
| u16 *pcifunc) |
| { |
| struct rvu_block *block; |
| struct rvu_hwinfo *hw; |
| |
| hw = rvu->hw; |
| block = &hw->block[blkaddr]; |
| |
| if (lf < 0 || lf >= block->lf.max) { |
| dev_warn(rvu->dev, "Invalid LF: valid range: 0-%d\n", |
| block->lf.max - 1); |
| return false; |
| } |
| |
| *pcifunc = block->fn_map[lf]; |
| if (!*pcifunc) { |
| dev_warn(rvu->dev, |
| "This LF is not attached to any RVU PFFUNC\n"); |
| return false; |
| } |
| return true; |
| } |
| |
| static void print_npa_qsize(struct seq_file *m, struct rvu_pfvf *pfvf) |
| { |
| char *buf; |
| |
| buf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
| if (!buf) |
| return; |
| |
| if (!pfvf->aura_ctx) { |
| seq_puts(m, "Aura context is not initialized\n"); |
| } else { |
| bitmap_print_to_pagebuf(false, buf, pfvf->aura_bmap, |
| pfvf->aura_ctx->qsize); |
| seq_printf(m, "Aura count : %d\n", pfvf->aura_ctx->qsize); |
| seq_printf(m, "Aura context ena/dis bitmap : %s\n", buf); |
| } |
| |
| if (!pfvf->pool_ctx) { |
| seq_puts(m, "Pool context is not initialized\n"); |
| } else { |
| bitmap_print_to_pagebuf(false, buf, pfvf->pool_bmap, |
| pfvf->pool_ctx->qsize); |
| seq_printf(m, "Pool count : %d\n", pfvf->pool_ctx->qsize); |
| seq_printf(m, "Pool context ena/dis bitmap : %s\n", buf); |
| } |
| kfree(buf); |
| } |
| |
| /* The 'qsize' entry dumps current Aura/Pool context Qsize |
| * and each context's current enable/disable status in a bitmap. |
| */ |
| static int rvu_dbg_qsize_display(struct seq_file *filp, void *unsused, |
| int blktype) |
| { |
| void (*print_qsize)(struct seq_file *filp, |
| struct rvu_pfvf *pfvf) = NULL; |
| struct dentry *current_dir; |
| struct rvu_pfvf *pfvf; |
| struct rvu *rvu; |
| int qsize_id; |
| u16 pcifunc; |
| int blkaddr; |
| |
| rvu = filp->private; |
| switch (blktype) { |
| case BLKTYPE_NPA: |
| qsize_id = rvu->rvu_dbg.npa_qsize_id; |
| print_qsize = print_npa_qsize; |
| break; |
| |
| case BLKTYPE_NIX: |
| qsize_id = rvu->rvu_dbg.nix_qsize_id; |
| print_qsize = print_nix_qsize; |
| break; |
| |
| default: |
| return -EINVAL; |
| } |
| |
| if (blktype == BLKTYPE_NPA) { |
| blkaddr = BLKADDR_NPA; |
| } else { |
| current_dir = filp->file->f_path.dentry->d_parent; |
| blkaddr = (!strcmp(current_dir->d_name.name, "nix1") ? |
| BLKADDR_NIX1 : BLKADDR_NIX0); |
| } |
| |
| if (!rvu_dbg_is_valid_lf(rvu, blkaddr, qsize_id, &pcifunc)) |
| return -EINVAL; |
| |
| pfvf = rvu_get_pfvf(rvu, pcifunc); |
| print_qsize(filp, pfvf); |
| |
| return 0; |
| } |
| |
| static ssize_t rvu_dbg_qsize_write(struct file *filp, |
| const char __user *buffer, size_t count, |
| loff_t *ppos, int blktype) |
| { |
| char *blk_string = (blktype == BLKTYPE_NPA) ? "npa" : "nix"; |
| struct seq_file *seqfile = filp->private_data; |
| char *cmd_buf, *cmd_buf_tmp, *subtoken; |
| struct rvu *rvu = seqfile->private; |
| struct dentry *current_dir; |
| int blkaddr; |
| u16 pcifunc; |
| int ret, lf; |
| |
| cmd_buf = memdup_user(buffer, count + 1); |
| if (IS_ERR(cmd_buf)) |
| return -ENOMEM; |
| |
| cmd_buf[count] = '\0'; |
| |
| cmd_buf_tmp = strchr(cmd_buf, '\n'); |
| if (cmd_buf_tmp) { |
| *cmd_buf_tmp = '\0'; |
| count = cmd_buf_tmp - cmd_buf + 1; |
| } |
| |
| cmd_buf_tmp = cmd_buf; |
| subtoken = strsep(&cmd_buf, " "); |
| ret = subtoken ? kstrtoint(subtoken, 10, &lf) : -EINVAL; |
| if (cmd_buf) |
| ret = -EINVAL; |
| |
| if (ret < 0 || !strncmp(subtoken, "help", 4)) { |
| dev_info(rvu->dev, "Use echo <%s-lf > qsize\n", blk_string); |
| goto qsize_write_done; |
| } |
| |
| if (blktype == BLKTYPE_NPA) { |
| blkaddr = BLKADDR_NPA; |
| } else { |
| current_dir = filp->f_path.dentry->d_parent; |
| blkaddr = (!strcmp(current_dir->d_name.name, "nix1") ? |
| BLKADDR_NIX1 : BLKADDR_NIX0); |
| } |
| |
| if (!rvu_dbg_is_valid_lf(rvu, blkaddr, lf, &pcifunc)) { |
| ret = -EINVAL; |
| goto qsize_write_done; |
| } |
| if (blktype == BLKTYPE_NPA) |
| rvu->rvu_dbg.npa_qsize_id = lf; |
| else |
| rvu->rvu_dbg.nix_qsize_id = lf; |
| |
| qsize_write_done: |
| kfree(cmd_buf_tmp); |
| return ret ? ret : count; |
| } |
| |
| static ssize_t rvu_dbg_npa_qsize_write(struct file *filp, |
| const char __user *buffer, |
| size_t count, loff_t *ppos) |
| { |
| return rvu_dbg_qsize_write(filp, buffer, count, ppos, |
| BLKTYPE_NPA); |
| } |
| |
| static int rvu_dbg_npa_qsize_display(struct seq_file *filp, void *unused) |
| { |
| return rvu_dbg_qsize_display(filp, unused, BLKTYPE_NPA); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(npa_qsize, npa_qsize_display, npa_qsize_write); |
| |
| /* Dumps given NPA Aura's context */ |
| static void print_npa_aura_ctx(struct seq_file *m, struct npa_aq_enq_rsp *rsp) |
| { |
| struct npa_aura_s *aura = &rsp->aura; |
| struct rvu *rvu = m->private; |
| |
| seq_printf(m, "W0: Pool addr\t\t%llx\n", aura->pool_addr); |
| |
| seq_printf(m, "W1: ena\t\t\t%d\nW1: pool caching\t%d\n", |
| aura->ena, aura->pool_caching); |
| seq_printf(m, "W1: pool way mask\t%d\nW1: avg con\t\t%d\n", |
| aura->pool_way_mask, aura->avg_con); |
| seq_printf(m, "W1: pool drop ena\t%d\nW1: aura drop ena\t%d\n", |
| aura->pool_drop_ena, aura->aura_drop_ena); |
| seq_printf(m, "W1: bp_ena\t\t%d\nW1: aura drop\t\t%d\n", |
| aura->bp_ena, aura->aura_drop); |
| seq_printf(m, "W1: aura shift\t\t%d\nW1: avg_level\t\t%d\n", |
| aura->shift, aura->avg_level); |
| |
| seq_printf(m, "W2: count\t\t%llu\nW2: nix0_bpid\t\t%d\nW2: nix1_bpid\t\t%d\n", |
| (u64)aura->count, aura->nix0_bpid, aura->nix1_bpid); |
| |
| seq_printf(m, "W3: limit\t\t%llu\nW3: bp\t\t\t%d\nW3: fc_ena\t\t%d\n", |
| (u64)aura->limit, aura->bp, aura->fc_ena); |
| |
| if (!is_rvu_otx2(rvu)) |
| seq_printf(m, "W3: fc_be\t\t%d\n", aura->fc_be); |
| seq_printf(m, "W3: fc_up_crossing\t%d\nW3: fc_stype\t\t%d\n", |
| aura->fc_up_crossing, aura->fc_stype); |
| seq_printf(m, "W3: fc_hyst_bits\t%d\n", aura->fc_hyst_bits); |
| |
| seq_printf(m, "W4: fc_addr\t\t%llx\n", aura->fc_addr); |
| |
| seq_printf(m, "W5: pool_drop\t\t%d\nW5: update_time\t\t%d\n", |
| aura->pool_drop, aura->update_time); |
| seq_printf(m, "W5: err_int \t\t%d\nW5: err_int_ena\t\t%d\n", |
| aura->err_int, aura->err_int_ena); |
| seq_printf(m, "W5: thresh_int\t\t%d\nW5: thresh_int_ena \t%d\n", |
| aura->thresh_int, aura->thresh_int_ena); |
| seq_printf(m, "W5: thresh_up\t\t%d\nW5: thresh_qint_idx\t%d\n", |
| aura->thresh_up, aura->thresh_qint_idx); |
| seq_printf(m, "W5: err_qint_idx \t%d\n", aura->err_qint_idx); |
| |
| seq_printf(m, "W6: thresh\t\t%llu\n", (u64)aura->thresh); |
| if (!is_rvu_otx2(rvu)) |
| seq_printf(m, "W6: fc_msh_dst\t\t%d\n", aura->fc_msh_dst); |
| } |
| |
| /* Dumps given NPA Pool's context */ |
| static void print_npa_pool_ctx(struct seq_file *m, struct npa_aq_enq_rsp *rsp) |
| { |
| struct npa_pool_s *pool = &rsp->pool; |
| struct rvu *rvu = m->private; |
| |
| seq_printf(m, "W0: Stack base\t\t%llx\n", pool->stack_base); |
| |
| seq_printf(m, "W1: ena \t\t%d\nW1: nat_align \t\t%d\n", |
| pool->ena, pool->nat_align); |
| seq_printf(m, "W1: stack_caching\t%d\nW1: stack_way_mask\t%d\n", |
| pool->stack_caching, pool->stack_way_mask); |
| seq_printf(m, "W1: buf_offset\t\t%d\nW1: buf_size\t\t%d\n", |
| pool->buf_offset, pool->buf_size); |
| |
| seq_printf(m, "W2: stack_max_pages \t%d\nW2: stack_pages\t\t%d\n", |
| pool->stack_max_pages, pool->stack_pages); |
| |
| seq_printf(m, "W3: op_pc \t\t%llu\n", (u64)pool->op_pc); |
| |
| seq_printf(m, "W4: stack_offset\t%d\nW4: shift\t\t%d\nW4: avg_level\t\t%d\n", |
| pool->stack_offset, pool->shift, pool->avg_level); |
| seq_printf(m, "W4: avg_con \t\t%d\nW4: fc_ena\t\t%d\nW4: fc_stype\t\t%d\n", |
| pool->avg_con, pool->fc_ena, pool->fc_stype); |
| seq_printf(m, "W4: fc_hyst_bits\t%d\nW4: fc_up_crossing\t%d\n", |
| pool->fc_hyst_bits, pool->fc_up_crossing); |
| if (!is_rvu_otx2(rvu)) |
| seq_printf(m, "W4: fc_be\t\t%d\n", pool->fc_be); |
| seq_printf(m, "W4: update_time\t\t%d\n", pool->update_time); |
| |
| seq_printf(m, "W5: fc_addr\t\t%llx\n", pool->fc_addr); |
| |
| seq_printf(m, "W6: ptr_start\t\t%llx\n", pool->ptr_start); |
| |
| seq_printf(m, "W7: ptr_end\t\t%llx\n", pool->ptr_end); |
| |
| seq_printf(m, "W8: err_int\t\t%d\nW8: err_int_ena\t\t%d\n", |
| pool->err_int, pool->err_int_ena); |
| seq_printf(m, "W8: thresh_int\t\t%d\n", pool->thresh_int); |
| seq_printf(m, "W8: thresh_int_ena\t%d\nW8: thresh_up\t\t%d\n", |
| pool->thresh_int_ena, pool->thresh_up); |
| seq_printf(m, "W8: thresh_qint_idx\t%d\nW8: err_qint_idx\t%d\n", |
| pool->thresh_qint_idx, pool->err_qint_idx); |
| if (!is_rvu_otx2(rvu)) |
| seq_printf(m, "W8: fc_msh_dst\t\t%d\n", pool->fc_msh_dst); |
| } |
| |
| /* Reads aura/pool's ctx from admin queue */ |
| static int rvu_dbg_npa_ctx_display(struct seq_file *m, void *unused, int ctype) |
| { |
| void (*print_npa_ctx)(struct seq_file *m, struct npa_aq_enq_rsp *rsp); |
| struct npa_aq_enq_req aq_req; |
| struct npa_aq_enq_rsp rsp; |
| struct rvu_pfvf *pfvf; |
| int aura, rc, max_id; |
| int npalf, id, all; |
| struct rvu *rvu; |
| u16 pcifunc; |
| |
| rvu = m->private; |
| |
| switch (ctype) { |
| case NPA_AQ_CTYPE_AURA: |
| npalf = rvu->rvu_dbg.npa_aura_ctx.lf; |
| id = rvu->rvu_dbg.npa_aura_ctx.id; |
| all = rvu->rvu_dbg.npa_aura_ctx.all; |
| break; |
| |
| case NPA_AQ_CTYPE_POOL: |
| npalf = rvu->rvu_dbg.npa_pool_ctx.lf; |
| id = rvu->rvu_dbg.npa_pool_ctx.id; |
| all = rvu->rvu_dbg.npa_pool_ctx.all; |
| break; |
| default: |
| return -EINVAL; |
| } |
| |
| if (!rvu_dbg_is_valid_lf(rvu, BLKADDR_NPA, npalf, &pcifunc)) |
| return -EINVAL; |
| |
| pfvf = rvu_get_pfvf(rvu, pcifunc); |
| if (ctype == NPA_AQ_CTYPE_AURA && !pfvf->aura_ctx) { |
| seq_puts(m, "Aura context is not initialized\n"); |
| return -EINVAL; |
| } else if (ctype == NPA_AQ_CTYPE_POOL && !pfvf->pool_ctx) { |
| seq_puts(m, "Pool context is not initialized\n"); |
| return -EINVAL; |
| } |
| |
| memset(&aq_req, 0, sizeof(struct npa_aq_enq_req)); |
| aq_req.hdr.pcifunc = pcifunc; |
| aq_req.ctype = ctype; |
| aq_req.op = NPA_AQ_INSTOP_READ; |
| if (ctype == NPA_AQ_CTYPE_AURA) { |
| max_id = pfvf->aura_ctx->qsize; |
| print_npa_ctx = print_npa_aura_ctx; |
| } else { |
| max_id = pfvf->pool_ctx->qsize; |
| print_npa_ctx = print_npa_pool_ctx; |
| } |
| |
| if (id < 0 || id >= max_id) { |
| seq_printf(m, "Invalid %s, valid range is 0-%d\n", |
| (ctype == NPA_AQ_CTYPE_AURA) ? "aura" : "pool", |
| max_id - 1); |
| return -EINVAL; |
| } |
| |
| if (all) |
| id = 0; |
| else |
| max_id = id + 1; |
| |
| for (aura = id; aura < max_id; aura++) { |
| aq_req.aura_id = aura; |
| seq_printf(m, "======%s : %d=======\n", |
| (ctype == NPA_AQ_CTYPE_AURA) ? "AURA" : "POOL", |
| aq_req.aura_id); |
| rc = rvu_npa_aq_enq_inst(rvu, &aq_req, &rsp); |
| if (rc) { |
| seq_puts(m, "Failed to read context\n"); |
| return -EINVAL; |
| } |
| print_npa_ctx(m, &rsp); |
| } |
| return 0; |
| } |
| |
| static int write_npa_ctx(struct rvu *rvu, bool all, |
| int npalf, int id, int ctype) |
| { |
| struct rvu_pfvf *pfvf; |
| int max_id = 0; |
| u16 pcifunc; |
| |
| if (!rvu_dbg_is_valid_lf(rvu, BLKADDR_NPA, npalf, &pcifunc)) |
| return -EINVAL; |
| |
| pfvf = rvu_get_pfvf(rvu, pcifunc); |
| |
| if (ctype == NPA_AQ_CTYPE_AURA) { |
| if (!pfvf->aura_ctx) { |
| dev_warn(rvu->dev, "Aura context is not initialized\n"); |
| return -EINVAL; |
| } |
| max_id = pfvf->aura_ctx->qsize; |
| } else if (ctype == NPA_AQ_CTYPE_POOL) { |
| if (!pfvf->pool_ctx) { |
| dev_warn(rvu->dev, "Pool context is not initialized\n"); |
| return -EINVAL; |
| } |
| max_id = pfvf->pool_ctx->qsize; |
| } |
| |
| if (id < 0 || id >= max_id) { |
| dev_warn(rvu->dev, "Invalid %s, valid range is 0-%d\n", |
| (ctype == NPA_AQ_CTYPE_AURA) ? "aura" : "pool", |
| max_id - 1); |
| return -EINVAL; |
| } |
| |
| switch (ctype) { |
| case NPA_AQ_CTYPE_AURA: |
| rvu->rvu_dbg.npa_aura_ctx.lf = npalf; |
| rvu->rvu_dbg.npa_aura_ctx.id = id; |
| rvu->rvu_dbg.npa_aura_ctx.all = all; |
| break; |
| |
| case NPA_AQ_CTYPE_POOL: |
| rvu->rvu_dbg.npa_pool_ctx.lf = npalf; |
| rvu->rvu_dbg.npa_pool_ctx.id = id; |
| rvu->rvu_dbg.npa_pool_ctx.all = all; |
| break; |
| default: |
| return -EINVAL; |
| } |
| return 0; |
| } |
| |
| static int parse_cmd_buffer_ctx(char *cmd_buf, size_t *count, |
| const char __user *buffer, int *npalf, |
| int *id, bool *all) |
| { |
| int bytes_not_copied; |
| char *cmd_buf_tmp; |
| char *subtoken; |
| int ret; |
| |
| bytes_not_copied = copy_from_user(cmd_buf, buffer, *count); |
| if (bytes_not_copied) |
| return -EFAULT; |
| |
| cmd_buf[*count] = '\0'; |
| cmd_buf_tmp = strchr(cmd_buf, '\n'); |
| |
| if (cmd_buf_tmp) { |
| *cmd_buf_tmp = '\0'; |
| *count = cmd_buf_tmp - cmd_buf + 1; |
| } |
| |
| subtoken = strsep(&cmd_buf, " "); |
| ret = subtoken ? kstrtoint(subtoken, 10, npalf) : -EINVAL; |
| if (ret < 0) |
| return ret; |
| subtoken = strsep(&cmd_buf, " "); |
| if (subtoken && strcmp(subtoken, "all") == 0) { |
| *all = true; |
| } else { |
| ret = subtoken ? kstrtoint(subtoken, 10, id) : -EINVAL; |
| if (ret < 0) |
| return ret; |
| } |
| if (cmd_buf) |
| return -EINVAL; |
| return ret; |
| } |
| |
| static ssize_t rvu_dbg_npa_ctx_write(struct file *filp, |
| const char __user *buffer, |
| size_t count, loff_t *ppos, int ctype) |
| { |
| char *cmd_buf, *ctype_string = (ctype == NPA_AQ_CTYPE_AURA) ? |
| "aura" : "pool"; |
| struct seq_file *seqfp = filp->private_data; |
| struct rvu *rvu = seqfp->private; |
| int npalf, id = 0, ret; |
| bool all = false; |
| |
| if ((*ppos != 0) || !count) |
| return -EINVAL; |
| |
| cmd_buf = kzalloc(count + 1, GFP_KERNEL); |
| if (!cmd_buf) |
| return count; |
| ret = parse_cmd_buffer_ctx(cmd_buf, &count, buffer, |
| &npalf, &id, &all); |
| if (ret < 0) { |
| dev_info(rvu->dev, |
| "Usage: echo <npalf> [%s number/all] > %s_ctx\n", |
| ctype_string, ctype_string); |
| goto done; |
| } else { |
| ret = write_npa_ctx(rvu, all, npalf, id, ctype); |
| } |
| done: |
| kfree(cmd_buf); |
| return ret ? ret : count; |
| } |
| |
| static ssize_t rvu_dbg_npa_aura_ctx_write(struct file *filp, |
| const char __user *buffer, |
| size_t count, loff_t *ppos) |
| { |
| return rvu_dbg_npa_ctx_write(filp, buffer, count, ppos, |
| NPA_AQ_CTYPE_AURA); |
| } |
| |
| static int rvu_dbg_npa_aura_ctx_display(struct seq_file *filp, void *unused) |
| { |
| return rvu_dbg_npa_ctx_display(filp, unused, NPA_AQ_CTYPE_AURA); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(npa_aura_ctx, npa_aura_ctx_display, npa_aura_ctx_write); |
| |
| static ssize_t rvu_dbg_npa_pool_ctx_write(struct file *filp, |
| const char __user *buffer, |
| size_t count, loff_t *ppos) |
| { |
| return rvu_dbg_npa_ctx_write(filp, buffer, count, ppos, |
| NPA_AQ_CTYPE_POOL); |
| } |
| |
| static int rvu_dbg_npa_pool_ctx_display(struct seq_file *filp, void *unused) |
| { |
| return rvu_dbg_npa_ctx_display(filp, unused, NPA_AQ_CTYPE_POOL); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(npa_pool_ctx, npa_pool_ctx_display, npa_pool_ctx_write); |
| |
| static void ndc_cache_stats(struct seq_file *s, int blk_addr, |
| int ctype, int transaction) |
| { |
| u64 req, out_req, lat, cant_alloc; |
| struct nix_hw *nix_hw; |
| struct rvu *rvu; |
| int port; |
| |
| if (blk_addr == BLKADDR_NDC_NPA0) { |
| rvu = s->private; |
| } else { |
| nix_hw = s->private; |
| rvu = nix_hw->rvu; |
| } |
| |
| for (port = 0; port < NDC_MAX_PORT; port++) { |
| req = rvu_read64(rvu, blk_addr, NDC_AF_PORTX_RTX_RWX_REQ_PC |
| (port, ctype, transaction)); |
| lat = rvu_read64(rvu, blk_addr, NDC_AF_PORTX_RTX_RWX_LAT_PC |
| (port, ctype, transaction)); |
| out_req = rvu_read64(rvu, blk_addr, |
| NDC_AF_PORTX_RTX_RWX_OSTDN_PC |
| (port, ctype, transaction)); |
| cant_alloc = rvu_read64(rvu, blk_addr, |
| NDC_AF_PORTX_RTX_CANT_ALLOC_PC |
| (port, transaction)); |
| seq_printf(s, "\nPort:%d\n", port); |
| seq_printf(s, "\tTotal Requests:\t\t%lld\n", req); |
| seq_printf(s, "\tTotal Time Taken:\t%lld cycles\n", lat); |
| seq_printf(s, "\tAvg Latency:\t\t%lld cycles\n", lat / req); |
| seq_printf(s, "\tOutstanding Requests:\t%lld\n", out_req); |
| seq_printf(s, "\tCant Alloc Requests:\t%lld\n", cant_alloc); |
| } |
| } |
| |
| static int ndc_blk_cache_stats(struct seq_file *s, int idx, int blk_addr) |
| { |
| seq_puts(s, "\n***** CACHE mode read stats *****\n"); |
| ndc_cache_stats(s, blk_addr, CACHING, NDC_READ_TRANS); |
| seq_puts(s, "\n***** CACHE mode write stats *****\n"); |
| ndc_cache_stats(s, blk_addr, CACHING, NDC_WRITE_TRANS); |
| seq_puts(s, "\n***** BY-PASS mode read stats *****\n"); |
| ndc_cache_stats(s, blk_addr, BYPASS, NDC_READ_TRANS); |
| seq_puts(s, "\n***** BY-PASS mode write stats *****\n"); |
| ndc_cache_stats(s, blk_addr, BYPASS, NDC_WRITE_TRANS); |
| return 0; |
| } |
| |
| static int rvu_dbg_npa_ndc_cache_display(struct seq_file *filp, void *unused) |
| { |
| return ndc_blk_cache_stats(filp, NPA0_U, BLKADDR_NDC_NPA0); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(npa_ndc_cache, npa_ndc_cache_display, NULL); |
| |
| static int ndc_blk_hits_miss_stats(struct seq_file *s, int idx, int blk_addr) |
| { |
| struct nix_hw *nix_hw; |
| struct rvu *rvu; |
| int bank, max_bank; |
| u64 ndc_af_const; |
| |
| if (blk_addr == BLKADDR_NDC_NPA0) { |
| rvu = s->private; |
| } else { |
| nix_hw = s->private; |
| rvu = nix_hw->rvu; |
| } |
| |
| ndc_af_const = rvu_read64(rvu, blk_addr, NDC_AF_CONST); |
| max_bank = FIELD_GET(NDC_AF_BANK_MASK, ndc_af_const); |
| for (bank = 0; bank < max_bank; bank++) { |
| seq_printf(s, "BANK:%d\n", bank); |
| seq_printf(s, "\tHits:\t%lld\n", |
| (u64)rvu_read64(rvu, blk_addr, |
| NDC_AF_BANKX_HIT_PC(bank))); |
| seq_printf(s, "\tMiss:\t%lld\n", |
| (u64)rvu_read64(rvu, blk_addr, |
| NDC_AF_BANKX_MISS_PC(bank))); |
| } |
| return 0; |
| } |
| |
| static int rvu_dbg_nix_ndc_rx_cache_display(struct seq_file *filp, void *unused) |
| { |
| struct nix_hw *nix_hw = filp->private; |
| int blkaddr = 0; |
| int ndc_idx = 0; |
| |
| blkaddr = (nix_hw->blkaddr == BLKADDR_NIX1 ? |
| BLKADDR_NDC_NIX1_RX : BLKADDR_NDC_NIX0_RX); |
| ndc_idx = (nix_hw->blkaddr == BLKADDR_NIX1 ? NIX1_RX : NIX0_RX); |
| |
| return ndc_blk_cache_stats(filp, ndc_idx, blkaddr); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(nix_ndc_rx_cache, nix_ndc_rx_cache_display, NULL); |
| |
| static int rvu_dbg_nix_ndc_tx_cache_display(struct seq_file *filp, void *unused) |
| { |
| struct nix_hw *nix_hw = filp->private; |
| int blkaddr = 0; |
| int ndc_idx = 0; |
| |
| blkaddr = (nix_hw->blkaddr == BLKADDR_NIX1 ? |
| BLKADDR_NDC_NIX1_TX : BLKADDR_NDC_NIX0_TX); |
| ndc_idx = (nix_hw->blkaddr == BLKADDR_NIX1 ? NIX1_TX : NIX0_TX); |
| |
| return ndc_blk_cache_stats(filp, ndc_idx, blkaddr); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(nix_ndc_tx_cache, nix_ndc_tx_cache_display, NULL); |
| |
| static int rvu_dbg_npa_ndc_hits_miss_display(struct seq_file *filp, |
| void *unused) |
| { |
| return ndc_blk_hits_miss_stats(filp, NPA0_U, BLKADDR_NDC_NPA0); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(npa_ndc_hits_miss, npa_ndc_hits_miss_display, NULL); |
| |
| static int rvu_dbg_nix_ndc_rx_hits_miss_display(struct seq_file *filp, |
| void *unused) |
| { |
| struct nix_hw *nix_hw = filp->private; |
| int ndc_idx = NPA0_U; |
| int blkaddr = 0; |
| |
| blkaddr = (nix_hw->blkaddr == BLKADDR_NIX1 ? |
| BLKADDR_NDC_NIX1_RX : BLKADDR_NDC_NIX0_RX); |
| |
| return ndc_blk_hits_miss_stats(filp, ndc_idx, blkaddr); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(nix_ndc_rx_hits_miss, nix_ndc_rx_hits_miss_display, NULL); |
| |
| static int rvu_dbg_nix_ndc_tx_hits_miss_display(struct seq_file *filp, |
| void *unused) |
| { |
| struct nix_hw *nix_hw = filp->private; |
| int ndc_idx = NPA0_U; |
| int blkaddr = 0; |
| |
| blkaddr = (nix_hw->blkaddr == BLKADDR_NIX1 ? |
| BLKADDR_NDC_NIX1_TX : BLKADDR_NDC_NIX0_TX); |
| |
| return ndc_blk_hits_miss_stats(filp, ndc_idx, blkaddr); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(nix_ndc_tx_hits_miss, nix_ndc_tx_hits_miss_display, NULL); |
| |
| static void print_nix_cn10k_sq_ctx(struct seq_file *m, |
| struct nix_cn10k_sq_ctx_s *sq_ctx) |
| { |
| seq_printf(m, "W0: ena \t\t\t%d\nW0: qint_idx \t\t\t%d\n", |
| sq_ctx->ena, sq_ctx->qint_idx); |
| seq_printf(m, "W0: substream \t\t\t0x%03x\nW0: sdp_mcast \t\t\t%d\n", |
| sq_ctx->substream, sq_ctx->sdp_mcast); |
| seq_printf(m, "W0: cq \t\t\t\t%d\nW0: sqe_way_mask \t\t%d\n\n", |
| sq_ctx->cq, sq_ctx->sqe_way_mask); |
| |
| seq_printf(m, "W1: smq \t\t\t%d\nW1: cq_ena \t\t\t%d\nW1: xoff\t\t\t%d\n", |
| sq_ctx->smq, sq_ctx->cq_ena, sq_ctx->xoff); |
| seq_printf(m, "W1: sso_ena \t\t\t%d\nW1: smq_rr_weight\t\t%d\n", |
| sq_ctx->sso_ena, sq_ctx->smq_rr_weight); |
| seq_printf(m, "W1: default_chan\t\t%d\nW1: sqb_count\t\t\t%d\n\n", |
| sq_ctx->default_chan, sq_ctx->sqb_count); |
| |
| seq_printf(m, "W2: smq_rr_count_lb \t\t%d\n", sq_ctx->smq_rr_count_lb); |
| seq_printf(m, "W2: smq_rr_count_ub \t\t%d\n", sq_ctx->smq_rr_count_ub); |
| seq_printf(m, "W2: sqb_aura \t\t\t%d\nW2: sq_int \t\t\t%d\n", |
| sq_ctx->sqb_aura, sq_ctx->sq_int); |
| seq_printf(m, "W2: sq_int_ena \t\t\t%d\nW2: sqe_stype \t\t\t%d\n", |
| sq_ctx->sq_int_ena, sq_ctx->sqe_stype); |
| |
| seq_printf(m, "W3: max_sqe_size\t\t%d\nW3: cq_limit\t\t\t%d\n", |
| sq_ctx->max_sqe_size, sq_ctx->cq_limit); |
| seq_printf(m, "W3: lmt_dis \t\t\t%d\nW3: mnq_dis \t\t\t%d\n", |
| sq_ctx->mnq_dis, sq_ctx->lmt_dis); |
| seq_printf(m, "W3: smq_next_sq\t\t\t%d\nW3: smq_lso_segnum\t\t%d\n", |
| sq_ctx->smq_next_sq, sq_ctx->smq_lso_segnum); |
| seq_printf(m, "W3: tail_offset \t\t%d\nW3: smenq_offset\t\t%d\n", |
| sq_ctx->tail_offset, sq_ctx->smenq_offset); |
| seq_printf(m, "W3: head_offset\t\t\t%d\nW3: smenq_next_sqb_vld\t\t%d\n\n", |
| sq_ctx->head_offset, sq_ctx->smenq_next_sqb_vld); |
| |
| seq_printf(m, "W3: smq_next_sq_vld\t\t%d\nW3: smq_pend\t\t\t%d\n", |
| sq_ctx->smq_next_sq_vld, sq_ctx->smq_pend); |
| seq_printf(m, "W4: next_sqb \t\t\t%llx\n\n", sq_ctx->next_sqb); |
| seq_printf(m, "W5: tail_sqb \t\t\t%llx\n\n", sq_ctx->tail_sqb); |
| seq_printf(m, "W6: smenq_sqb \t\t\t%llx\n\n", sq_ctx->smenq_sqb); |
| seq_printf(m, "W7: smenq_next_sqb \t\t%llx\n\n", |
| sq_ctx->smenq_next_sqb); |
| |
| seq_printf(m, "W8: head_sqb\t\t\t%llx\n\n", sq_ctx->head_sqb); |
| |
| seq_printf(m, "W9: vfi_lso_total\t\t%d\n", sq_ctx->vfi_lso_total); |
| seq_printf(m, "W9: vfi_lso_sizem1\t\t%d\nW9: vfi_lso_sb\t\t\t%d\n", |
| sq_ctx->vfi_lso_sizem1, sq_ctx->vfi_lso_sb); |
| seq_printf(m, "W9: vfi_lso_mps\t\t\t%d\nW9: vfi_lso_vlan0_ins_ena\t%d\n", |
| sq_ctx->vfi_lso_mps, sq_ctx->vfi_lso_vlan0_ins_ena); |
| seq_printf(m, "W9: vfi_lso_vlan1_ins_ena\t%d\nW9: vfi_lso_vld \t\t%d\n\n", |
| sq_ctx->vfi_lso_vld, sq_ctx->vfi_lso_vlan1_ins_ena); |
| |
| seq_printf(m, "W10: scm_lso_rem \t\t%llu\n\n", |
| (u64)sq_ctx->scm_lso_rem); |
| seq_printf(m, "W11: octs \t\t\t%llu\n\n", (u64)sq_ctx->octs); |
| seq_printf(m, "W12: pkts \t\t\t%llu\n\n", (u64)sq_ctx->pkts); |
| seq_printf(m, "W14: dropped_octs \t\t%llu\n\n", |
| (u64)sq_ctx->dropped_octs); |
| seq_printf(m, "W15: dropped_pkts \t\t%llu\n\n", |
| (u64)sq_ctx->dropped_pkts); |
| } |
| |
| /* Dumps given nix_sq's context */ |
| static void print_nix_sq_ctx(struct seq_file *m, struct nix_aq_enq_rsp *rsp) |
| { |
| struct nix_sq_ctx_s *sq_ctx = &rsp->sq; |
| struct nix_hw *nix_hw = m->private; |
| struct rvu *rvu = nix_hw->rvu; |
| |
| if (!is_rvu_otx2(rvu)) { |
| print_nix_cn10k_sq_ctx(m, (struct nix_cn10k_sq_ctx_s *)sq_ctx); |
| return; |
| } |
| seq_printf(m, "W0: sqe_way_mask \t\t%d\nW0: cq \t\t\t\t%d\n", |
| sq_ctx->sqe_way_mask, sq_ctx->cq); |
| seq_printf(m, "W0: sdp_mcast \t\t\t%d\nW0: substream \t\t\t0x%03x\n", |
| sq_ctx->sdp_mcast, sq_ctx->substream); |
| seq_printf(m, "W0: qint_idx \t\t\t%d\nW0: ena \t\t\t%d\n\n", |
| sq_ctx->qint_idx, sq_ctx->ena); |
| |
| seq_printf(m, "W1: sqb_count \t\t\t%d\nW1: default_chan \t\t%d\n", |
| sq_ctx->sqb_count, sq_ctx->default_chan); |
| seq_printf(m, "W1: smq_rr_quantum \t\t%d\nW1: sso_ena \t\t\t%d\n", |
| sq_ctx->smq_rr_quantum, sq_ctx->sso_ena); |
| seq_printf(m, "W1: xoff \t\t\t%d\nW1: cq_ena \t\t\t%d\nW1: smq\t\t\t\t%d\n\n", |
| sq_ctx->xoff, sq_ctx->cq_ena, sq_ctx->smq); |
| |
| seq_printf(m, "W2: sqe_stype \t\t\t%d\nW2: sq_int_ena \t\t\t%d\n", |
| sq_ctx->sqe_stype, sq_ctx->sq_int_ena); |
| seq_printf(m, "W2: sq_int \t\t\t%d\nW2: sqb_aura \t\t\t%d\n", |
| sq_ctx->sq_int, sq_ctx->sqb_aura); |
| seq_printf(m, "W2: smq_rr_count \t\t%d\n\n", sq_ctx->smq_rr_count); |
| |
| seq_printf(m, "W3: smq_next_sq_vld\t\t%d\nW3: smq_pend\t\t\t%d\n", |
| sq_ctx->smq_next_sq_vld, sq_ctx->smq_pend); |
| seq_printf(m, "W3: smenq_next_sqb_vld \t\t%d\nW3: head_offset\t\t\t%d\n", |
| sq_ctx->smenq_next_sqb_vld, sq_ctx->head_offset); |
| seq_printf(m, "W3: smenq_offset\t\t%d\nW3: tail_offset\t\t\t%d\n", |
| sq_ctx->smenq_offset, sq_ctx->tail_offset); |
| seq_printf(m, "W3: smq_lso_segnum \t\t%d\nW3: smq_next_sq\t\t\t%d\n", |
| sq_ctx->smq_lso_segnum, sq_ctx->smq_next_sq); |
| seq_printf(m, "W3: mnq_dis \t\t\t%d\nW3: lmt_dis \t\t\t%d\n", |
| sq_ctx->mnq_dis, sq_ctx->lmt_dis); |
| seq_printf(m, "W3: cq_limit\t\t\t%d\nW3: max_sqe_size\t\t%d\n\n", |
| sq_ctx->cq_limit, sq_ctx->max_sqe_size); |
| |
| seq_printf(m, "W4: next_sqb \t\t\t%llx\n\n", sq_ctx->next_sqb); |
| seq_printf(m, "W5: tail_sqb \t\t\t%llx\n\n", sq_ctx->tail_sqb); |
| seq_printf(m, "W6: smenq_sqb \t\t\t%llx\n\n", sq_ctx->smenq_sqb); |
| seq_printf(m, "W7: smenq_next_sqb \t\t%llx\n\n", |
| sq_ctx->smenq_next_sqb); |
| |
| seq_printf(m, "W8: head_sqb\t\t\t%llx\n\n", sq_ctx->head_sqb); |
| |
| seq_printf(m, "W9: vfi_lso_vld\t\t\t%d\nW9: vfi_lso_vlan1_ins_ena\t%d\n", |
| sq_ctx->vfi_lso_vld, sq_ctx->vfi_lso_vlan1_ins_ena); |
| seq_printf(m, "W9: vfi_lso_vlan0_ins_ena\t%d\nW9: vfi_lso_mps\t\t\t%d\n", |
| sq_ctx->vfi_lso_vlan0_ins_ena, sq_ctx->vfi_lso_mps); |
| seq_printf(m, "W9: vfi_lso_sb\t\t\t%d\nW9: vfi_lso_sizem1\t\t%d\n", |
| sq_ctx->vfi_lso_sb, sq_ctx->vfi_lso_sizem1); |
| seq_printf(m, "W9: vfi_lso_total\t\t%d\n\n", sq_ctx->vfi_lso_total); |
| |
| seq_printf(m, "W10: scm_lso_rem \t\t%llu\n\n", |
| (u64)sq_ctx->scm_lso_rem); |
| seq_printf(m, "W11: octs \t\t\t%llu\n\n", (u64)sq_ctx->octs); |
| seq_printf(m, "W12: pkts \t\t\t%llu\n\n", (u64)sq_ctx->pkts); |
| seq_printf(m, "W14: dropped_octs \t\t%llu\n\n", |
| (u64)sq_ctx->dropped_octs); |
| seq_printf(m, "W15: dropped_pkts \t\t%llu\n\n", |
| (u64)sq_ctx->dropped_pkts); |
| } |
| |
| static void print_nix_cn10k_rq_ctx(struct seq_file *m, |
| struct nix_cn10k_rq_ctx_s *rq_ctx) |
| { |
| seq_printf(m, "W0: ena \t\t\t%d\nW0: sso_ena \t\t\t%d\n", |
| rq_ctx->ena, rq_ctx->sso_ena); |
| seq_printf(m, "W0: ipsech_ena \t\t\t%d\nW0: ena_wqwd \t\t\t%d\n", |
| rq_ctx->ipsech_ena, rq_ctx->ena_wqwd); |
| seq_printf(m, "W0: cq \t\t\t\t%d\nW0: lenerr_dis \t\t\t%d\n", |
| rq_ctx->cq, rq_ctx->lenerr_dis); |
| seq_printf(m, "W0: csum_il4_dis \t\t%d\nW0: csum_ol4_dis \t\t%d\n", |
| rq_ctx->csum_il4_dis, rq_ctx->csum_ol4_dis); |
| seq_printf(m, "W0: len_il4_dis \t\t%d\nW0: len_il3_dis \t\t%d\n", |
| rq_ctx->len_il4_dis, rq_ctx->len_il3_dis); |
| seq_printf(m, "W0: len_ol4_dis \t\t%d\nW0: len_ol3_dis \t\t%d\n", |
| rq_ctx->len_ol4_dis, rq_ctx->len_ol3_dis); |
| seq_printf(m, "W0: wqe_aura \t\t\t%d\n\n", rq_ctx->wqe_aura); |
| |
| seq_printf(m, "W1: spb_aura \t\t\t%d\nW1: lpb_aura \t\t\t%d\n", |
| rq_ctx->spb_aura, rq_ctx->lpb_aura); |
| seq_printf(m, "W1: spb_aura \t\t\t%d\n", rq_ctx->spb_aura); |
| seq_printf(m, "W1: sso_grp \t\t\t%d\nW1: sso_tt \t\t\t%d\n", |
| rq_ctx->sso_grp, rq_ctx->sso_tt); |
| seq_printf(m, "W1: pb_caching \t\t\t%d\nW1: wqe_caching \t\t%d\n", |
| rq_ctx->pb_caching, rq_ctx->wqe_caching); |
| seq_printf(m, "W1: xqe_drop_ena \t\t%d\nW1: spb_drop_ena \t\t%d\n", |
| rq_ctx->xqe_drop_ena, rq_ctx->spb_drop_ena); |
| seq_printf(m, "W1: lpb_drop_ena \t\t%d\nW1: pb_stashing \t\t%d\n", |
| rq_ctx->lpb_drop_ena, rq_ctx->pb_stashing); |
| seq_printf(m, "W1: ipsecd_drop_ena \t\t%d\nW1: chi_ena \t\t\t%d\n\n", |
| rq_ctx->ipsecd_drop_ena, rq_ctx->chi_ena); |
| |
| seq_printf(m, "W2: band_prof_id \t\t%d\n", rq_ctx->band_prof_id); |
| seq_printf(m, "W2: policer_ena \t\t%d\n", rq_ctx->policer_ena); |
| seq_printf(m, "W2: spb_sizem1 \t\t\t%d\n", rq_ctx->spb_sizem1); |
| seq_printf(m, "W2: wqe_skip \t\t\t%d\nW2: sqb_ena \t\t\t%d\n", |
| rq_ctx->wqe_skip, rq_ctx->spb_ena); |
| seq_printf(m, "W2: lpb_size1 \t\t\t%d\nW2: first_skip \t\t\t%d\n", |
| rq_ctx->lpb_sizem1, rq_ctx->first_skip); |
| seq_printf(m, "W2: later_skip\t\t\t%d\nW2: xqe_imm_size\t\t%d\n", |
| rq_ctx->later_skip, rq_ctx->xqe_imm_size); |
| seq_printf(m, "W2: xqe_imm_copy \t\t%d\nW2: xqe_hdr_split \t\t%d\n\n", |
| rq_ctx->xqe_imm_copy, rq_ctx->xqe_hdr_split); |
| |
| seq_printf(m, "W3: xqe_drop \t\t\t%d\nW3: xqe_pass \t\t\t%d\n", |
| rq_ctx->xqe_drop, rq_ctx->xqe_pass); |
| seq_printf(m, "W3: wqe_pool_drop \t\t%d\nW3: wqe_pool_pass \t\t%d\n", |
| rq_ctx->wqe_pool_drop, rq_ctx->wqe_pool_pass); |
| seq_printf(m, "W3: spb_pool_drop \t\t%d\nW3: spb_pool_pass \t\t%d\n", |
| rq_ctx->spb_pool_drop, rq_ctx->spb_pool_pass); |
| seq_printf(m, "W3: spb_aura_drop \t\t%d\nW3: spb_aura_pass \t\t%d\n\n", |
| rq_ctx->spb_aura_pass, rq_ctx->spb_aura_drop); |
| |
| seq_printf(m, "W4: lpb_aura_drop \t\t%d\nW3: lpb_aura_pass \t\t%d\n", |
| rq_ctx->lpb_aura_pass, rq_ctx->lpb_aura_drop); |
| seq_printf(m, "W4: lpb_pool_drop \t\t%d\nW3: lpb_pool_pass \t\t%d\n", |
| rq_ctx->lpb_pool_drop, rq_ctx->lpb_pool_pass); |
| seq_printf(m, "W4: rq_int \t\t\t%d\nW4: rq_int_ena\t\t\t%d\n", |
| rq_ctx->rq_int, rq_ctx->rq_int_ena); |
| seq_printf(m, "W4: qint_idx \t\t\t%d\n\n", rq_ctx->qint_idx); |
| |
| seq_printf(m, "W5: ltag \t\t\t%d\nW5: good_utag \t\t\t%d\n", |
| rq_ctx->ltag, rq_ctx->good_utag); |
| seq_printf(m, "W5: bad_utag \t\t\t%d\nW5: flow_tagw \t\t\t%d\n", |
| rq_ctx->bad_utag, rq_ctx->flow_tagw); |
| seq_printf(m, "W5: ipsec_vwqe \t\t\t%d\nW5: vwqe_ena \t\t\t%d\n", |
| rq_ctx->ipsec_vwqe, rq_ctx->vwqe_ena); |
| seq_printf(m, "W5: vwqe_wait \t\t\t%d\nW5: max_vsize_exp\t\t%d\n", |
| rq_ctx->vwqe_wait, rq_ctx->max_vsize_exp); |
| seq_printf(m, "W5: vwqe_skip \t\t\t%d\n\n", rq_ctx->vwqe_skip); |
| |
| seq_printf(m, "W6: octs \t\t\t%llu\n\n", (u64)rq_ctx->octs); |
| seq_printf(m, "W7: pkts \t\t\t%llu\n\n", (u64)rq_ctx->pkts); |
| seq_printf(m, "W8: drop_octs \t\t\t%llu\n\n", (u64)rq_ctx->drop_octs); |
| seq_printf(m, "W9: drop_pkts \t\t\t%llu\n\n", (u64)rq_ctx->drop_pkts); |
| seq_printf(m, "W10: re_pkts \t\t\t%llu\n", (u64)rq_ctx->re_pkts); |
| } |
| |
| /* Dumps given nix_rq's context */ |
| static void print_nix_rq_ctx(struct seq_file *m, struct nix_aq_enq_rsp *rsp) |
| { |
| struct nix_rq_ctx_s *rq_ctx = &rsp->rq; |
| struct nix_hw *nix_hw = m->private; |
| struct rvu *rvu = nix_hw->rvu; |
| |
| if (!is_rvu_otx2(rvu)) { |
| print_nix_cn10k_rq_ctx(m, (struct nix_cn10k_rq_ctx_s *)rq_ctx); |
| return; |
| } |
| |
| seq_printf(m, "W0: wqe_aura \t\t\t%d\nW0: substream \t\t\t0x%03x\n", |
| rq_ctx->wqe_aura, rq_ctx->substream); |
| seq_printf(m, "W0: cq \t\t\t\t%d\nW0: ena_wqwd \t\t\t%d\n", |
| rq_ctx->cq, rq_ctx->ena_wqwd); |
| seq_printf(m, "W0: ipsech_ena \t\t\t%d\nW0: sso_ena \t\t\t%d\n", |
| rq_ctx->ipsech_ena, rq_ctx->sso_ena); |
| seq_printf(m, "W0: ena \t\t\t%d\n\n", rq_ctx->ena); |
| |
| seq_printf(m, "W1: lpb_drop_ena \t\t%d\nW1: spb_drop_ena \t\t%d\n", |
| rq_ctx->lpb_drop_ena, rq_ctx->spb_drop_ena); |
| seq_printf(m, "W1: xqe_drop_ena \t\t%d\nW1: wqe_caching \t\t%d\n", |
| rq_ctx->xqe_drop_ena, rq_ctx->wqe_caching); |
| seq_printf(m, "W1: pb_caching \t\t\t%d\nW1: sso_tt \t\t\t%d\n", |
| rq_ctx->pb_caching, rq_ctx->sso_tt); |
| seq_printf(m, "W1: sso_grp \t\t\t%d\nW1: lpb_aura \t\t\t%d\n", |
| rq_ctx->sso_grp, rq_ctx->lpb_aura); |
| seq_printf(m, "W1: spb_aura \t\t\t%d\n\n", rq_ctx->spb_aura); |
| |
| seq_printf(m, "W2: xqe_hdr_split \t\t%d\nW2: xqe_imm_copy \t\t%d\n", |
| rq_ctx->xqe_hdr_split, rq_ctx->xqe_imm_copy); |
| seq_printf(m, "W2: xqe_imm_size \t\t%d\nW2: later_skip \t\t\t%d\n", |
| rq_ctx->xqe_imm_size, rq_ctx->later_skip); |
| seq_printf(m, "W2: first_skip \t\t\t%d\nW2: lpb_sizem1 \t\t\t%d\n", |
| rq_ctx->first_skip, rq_ctx->lpb_sizem1); |
| seq_printf(m, "W2: spb_ena \t\t\t%d\nW2: wqe_skip \t\t\t%d\n", |
| rq_ctx->spb_ena, rq_ctx->wqe_skip); |
| seq_printf(m, "W2: spb_sizem1 \t\t\t%d\n\n", rq_ctx->spb_sizem1); |
| |
| seq_printf(m, "W3: spb_pool_pass \t\t%d\nW3: spb_pool_drop \t\t%d\n", |
| rq_ctx->spb_pool_pass, rq_ctx->spb_pool_drop); |
| seq_printf(m, "W3: spb_aura_pass \t\t%d\nW3: spb_aura_drop \t\t%d\n", |
| rq_ctx->spb_aura_pass, rq_ctx->spb_aura_drop); |
| seq_printf(m, "W3: wqe_pool_pass \t\t%d\nW3: wqe_pool_drop \t\t%d\n", |
| rq_ctx->wqe_pool_pass, rq_ctx->wqe_pool_drop); |
| seq_printf(m, "W3: xqe_pass \t\t\t%d\nW3: xqe_drop \t\t\t%d\n\n", |
| rq_ctx->xqe_pass, rq_ctx->xqe_drop); |
| |
| seq_printf(m, "W4: qint_idx \t\t\t%d\nW4: rq_int_ena \t\t\t%d\n", |
| rq_ctx->qint_idx, rq_ctx->rq_int_ena); |
| seq_printf(m, "W4: rq_int \t\t\t%d\nW4: lpb_pool_pass \t\t%d\n", |
| rq_ctx->rq_int, rq_ctx->lpb_pool_pass); |
| seq_printf(m, "W4: lpb_pool_drop \t\t%d\nW4: lpb_aura_pass \t\t%d\n", |
| rq_ctx->lpb_pool_drop, rq_ctx->lpb_aura_pass); |
| seq_printf(m, "W4: lpb_aura_drop \t\t%d\n\n", rq_ctx->lpb_aura_drop); |
| |
| seq_printf(m, "W5: flow_tagw \t\t\t%d\nW5: bad_utag \t\t\t%d\n", |
| rq_ctx->flow_tagw, rq_ctx->bad_utag); |
| seq_printf(m, "W5: good_utag \t\t\t%d\nW5: ltag \t\t\t%d\n\n", |
| rq_ctx->good_utag, rq_ctx->ltag); |
| |
| seq_printf(m, "W6: octs \t\t\t%llu\n\n", (u64)rq_ctx->octs); |
| seq_printf(m, "W7: pkts \t\t\t%llu\n\n", (u64)rq_ctx->pkts); |
| seq_printf(m, "W8: drop_octs \t\t\t%llu\n\n", (u64)rq_ctx->drop_octs); |
| seq_printf(m, "W9: drop_pkts \t\t\t%llu\n\n", (u64)rq_ctx->drop_pkts); |
| seq_printf(m, "W10: re_pkts \t\t\t%llu\n", (u64)rq_ctx->re_pkts); |
| } |
| |
| /* Dumps given nix_cq's context */ |
| static void print_nix_cq_ctx(struct seq_file *m, struct nix_aq_enq_rsp *rsp) |
| { |
| struct nix_cq_ctx_s *cq_ctx = &rsp->cq; |
| |
| seq_printf(m, "W0: base \t\t\t%llx\n\n", cq_ctx->base); |
| |
| seq_printf(m, "W1: wrptr \t\t\t%llx\n", (u64)cq_ctx->wrptr); |
| seq_printf(m, "W1: avg_con \t\t\t%d\nW1: cint_idx \t\t\t%d\n", |
| cq_ctx->avg_con, cq_ctx->cint_idx); |
| seq_printf(m, "W1: cq_err \t\t\t%d\nW1: qint_idx \t\t\t%d\n", |
| cq_ctx->cq_err, cq_ctx->qint_idx); |
| seq_printf(m, "W1: bpid \t\t\t%d\nW1: bp_ena \t\t\t%d\n\n", |
| cq_ctx->bpid, cq_ctx->bp_ena); |
| |
| seq_printf(m, "W2: update_time \t\t%d\nW2:avg_level \t\t\t%d\n", |
| cq_ctx->update_time, cq_ctx->avg_level); |
| seq_printf(m, "W2: head \t\t\t%d\nW2:tail \t\t\t%d\n\n", |
| cq_ctx->head, cq_ctx->tail); |
| |
| seq_printf(m, "W3: cq_err_int_ena \t\t%d\nW3:cq_err_int \t\t\t%d\n", |
| cq_ctx->cq_err_int_ena, cq_ctx->cq_err_int); |
| seq_printf(m, "W3: qsize \t\t\t%d\nW3:caching \t\t\t%d\n", |
| cq_ctx->qsize, cq_ctx->caching); |
| seq_printf(m, "W3: substream \t\t\t0x%03x\nW3: ena \t\t\t%d\n", |
| cq_ctx->substream, cq_ctx->ena); |
| seq_printf(m, "W3: drop_ena \t\t\t%d\nW3: drop \t\t\t%d\n", |
| cq_ctx->drop_ena, cq_ctx->drop); |
| seq_printf(m, "W3: bp \t\t\t\t%d\n\n", cq_ctx->bp); |
| } |
| |
| static int rvu_dbg_nix_queue_ctx_display(struct seq_file *filp, |
| void *unused, int ctype) |
| { |
| void (*print_nix_ctx)(struct seq_file *filp, |
| struct nix_aq_enq_rsp *rsp) = NULL; |
| struct nix_hw *nix_hw = filp->private; |
| struct rvu *rvu = nix_hw->rvu; |
| struct nix_aq_enq_req aq_req; |
| struct nix_aq_enq_rsp rsp; |
| char *ctype_string = NULL; |
| int qidx, rc, max_id = 0; |
| struct rvu_pfvf *pfvf; |
| int nixlf, id, all; |
| u16 pcifunc; |
| |
| switch (ctype) { |
| case NIX_AQ_CTYPE_CQ: |
| nixlf = rvu->rvu_dbg.nix_cq_ctx.lf; |
| id = rvu->rvu_dbg.nix_cq_ctx.id; |
| all = rvu->rvu_dbg.nix_cq_ctx.all; |
| break; |
| |
| case NIX_AQ_CTYPE_SQ: |
| nixlf = rvu->rvu_dbg.nix_sq_ctx.lf; |
| id = rvu->rvu_dbg.nix_sq_ctx.id; |
| all = rvu->rvu_dbg.nix_sq_ctx.all; |
| break; |
| |
| case NIX_AQ_CTYPE_RQ: |
| nixlf = rvu->rvu_dbg.nix_rq_ctx.lf; |
| id = rvu->rvu_dbg.nix_rq_ctx.id; |
| all = rvu->rvu_dbg.nix_rq_ctx.all; |
| break; |
| |
| default: |
| return -EINVAL; |
| } |
| |
| if (!rvu_dbg_is_valid_lf(rvu, nix_hw->blkaddr, nixlf, &pcifunc)) |
| return -EINVAL; |
| |
| pfvf = rvu_get_pfvf(rvu, pcifunc); |
| if (ctype == NIX_AQ_CTYPE_SQ && !pfvf->sq_ctx) { |
| seq_puts(filp, "SQ context is not initialized\n"); |
| return -EINVAL; |
| } else if (ctype == NIX_AQ_CTYPE_RQ && !pfvf->rq_ctx) { |
| seq_puts(filp, "RQ context is not initialized\n"); |
| return -EINVAL; |
| } else if (ctype == NIX_AQ_CTYPE_CQ && !pfvf->cq_ctx) { |
| seq_puts(filp, "CQ context is not initialized\n"); |
| return -EINVAL; |
| } |
| |
| if (ctype == NIX_AQ_CTYPE_SQ) { |
| max_id = pfvf->sq_ctx->qsize; |
| ctype_string = "sq"; |
| print_nix_ctx = print_nix_sq_ctx; |
| } else if (ctype == NIX_AQ_CTYPE_RQ) { |
| max_id = pfvf->rq_ctx->qsize; |
| ctype_string = "rq"; |
| print_nix_ctx = print_nix_rq_ctx; |
| } else if (ctype == NIX_AQ_CTYPE_CQ) { |
| max_id = pfvf->cq_ctx->qsize; |
| ctype_string = "cq"; |
| print_nix_ctx = print_nix_cq_ctx; |
| } |
| |
| memset(&aq_req, 0, sizeof(struct nix_aq_enq_req)); |
| aq_req.hdr.pcifunc = pcifunc; |
| aq_req.ctype = ctype; |
| aq_req.op = NIX_AQ_INSTOP_READ; |
| if (all) |
| id = 0; |
| else |
| max_id = id + 1; |
| for (qidx = id; qidx < max_id; qidx++) { |
| aq_req.qidx = qidx; |
| seq_printf(filp, "=====%s_ctx for nixlf:%d and qidx:%d is=====\n", |
| ctype_string, nixlf, aq_req.qidx); |
| rc = rvu_mbox_handler_nix_aq_enq(rvu, &aq_req, &rsp); |
| if (rc) { |
| seq_puts(filp, "Failed to read the context\n"); |
| return -EINVAL; |
| } |
| print_nix_ctx(filp, &rsp); |
| } |
| return 0; |
| } |
| |
| static int write_nix_queue_ctx(struct rvu *rvu, bool all, int nixlf, |
| int id, int ctype, char *ctype_string, |
| struct seq_file *m) |
| { |
| struct nix_hw *nix_hw = m->private; |
| struct rvu_pfvf *pfvf; |
| int max_id = 0; |
| u16 pcifunc; |
| |
| if (!rvu_dbg_is_valid_lf(rvu, nix_hw->blkaddr, nixlf, &pcifunc)) |
| return -EINVAL; |
| |
| pfvf = rvu_get_pfvf(rvu, pcifunc); |
| |
| if (ctype == NIX_AQ_CTYPE_SQ) { |
| if (!pfvf->sq_ctx) { |
| dev_warn(rvu->dev, "SQ context is not initialized\n"); |
| return -EINVAL; |
| } |
| max_id = pfvf->sq_ctx->qsize; |
| } else if (ctype == NIX_AQ_CTYPE_RQ) { |
| if (!pfvf->rq_ctx) { |
| dev_warn(rvu->dev, "RQ context is not initialized\n"); |
| return -EINVAL; |
| } |
| max_id = pfvf->rq_ctx->qsize; |
| } else if (ctype == NIX_AQ_CTYPE_CQ) { |
| if (!pfvf->cq_ctx) { |
| dev_warn(rvu->dev, "CQ context is not initialized\n"); |
| return -EINVAL; |
| } |
| max_id = pfvf->cq_ctx->qsize; |
| } |
| |
| if (id < 0 || id >= max_id) { |
| dev_warn(rvu->dev, "Invalid %s_ctx valid range 0-%d\n", |
| ctype_string, max_id - 1); |
| return -EINVAL; |
| } |
| switch (ctype) { |
| case NIX_AQ_CTYPE_CQ: |
| rvu->rvu_dbg.nix_cq_ctx.lf = nixlf; |
| rvu->rvu_dbg.nix_cq_ctx.id = id; |
| rvu->rvu_dbg.nix_cq_ctx.all = all; |
| break; |
| |
| case NIX_AQ_CTYPE_SQ: |
| rvu->rvu_dbg.nix_sq_ctx.lf = nixlf; |
| rvu->rvu_dbg.nix_sq_ctx.id = id; |
| rvu->rvu_dbg.nix_sq_ctx.all = all; |
| break; |
| |
| case NIX_AQ_CTYPE_RQ: |
| rvu->rvu_dbg.nix_rq_ctx.lf = nixlf; |
| rvu->rvu_dbg.nix_rq_ctx.id = id; |
| rvu->rvu_dbg.nix_rq_ctx.all = all; |
| break; |
| default: |
| return -EINVAL; |
| } |
| return 0; |
| } |
| |
| static ssize_t rvu_dbg_nix_queue_ctx_write(struct file *filp, |
| const char __user *buffer, |
| size_t count, loff_t *ppos, |
| int ctype) |
| { |
| struct seq_file *m = filp->private_data; |
| struct nix_hw *nix_hw = m->private; |
| struct rvu *rvu = nix_hw->rvu; |
| char *cmd_buf, *ctype_string; |
| int nixlf, id = 0, ret; |
| bool all = false; |
| |
| if ((*ppos != 0) || !count) |
| return -EINVAL; |
| |
| switch (ctype) { |
| case NIX_AQ_CTYPE_SQ: |
| ctype_string = "sq"; |
| break; |
| case NIX_AQ_CTYPE_RQ: |
| ctype_string = "rq"; |
| break; |
| case NIX_AQ_CTYPE_CQ: |
| ctype_string = "cq"; |
| break; |
| default: |
| return -EINVAL; |
| } |
| |
| cmd_buf = kzalloc(count + 1, GFP_KERNEL); |
| |
| if (!cmd_buf) |
| return count; |
| |
| ret = parse_cmd_buffer_ctx(cmd_buf, &count, buffer, |
| &nixlf, &id, &all); |
| if (ret < 0) { |
| dev_info(rvu->dev, |
| "Usage: echo <nixlf> [%s number/all] > %s_ctx\n", |
| ctype_string, ctype_string); |
| goto done; |
| } else { |
| ret = write_nix_queue_ctx(rvu, all, nixlf, id, ctype, |
| ctype_string, m); |
| } |
| done: |
| kfree(cmd_buf); |
| return ret ? ret : count; |
| } |
| |
| static ssize_t rvu_dbg_nix_sq_ctx_write(struct file *filp, |
| const char __user *buffer, |
| size_t count, loff_t *ppos) |
| { |
| return rvu_dbg_nix_queue_ctx_write(filp, buffer, count, ppos, |
| NIX_AQ_CTYPE_SQ); |
| } |
| |
| static int rvu_dbg_nix_sq_ctx_display(struct seq_file *filp, void *unused) |
| { |
| return rvu_dbg_nix_queue_ctx_display(filp, unused, NIX_AQ_CTYPE_SQ); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(nix_sq_ctx, nix_sq_ctx_display, nix_sq_ctx_write); |
| |
| static ssize_t rvu_dbg_nix_rq_ctx_write(struct file *filp, |
| const char __user *buffer, |
| size_t count, loff_t *ppos) |
| { |
| return rvu_dbg_nix_queue_ctx_write(filp, buffer, count, ppos, |
| NIX_AQ_CTYPE_RQ); |
| } |
| |
| static int rvu_dbg_nix_rq_ctx_display(struct seq_file *filp, void *unused) |
| { |
| return rvu_dbg_nix_queue_ctx_display(filp, unused, NIX_AQ_CTYPE_RQ); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(nix_rq_ctx, nix_rq_ctx_display, nix_rq_ctx_write); |
| |
| static ssize_t rvu_dbg_nix_cq_ctx_write(struct file *filp, |
| const char __user *buffer, |
| size_t count, loff_t *ppos) |
| { |
| return rvu_dbg_nix_queue_ctx_write(filp, buffer, count, ppos, |
| NIX_AQ_CTYPE_CQ); |
| } |
| |
| static int rvu_dbg_nix_cq_ctx_display(struct seq_file *filp, void *unused) |
| { |
| return rvu_dbg_nix_queue_ctx_display(filp, unused, NIX_AQ_CTYPE_CQ); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(nix_cq_ctx, nix_cq_ctx_display, nix_cq_ctx_write); |
| |
| static void print_nix_qctx_qsize(struct seq_file *filp, int qsize, |
| unsigned long *bmap, char *qtype) |
| { |
| char *buf; |
| |
| buf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
| if (!buf) |
| return; |
| |
| bitmap_print_to_pagebuf(false, buf, bmap, qsize); |
| seq_printf(filp, "%s context count : %d\n", qtype, qsize); |
| seq_printf(filp, "%s context ena/dis bitmap : %s\n", |
| qtype, buf); |
| kfree(buf); |
| } |
| |
| static void print_nix_qsize(struct seq_file *filp, struct rvu_pfvf *pfvf) |
| { |
| if (!pfvf->cq_ctx) |
| seq_puts(filp, "cq context is not initialized\n"); |
| else |
| print_nix_qctx_qsize(filp, pfvf->cq_ctx->qsize, pfvf->cq_bmap, |
| "cq"); |
| |
| if (!pfvf->rq_ctx) |
| seq_puts(filp, "rq context is not initialized\n"); |
| else |
| print_nix_qctx_qsize(filp, pfvf->rq_ctx->qsize, pfvf->rq_bmap, |
| "rq"); |
| |
| if (!pfvf->sq_ctx) |
| seq_puts(filp, "sq context is not initialized\n"); |
| else |
| print_nix_qctx_qsize(filp, pfvf->sq_ctx->qsize, pfvf->sq_bmap, |
| "sq"); |
| } |
| |
| static ssize_t rvu_dbg_nix_qsize_write(struct file *filp, |
| const char __user *buffer, |
| size_t count, loff_t *ppos) |
| { |
| return rvu_dbg_qsize_write(filp, buffer, count, ppos, |
| BLKTYPE_NIX); |
| } |
| |
| static int rvu_dbg_nix_qsize_display(struct seq_file *filp, void *unused) |
| { |
| return rvu_dbg_qsize_display(filp, unused, BLKTYPE_NIX); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(nix_qsize, nix_qsize_display, nix_qsize_write); |
| |
| static void print_band_prof_ctx(struct seq_file *m, |
| struct nix_bandprof_s *prof) |
| { |
| char *str; |
| |
| switch (prof->pc_mode) { |
| case NIX_RX_PC_MODE_VLAN: |
| str = "VLAN"; |
| break; |
| case NIX_RX_PC_MODE_DSCP: |
| str = "DSCP"; |
| break; |
| case NIX_RX_PC_MODE_GEN: |
| str = "Generic"; |
| break; |
| case NIX_RX_PC_MODE_RSVD: |
| str = "Reserved"; |
| break; |
| } |
| seq_printf(m, "W0: pc_mode\t\t%s\n", str); |
| str = (prof->icolor == 3) ? "Color blind" : |
| (prof->icolor == 0) ? "Green" : |
| (prof->icolor == 1) ? "Yellow" : "Red"; |
| seq_printf(m, "W0: icolor\t\t%s\n", str); |
| seq_printf(m, "W0: tnl_ena\t\t%d\n", prof->tnl_ena); |
| seq_printf(m, "W0: peir_exponent\t%d\n", prof->peir_exponent); |
| seq_printf(m, "W0: pebs_exponent\t%d\n", prof->pebs_exponent); |
| seq_printf(m, "W0: cir_exponent\t%d\n", prof->cir_exponent); |
| seq_printf(m, "W0: cbs_exponent\t%d\n", prof->cbs_exponent); |
| seq_printf(m, "W0: peir_mantissa\t%d\n", prof->peir_mantissa); |
| seq_printf(m, "W0: pebs_mantissa\t%d\n", prof->pebs_mantissa); |
| seq_printf(m, "W0: cir_mantissa\t%d\n", prof->cir_mantissa); |
| |
| seq_printf(m, "W1: cbs_mantissa\t%d\n", prof->cbs_mantissa); |
| str = (prof->lmode == 0) ? "byte" : "packet"; |
| seq_printf(m, "W1: lmode\t\t%s\n", str); |
| seq_printf(m, "W1: l_select\t\t%d\n", prof->l_sellect); |
| seq_printf(m, "W1: rdiv\t\t%d\n", prof->rdiv); |
| seq_printf(m, "W1: adjust_exponent\t%d\n", prof->adjust_exponent); |
| seq_printf(m, "W1: adjust_mantissa\t%d\n", prof->adjust_mantissa); |
| str = (prof->gc_action == 0) ? "PASS" : |
| (prof->gc_action == 1) ? "DROP" : "RED"; |
| seq_printf(m, "W1: gc_action\t\t%s\n", str); |
| str = (prof->yc_action == 0) ? "PASS" : |
| (prof->yc_action == 1) ? "DROP" : "RED"; |
| seq_printf(m, "W1: yc_action\t\t%s\n", str); |
| str = (prof->rc_action == 0) ? "PASS" : |
| (prof->rc_action == 1) ? "DROP" : "RED"; |
| seq_printf(m, "W1: rc_action\t\t%s\n", str); |
| seq_printf(m, "W1: meter_algo\t\t%d\n", prof->meter_algo); |
| seq_printf(m, "W1: band_prof_id\t%d\n", prof->band_prof_id); |
| seq_printf(m, "W1: hl_en\t\t%d\n", prof->hl_en); |
| |
| seq_printf(m, "W2: ts\t\t\t%lld\n", (u64)prof->ts); |
| seq_printf(m, "W3: pe_accum\t\t%d\n", prof->pe_accum); |
| seq_printf(m, "W3: c_accum\t\t%d\n", prof->c_accum); |
| seq_printf(m, "W4: green_pkt_pass\t%lld\n", |
| (u64)prof->green_pkt_pass); |
| seq_printf(m, "W5: yellow_pkt_pass\t%lld\n", |
| (u64)prof->yellow_pkt_pass); |
| seq_printf(m, "W6: red_pkt_pass\t%lld\n", (u64)prof->red_pkt_pass); |
| seq_printf(m, "W7: green_octs_pass\t%lld\n", |
| (u64)prof->green_octs_pass); |
| seq_printf(m, "W8: yellow_octs_pass\t%lld\n", |
| (u64)prof->yellow_octs_pass); |
| seq_printf(m, "W9: red_octs_pass\t%lld\n", (u64)prof->red_octs_pass); |
| seq_printf(m, "W10: green_pkt_drop\t%lld\n", |
| (u64)prof->green_pkt_drop); |
| seq_printf(m, "W11: yellow_pkt_drop\t%lld\n", |
| (u64)prof->yellow_pkt_drop); |
| seq_printf(m, "W12: red_pkt_drop\t%lld\n", (u64)prof->red_pkt_drop); |
| seq_printf(m, "W13: green_octs_drop\t%lld\n", |
| (u64)prof->green_octs_drop); |
| seq_printf(m, "W14: yellow_octs_drop\t%lld\n", |
| (u64)prof->yellow_octs_drop); |
| seq_printf(m, "W15: red_octs_drop\t%lld\n", (u64)prof->red_octs_drop); |
| seq_puts(m, "==============================\n"); |
| } |
| |
| static int rvu_dbg_nix_band_prof_ctx_display(struct seq_file *m, void *unused) |
| { |
| struct nix_hw *nix_hw = m->private; |
| struct nix_cn10k_aq_enq_req aq_req; |
| struct nix_cn10k_aq_enq_rsp aq_rsp; |
| struct rvu *rvu = nix_hw->rvu; |
| struct nix_ipolicer *ipolicer; |
| int layer, prof_idx, idx, rc; |
| u16 pcifunc; |
| char *str; |
| |
| /* Ingress policers do not exist on all platforms */ |
| if (!nix_hw->ipolicer) |
| return 0; |
| |
| for (layer = 0; layer < BAND_PROF_NUM_LAYERS; layer++) { |
| if (layer == BAND_PROF_INVAL_LAYER) |
| continue; |
| str = (layer == BAND_PROF_LEAF_LAYER) ? "Leaf" : |
| (layer == BAND_PROF_MID_LAYER) ? "Mid" : "Top"; |
| |
| seq_printf(m, "\n%s bandwidth profiles\n", str); |
| seq_puts(m, "=======================\n"); |
| |
| ipolicer = &nix_hw->ipolicer[layer]; |
| |
| for (idx = 0; idx < ipolicer->band_prof.max; idx++) { |
| if (is_rsrc_free(&ipolicer->band_prof, idx)) |
| continue; |
| |
| prof_idx = (idx & 0x3FFF) | (layer << 14); |
| rc = nix_aq_context_read(rvu, nix_hw, &aq_req, &aq_rsp, |
| 0x00, NIX_AQ_CTYPE_BANDPROF, |
| prof_idx); |
| if (rc) { |
| dev_err(rvu->dev, |
| "%s: Failed to fetch context of %s profile %d, err %d\n", |
| __func__, str, idx, rc); |
| return 0; |
| } |
| seq_printf(m, "\n%s bandwidth profile:: %d\n", str, idx); |
| pcifunc = ipolicer->pfvf_map[idx]; |
| if (!(pcifunc & RVU_PFVF_FUNC_MASK)) |
| seq_printf(m, "Allocated to :: PF %d\n", |
| rvu_get_pf(pcifunc)); |
| else |
| seq_printf(m, "Allocated to :: PF %d VF %d\n", |
| rvu_get_pf(pcifunc), |
| (pcifunc & RVU_PFVF_FUNC_MASK) - 1); |
| print_band_prof_ctx(m, &aq_rsp.prof); |
| } |
| } |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(nix_band_prof_ctx, nix_band_prof_ctx_display, NULL); |
| |
| static int rvu_dbg_nix_band_prof_rsrc_display(struct seq_file *m, void *unused) |
| { |
| struct nix_hw *nix_hw = m->private; |
| struct nix_ipolicer *ipolicer; |
| int layer; |
| char *str; |
| |
| /* Ingress policers do not exist on all platforms */ |
| if (!nix_hw->ipolicer) |
| return 0; |
| |
| seq_puts(m, "\nBandwidth profile resource free count\n"); |
| seq_puts(m, "=====================================\n"); |
| for (layer = 0; layer < BAND_PROF_NUM_LAYERS; layer++) { |
| if (layer == BAND_PROF_INVAL_LAYER) |
| continue; |
| str = (layer == BAND_PROF_LEAF_LAYER) ? "Leaf" : |
| (layer == BAND_PROF_MID_LAYER) ? "Mid " : "Top "; |
| |
| ipolicer = &nix_hw->ipolicer[layer]; |
| seq_printf(m, "%s :: Max: %4d Free: %4d\n", str, |
| ipolicer->band_prof.max, |
| rvu_rsrc_free_count(&ipolicer->band_prof)); |
| } |
| seq_puts(m, "=====================================\n"); |
| |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(nix_band_prof_rsrc, nix_band_prof_rsrc_display, NULL); |
| |
| static void rvu_dbg_nix_init(struct rvu *rvu, int blkaddr) |
| { |
| struct nix_hw *nix_hw; |
| |
| if (!is_block_implemented(rvu->hw, blkaddr)) |
| return; |
| |
| if (blkaddr == BLKADDR_NIX0) { |
| rvu->rvu_dbg.nix = debugfs_create_dir("nix", rvu->rvu_dbg.root); |
| nix_hw = &rvu->hw->nix[0]; |
| } else { |
| rvu->rvu_dbg.nix = debugfs_create_dir("nix1", |
| rvu->rvu_dbg.root); |
| nix_hw = &rvu->hw->nix[1]; |
| } |
| |
| debugfs_create_file("sq_ctx", 0600, rvu->rvu_dbg.nix, nix_hw, |
| &rvu_dbg_nix_sq_ctx_fops); |
| debugfs_create_file("rq_ctx", 0600, rvu->rvu_dbg.nix, nix_hw, |
| &rvu_dbg_nix_rq_ctx_fops); |
| debugfs_create_file("cq_ctx", 0600, rvu->rvu_dbg.nix, nix_hw, |
| &rvu_dbg_nix_cq_ctx_fops); |
| debugfs_create_file("ndc_tx_cache", 0600, rvu->rvu_dbg.nix, nix_hw, |
| &rvu_dbg_nix_ndc_tx_cache_fops); |
| debugfs_create_file("ndc_rx_cache", 0600, rvu->rvu_dbg.nix, nix_hw, |
| &rvu_dbg_nix_ndc_rx_cache_fops); |
| debugfs_create_file("ndc_tx_hits_miss", 0600, rvu->rvu_dbg.nix, nix_hw, |
| &rvu_dbg_nix_ndc_tx_hits_miss_fops); |
| debugfs_create_file("ndc_rx_hits_miss", 0600, rvu->rvu_dbg.nix, nix_hw, |
| &rvu_dbg_nix_ndc_rx_hits_miss_fops); |
| debugfs_create_file("qsize", 0600, rvu->rvu_dbg.nix, rvu, |
| &rvu_dbg_nix_qsize_fops); |
| debugfs_create_file("ingress_policer_ctx", 0600, rvu->rvu_dbg.nix, nix_hw, |
| &rvu_dbg_nix_band_prof_ctx_fops); |
| debugfs_create_file("ingress_policer_rsrc", 0600, rvu->rvu_dbg.nix, nix_hw, |
| &rvu_dbg_nix_band_prof_rsrc_fops); |
| } |
| |
| static void rvu_dbg_npa_init(struct rvu *rvu) |
| { |
| rvu->rvu_dbg.npa = debugfs_create_dir("npa", rvu->rvu_dbg.root); |
| |
| debugfs_create_file("qsize", 0600, rvu->rvu_dbg.npa, rvu, |
| &rvu_dbg_npa_qsize_fops); |
| debugfs_create_file("aura_ctx", 0600, rvu->rvu_dbg.npa, rvu, |
| &rvu_dbg_npa_aura_ctx_fops); |
| debugfs_create_file("pool_ctx", 0600, rvu->rvu_dbg.npa, rvu, |
| &rvu_dbg_npa_pool_ctx_fops); |
| debugfs_create_file("ndc_cache", 0600, rvu->rvu_dbg.npa, rvu, |
| &rvu_dbg_npa_ndc_cache_fops); |
| debugfs_create_file("ndc_hits_miss", 0600, rvu->rvu_dbg.npa, rvu, |
| &rvu_dbg_npa_ndc_hits_miss_fops); |
| } |
| |
| #define PRINT_CGX_CUML_NIXRX_STATUS(idx, name) \ |
| ({ \ |
| u64 cnt; \ |
| err = rvu_cgx_nix_cuml_stats(rvu, cgxd, lmac_id, (idx), \ |
| NIX_STATS_RX, &(cnt)); \ |
| if (!err) \ |
| seq_printf(s, "%s: %llu\n", name, cnt); \ |
| cnt; \ |
| }) |
| |
| #define PRINT_CGX_CUML_NIXTX_STATUS(idx, name) \ |
| ({ \ |
| u64 cnt; \ |
| err = rvu_cgx_nix_cuml_stats(rvu, cgxd, lmac_id, (idx), \ |
| NIX_STATS_TX, &(cnt)); \ |
| if (!err) \ |
| seq_printf(s, "%s: %llu\n", name, cnt); \ |
| cnt; \ |
| }) |
| |
| static int cgx_print_stats(struct seq_file *s, int lmac_id) |
| { |
| struct cgx_link_user_info linfo; |
| struct mac_ops *mac_ops; |
| void *cgxd = s->private; |
| u64 ucast, mcast, bcast; |
| int stat = 0, err = 0; |
| u64 tx_stat, rx_stat; |
| struct rvu *rvu; |
| |
| rvu = pci_get_drvdata(pci_get_device(PCI_VENDOR_ID_CAVIUM, |
| PCI_DEVID_OCTEONTX2_RVU_AF, NULL)); |
| if (!rvu) |
| return -ENODEV; |
| |
| mac_ops = get_mac_ops(cgxd); |
| /* There can be no CGX devices at all */ |
| if (!mac_ops) |
| return 0; |
| |
| /* Link status */ |
| seq_puts(s, "\n=======Link Status======\n\n"); |
| err = cgx_get_link_info(cgxd, lmac_id, &linfo); |
| if (err) |
| seq_puts(s, "Failed to read link status\n"); |
| seq_printf(s, "\nLink is %s %d Mbps\n\n", |
| linfo.link_up ? "UP" : "DOWN", linfo.speed); |
| |
| /* Rx stats */ |
| seq_printf(s, "\n=======NIX RX_STATS(%s port level)======\n\n", |
| mac_ops->name); |
| ucast = PRINT_CGX_CUML_NIXRX_STATUS(RX_UCAST, "rx_ucast_frames"); |
| if (err) |
| return err; |
| mcast = PRINT_CGX_CUML_NIXRX_STATUS(RX_MCAST, "rx_mcast_frames"); |
| if (err) |
| return err; |
| bcast = PRINT_CGX_CUML_NIXRX_STATUS(RX_BCAST, "rx_bcast_frames"); |
| if (err) |
| return err; |
| seq_printf(s, "rx_frames: %llu\n", ucast + mcast + bcast); |
| PRINT_CGX_CUML_NIXRX_STATUS(RX_OCTS, "rx_bytes"); |
| if (err) |
| return err; |
| PRINT_CGX_CUML_NIXRX_STATUS(RX_DROP, "rx_drops"); |
| if (err) |
| return err; |
| PRINT_CGX_CUML_NIXRX_STATUS(RX_ERR, "rx_errors"); |
| if (err) |
| return err; |
| |
| /* Tx stats */ |
| seq_printf(s, "\n=======NIX TX_STATS(%s port level)======\n\n", |
| mac_ops->name); |
| ucast = PRINT_CGX_CUML_NIXTX_STATUS(TX_UCAST, "tx_ucast_frames"); |
| if (err) |
| return err; |
| mcast = PRINT_CGX_CUML_NIXTX_STATUS(TX_MCAST, "tx_mcast_frames"); |
| if (err) |
| return err; |
| bcast = PRINT_CGX_CUML_NIXTX_STATUS(TX_BCAST, "tx_bcast_frames"); |
| if (err) |
| return err; |
| seq_printf(s, "tx_frames: %llu\n", ucast + mcast + bcast); |
| PRINT_CGX_CUML_NIXTX_STATUS(TX_OCTS, "tx_bytes"); |
| if (err) |
| return err; |
| PRINT_CGX_CUML_NIXTX_STATUS(TX_DROP, "tx_drops"); |
| if (err) |
| return err; |
| |
| /* Rx stats */ |
| seq_printf(s, "\n=======%s RX_STATS======\n\n", mac_ops->name); |
| while (stat < mac_ops->rx_stats_cnt) { |
| err = mac_ops->mac_get_rx_stats(cgxd, lmac_id, stat, &rx_stat); |
| if (err) |
| return err; |
| if (is_rvu_otx2(rvu)) |
| seq_printf(s, "%s: %llu\n", cgx_rx_stats_fields[stat], |
| rx_stat); |
| else |
| seq_printf(s, "%s: %llu\n", rpm_rx_stats_fields[stat], |
| rx_stat); |
| stat++; |
| } |
| |
| /* Tx stats */ |
| stat = 0; |
| seq_printf(s, "\n=======%s TX_STATS======\n\n", mac_ops->name); |
| while (stat < mac_ops->tx_stats_cnt) { |
| err = mac_ops->mac_get_tx_stats(cgxd, lmac_id, stat, &tx_stat); |
| if (err) |
| return err; |
| |
| if (is_rvu_otx2(rvu)) |
| seq_printf(s, "%s: %llu\n", cgx_tx_stats_fields[stat], |
| tx_stat); |
| else |
| seq_printf(s, "%s: %llu\n", rpm_tx_stats_fields[stat], |
| tx_stat); |
| stat++; |
| } |
| |
| return err; |
| } |
| |
| static int rvu_dbg_derive_lmacid(struct seq_file *filp, int *lmac_id) |
| { |
| struct dentry *current_dir; |
| char *buf; |
| |
| current_dir = filp->file->f_path.dentry->d_parent; |
| buf = strrchr(current_dir->d_name.name, 'c'); |
| if (!buf) |
| return -EINVAL; |
| |
| return kstrtoint(buf + 1, 10, lmac_id); |
| } |
| |
| static int rvu_dbg_cgx_stat_display(struct seq_file *filp, void *unused) |
| { |
| int lmac_id, err; |
| |
| err = rvu_dbg_derive_lmacid(filp, &lmac_id); |
| if (!err) |
| return cgx_print_stats(filp, lmac_id); |
| |
| return err; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(cgx_stat, cgx_stat_display, NULL); |
| |
| static int cgx_print_dmac_flt(struct seq_file *s, int lmac_id) |
| { |
| struct pci_dev *pdev = NULL; |
| void *cgxd = s->private; |
| char *bcast, *mcast; |
| u16 index, domain; |
| u8 dmac[ETH_ALEN]; |
| struct rvu *rvu; |
| u64 cfg, mac; |
| int pf; |
| |
| rvu = pci_get_drvdata(pci_get_device(PCI_VENDOR_ID_CAVIUM, |
| PCI_DEVID_OCTEONTX2_RVU_AF, NULL)); |
| if (!rvu) |
| return -ENODEV; |
| |
| pf = cgxlmac_to_pf(rvu, cgx_get_cgxid(cgxd), lmac_id); |
| domain = 2; |
| |
| pdev = pci_get_domain_bus_and_slot(domain, pf + 1, 0); |
| if (!pdev) |
| return 0; |
| |
| cfg = cgx_read_dmac_ctrl(cgxd, lmac_id); |
| bcast = cfg & CGX_DMAC_BCAST_MODE ? "ACCEPT" : "REJECT"; |
| mcast = cfg & CGX_DMAC_MCAST_MODE ? "ACCEPT" : "REJECT"; |
| |
| seq_puts(s, |
| "PCI dev RVUPF BROADCAST MULTICAST FILTER-MODE\n"); |
| seq_printf(s, "%s PF%d %9s %9s", |
| dev_name(&pdev->dev), pf, bcast, mcast); |
| if (cfg & CGX_DMAC_CAM_ACCEPT) |
| seq_printf(s, "%12s\n\n", "UNICAST"); |
| else |
| seq_printf(s, "%16s\n\n", "PROMISCUOUS"); |
| |
| seq_puts(s, "\nDMAC-INDEX ADDRESS\n"); |
| |
| for (index = 0 ; index < 32 ; index++) { |
| cfg = cgx_read_dmac_entry(cgxd, index); |
| /* Display enabled dmac entries associated with current lmac */ |
| if (lmac_id == FIELD_GET(CGX_DMAC_CAM_ENTRY_LMACID, cfg) && |
| FIELD_GET(CGX_DMAC_CAM_ADDR_ENABLE, cfg)) { |
| mac = FIELD_GET(CGX_RX_DMAC_ADR_MASK, cfg); |
| u64_to_ether_addr(mac, dmac); |
| seq_printf(s, "%7d %pM\n", index, dmac); |
| } |
| } |
| |
| pci_dev_put(pdev); |
| return 0; |
| } |
| |
| static int rvu_dbg_cgx_dmac_flt_display(struct seq_file *filp, void *unused) |
| { |
| int err, lmac_id; |
| |
| err = rvu_dbg_derive_lmacid(filp, &lmac_id); |
| if (!err) |
| return cgx_print_dmac_flt(filp, lmac_id); |
| |
| return err; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(cgx_dmac_flt, cgx_dmac_flt_display, NULL); |
| |
| static void rvu_dbg_cgx_init(struct rvu *rvu) |
| { |
| struct mac_ops *mac_ops; |
| unsigned long lmac_bmap; |
| int i, lmac_id; |
| char dname[20]; |
| void *cgx; |
| |
| if (!cgx_get_cgxcnt_max()) |
| return; |
| |
| mac_ops = get_mac_ops(rvu_first_cgx_pdata(rvu)); |
| if (!mac_ops) |
| return; |
| |
| rvu->rvu_dbg.cgx_root = debugfs_create_dir(mac_ops->name, |
| rvu->rvu_dbg.root); |
| |
| for (i = 0; i < cgx_get_cgxcnt_max(); i++) { |
| cgx = rvu_cgx_pdata(i, rvu); |
| if (!cgx) |
| continue; |
| lmac_bmap = cgx_get_lmac_bmap(cgx); |
| /* cgx debugfs dir */ |
| sprintf(dname, "%s%d", mac_ops->name, i); |
| rvu->rvu_dbg.cgx = debugfs_create_dir(dname, |
| rvu->rvu_dbg.cgx_root); |
| |
| for_each_set_bit(lmac_id, &lmac_bmap, rvu->hw->lmac_per_cgx) { |
| /* lmac debugfs dir */ |
| sprintf(dname, "lmac%d", lmac_id); |
| rvu->rvu_dbg.lmac = |
| debugfs_create_dir(dname, rvu->rvu_dbg.cgx); |
| |
| debugfs_create_file("stats", 0600, rvu->rvu_dbg.lmac, |
| cgx, &rvu_dbg_cgx_stat_fops); |
| debugfs_create_file("mac_filter", 0600, |
| rvu->rvu_dbg.lmac, cgx, |
| &rvu_dbg_cgx_dmac_flt_fops); |
| } |
| } |
| } |
| |
| /* NPC debugfs APIs */ |
| static void rvu_print_npc_mcam_info(struct seq_file *s, |
| u16 pcifunc, int blkaddr) |
| { |
| struct rvu *rvu = s->private; |
| int entry_acnt, entry_ecnt; |
| int cntr_acnt, cntr_ecnt; |
| |
| rvu_npc_get_mcam_entry_alloc_info(rvu, pcifunc, blkaddr, |
| &entry_acnt, &entry_ecnt); |
| rvu_npc_get_mcam_counter_alloc_info(rvu, pcifunc, blkaddr, |
| &cntr_acnt, &cntr_ecnt); |
| if (!entry_acnt && !cntr_acnt) |
| return; |
| |
| if (!(pcifunc & RVU_PFVF_FUNC_MASK)) |
| seq_printf(s, "\n\t\t Device \t\t: PF%d\n", |
| rvu_get_pf(pcifunc)); |
| else |
| seq_printf(s, "\n\t\t Device \t\t: PF%d VF%d\n", |
| rvu_get_pf(pcifunc), |
| (pcifunc & RVU_PFVF_FUNC_MASK) - 1); |
| |
| if (entry_acnt) { |
| seq_printf(s, "\t\t Entries allocated \t: %d\n", entry_acnt); |
| seq_printf(s, "\t\t Entries enabled \t: %d\n", entry_ecnt); |
| } |
| if (cntr_acnt) { |
| seq_printf(s, "\t\t Counters allocated \t: %d\n", cntr_acnt); |
| seq_printf(s, "\t\t Counters enabled \t: %d\n", cntr_ecnt); |
| } |
| } |
| |
| static int rvu_dbg_npc_mcam_info_display(struct seq_file *filp, void *unsued) |
| { |
| struct rvu *rvu = filp->private; |
| int pf, vf, numvfs, blkaddr; |
| struct npc_mcam *mcam; |
| u16 pcifunc, counters; |
| u64 cfg; |
| |
| blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); |
| if (blkaddr < 0) |
| return -ENODEV; |
| |
| mcam = &rvu->hw->mcam; |
| counters = rvu->hw->npc_counters; |
| |
| seq_puts(filp, "\nNPC MCAM info:\n"); |
| /* MCAM keywidth on receive and transmit sides */ |
| cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_RX)); |
| cfg = (cfg >> 32) & 0x07; |
| seq_printf(filp, "\t\t RX keywidth \t: %s\n", (cfg == NPC_MCAM_KEY_X1) ? |
| "112bits" : ((cfg == NPC_MCAM_KEY_X2) ? |
| "224bits" : "448bits")); |
| cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_TX)); |
| cfg = (cfg >> 32) & 0x07; |
| seq_printf(filp, "\t\t TX keywidth \t: %s\n", (cfg == NPC_MCAM_KEY_X1) ? |
| "112bits" : ((cfg == NPC_MCAM_KEY_X2) ? |
| "224bits" : "448bits")); |
| |
| mutex_lock(&mcam->lock); |
| /* MCAM entries */ |
| seq_printf(filp, "\n\t\t MCAM entries \t: %d\n", mcam->total_entries); |
| seq_printf(filp, "\t\t Reserved \t: %d\n", |
| mcam->total_entries - mcam->bmap_entries); |
| seq_printf(filp, "\t\t Available \t: %d\n", mcam->bmap_fcnt); |
| |
| /* MCAM counters */ |
| seq_printf(filp, "\n\t\t MCAM counters \t: %d\n", counters); |
| seq_printf(filp, "\t\t Reserved \t: %d\n", |
| counters - mcam->counters.max); |
| seq_printf(filp, "\t\t Available \t: %d\n", |
| rvu_rsrc_free_count(&mcam->counters)); |
| |
| if (mcam->bmap_entries == mcam->bmap_fcnt) { |
| mutex_unlock(&mcam->lock); |
| return 0; |
| } |
| |
| seq_puts(filp, "\n\t\t Current allocation\n"); |
| seq_puts(filp, "\t\t====================\n"); |
| for (pf = 0; pf < rvu->hw->total_pfs; pf++) { |
| pcifunc = (pf << RVU_PFVF_PF_SHIFT); |
| rvu_print_npc_mcam_info(filp, pcifunc, blkaddr); |
| |
| cfg = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf)); |
| numvfs = (cfg >> 12) & 0xFF; |
| for (vf = 0; vf < numvfs; vf++) { |
| pcifunc = (pf << RVU_PFVF_PF_SHIFT) | (vf + 1); |
| rvu_print_npc_mcam_info(filp, pcifunc, blkaddr); |
| } |
| } |
| |
| mutex_unlock(&mcam->lock); |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(npc_mcam_info, npc_mcam_info_display, NULL); |
| |
| static int rvu_dbg_npc_rx_miss_stats_display(struct seq_file *filp, |
| void *unused) |
| { |
| struct rvu *rvu = filp->private; |
| struct npc_mcam *mcam; |
| int blkaddr; |
| |
| blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); |
| if (blkaddr < 0) |
| return -ENODEV; |
| |
| mcam = &rvu->hw->mcam; |
| |
| seq_puts(filp, "\nNPC MCAM RX miss action stats\n"); |
| seq_printf(filp, "\t\tStat %d: \t%lld\n", mcam->rx_miss_act_cntr, |
| rvu_read64(rvu, blkaddr, |
| NPC_AF_MATCH_STATX(mcam->rx_miss_act_cntr))); |
| |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(npc_rx_miss_act, npc_rx_miss_stats_display, NULL); |
| |
| static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s, |
| struct rvu_npc_mcam_rule *rule) |
| { |
| u8 bit; |
| |
| for_each_set_bit(bit, (unsigned long *)&rule->features, 64) { |
| seq_printf(s, "\t%s ", npc_get_field_name(bit)); |
| switch (bit) { |
| case NPC_LXMB: |
| if (rule->lxmb == 1) |
| seq_puts(s, "\tL2M nibble is set\n"); |
| else |
| seq_puts(s, "\tL2B nibble is set\n"); |
| break; |
| case NPC_DMAC: |
| seq_printf(s, "%pM ", rule->packet.dmac); |
| seq_printf(s, "mask %pM\n", rule->mask.dmac); |
| break; |
| case NPC_SMAC: |
| seq_printf(s, "%pM ", rule->packet.smac); |
| seq_printf(s, "mask %pM\n", rule->mask.smac); |
| break; |
| case NPC_ETYPE: |
| seq_printf(s, "0x%x ", ntohs(rule->packet.etype)); |
| seq_printf(s, "mask 0x%x\n", ntohs(rule->mask.etype)); |
| break; |
| case NPC_OUTER_VID: |
| seq_printf(s, "0x%x ", ntohs(rule->packet.vlan_tci)); |
| seq_printf(s, "mask 0x%x\n", |
| ntohs(rule->mask.vlan_tci)); |
| break; |
| case NPC_TOS: |
| seq_printf(s, "%d ", rule->packet.tos); |
| seq_printf(s, "mask 0x%x\n", rule->mask.tos); |
| break; |
| case NPC_SIP_IPV4: |
| seq_printf(s, "%pI4 ", &rule->packet.ip4src); |
| seq_printf(s, "mask %pI4\n", &rule->mask.ip4src); |
| break; |
| case NPC_DIP_IPV4: |
| seq_printf(s, "%pI4 ", &rule->packet.ip4dst); |
| seq_printf(s, "mask %pI4\n", &rule->mask.ip4dst); |
| break; |
| case NPC_SIP_IPV6: |
| seq_printf(s, "%pI6 ", rule->packet.ip6src); |
| seq_printf(s, "mask %pI6\n", rule->mask.ip6src); |
| break; |
| case NPC_DIP_IPV6: |
| seq_printf(s, "%pI6 ", rule->packet.ip6dst); |
| seq_printf(s, "mask %pI6\n", rule->mask.ip6dst); |
| break; |
| case NPC_IPFRAG_IPV6: |
| seq_printf(s, "0x%x ", rule->packet.next_header); |
| seq_printf(s, "mask 0x%x\n", rule->mask.next_header); |
| break; |
| case NPC_IPFRAG_IPV4: |
| seq_printf(s, "0x%x ", rule->packet.ip_flag); |
| seq_printf(s, "mask 0x%x\n", rule->mask.ip_flag); |
| break; |
| case NPC_SPORT_TCP: |
| case NPC_SPORT_UDP: |
| case NPC_SPORT_SCTP: |
| seq_printf(s, "%d ", ntohs(rule->packet.sport)); |
| seq_printf(s, "mask 0x%x\n", ntohs(rule->mask.sport)); |
| break; |
| case NPC_DPORT_TCP: |
| case NPC_DPORT_UDP: |
| case NPC_DPORT_SCTP: |
| seq_printf(s, "%d ", ntohs(rule->packet.dport)); |
| seq_printf(s, "mask 0x%x\n", ntohs(rule->mask.dport)); |
| break; |
| default: |
| seq_puts(s, "\n"); |
| break; |
| } |
| } |
| } |
| |
| static void rvu_dbg_npc_mcam_show_action(struct seq_file *s, |
| struct rvu_npc_mcam_rule *rule) |
| { |
| if (is_npc_intf_tx(rule->intf)) { |
| switch (rule->tx_action.op) { |
| case NIX_TX_ACTIONOP_DROP: |
| seq_puts(s, "\taction: Drop\n"); |
| break; |
| case NIX_TX_ACTIONOP_UCAST_DEFAULT: |
| seq_puts(s, "\taction: Unicast to default channel\n"); |
| break; |
| case NIX_TX_ACTIONOP_UCAST_CHAN: |
| seq_printf(s, "\taction: Unicast to channel %d\n", |
| rule->tx_action.index); |
| break; |
| case NIX_TX_ACTIONOP_MCAST: |
| seq_puts(s, "\taction: Multicast\n"); |
| break; |
| case NIX_TX_ACTIONOP_DROP_VIOL: |
| seq_puts(s, "\taction: Lockdown Violation Drop\n"); |
| break; |
| default: |
| break; |
| } |
| } else { |
| switch (rule->rx_action.op) { |
| case NIX_RX_ACTIONOP_DROP: |
| seq_puts(s, "\taction: Drop\n"); |
| break; |
| case NIX_RX_ACTIONOP_UCAST: |
| seq_printf(s, "\taction: Direct to queue %d\n", |
| rule->rx_action.index); |
| break; |
| case NIX_RX_ACTIONOP_RSS: |
| seq_puts(s, "\taction: RSS\n"); |
| break; |
| case NIX_RX_ACTIONOP_UCAST_IPSEC: |
| seq_puts(s, "\taction: Unicast ipsec\n"); |
| break; |
| case NIX_RX_ACTIONOP_MCAST: |
| seq_puts(s, "\taction: Multicast\n"); |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| static const char *rvu_dbg_get_intf_name(int intf) |
| { |
| switch (intf) { |
| case NIX_INTFX_RX(0): |
| return "NIX0_RX"; |
| case NIX_INTFX_RX(1): |
| return "NIX1_RX"; |
| case NIX_INTFX_TX(0): |
| return "NIX0_TX"; |
| case NIX_INTFX_TX(1): |
| return "NIX1_TX"; |
| default: |
| break; |
| } |
| |
| return "unknown"; |
| } |
| |
| static int rvu_dbg_npc_mcam_show_rules(struct seq_file *s, void *unused) |
| { |
| struct rvu_npc_mcam_rule *iter; |
| struct rvu *rvu = s->private; |
| struct npc_mcam *mcam; |
| int pf, vf = -1; |
| bool enabled; |
| int blkaddr; |
| u16 target; |
| u64 hits; |
| |
| blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); |
| if (blkaddr < 0) |
| return 0; |
| |
| mcam = &rvu->hw->mcam; |
| |
| mutex_lock(&mcam->lock); |
| list_for_each_entry(iter, &mcam->mcam_rules, list) { |
| pf = (iter->owner >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK; |
| seq_printf(s, "\n\tInstalled by: PF%d ", pf); |
| |
| if (iter->owner & RVU_PFVF_FUNC_MASK) { |
| vf = (iter->owner & RVU_PFVF_FUNC_MASK) - 1; |
| seq_printf(s, "VF%d", vf); |
| } |
| seq_puts(s, "\n"); |
| |
| seq_printf(s, "\tdirection: %s\n", is_npc_intf_rx(iter->intf) ? |
| "RX" : "TX"); |
| seq_printf(s, "\tinterface: %s\n", |
| rvu_dbg_get_intf_name(iter->intf)); |
| seq_printf(s, "\tmcam entry: %d\n", iter->entry); |
| |
| rvu_dbg_npc_mcam_show_flows(s, iter); |
| if (is_npc_intf_rx(iter->intf)) { |
| target = iter->rx_action.pf_func; |
| pf = (target >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK; |
| seq_printf(s, "\tForward to: PF%d ", pf); |
| |
| if (target & RVU_PFVF_FUNC_MASK) { |
| vf = (target & RVU_PFVF_FUNC_MASK) - 1; |
| seq_printf(s, "VF%d", vf); |
| } |
| seq_puts(s, "\n"); |
| seq_printf(s, "\tchannel: 0x%x\n", iter->chan); |
| seq_printf(s, "\tchannel_mask: 0x%x\n", iter->chan_mask); |
| } |
| |
| rvu_dbg_npc_mcam_show_action(s, iter); |
| |
| enabled = is_mcam_entry_enabled(rvu, mcam, blkaddr, iter->entry); |
| seq_printf(s, "\tenabled: %s\n", enabled ? "yes" : "no"); |
| |
| if (!iter->has_cntr) |
| continue; |
| seq_printf(s, "\tcounter: %d\n", iter->cntr); |
| |
| hits = rvu_read64(rvu, blkaddr, NPC_AF_MATCH_STATX(iter->cntr)); |
| seq_printf(s, "\thits: %lld\n", hits); |
| } |
| mutex_unlock(&mcam->lock); |
| |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(npc_mcam_rules, npc_mcam_show_rules, NULL); |
| |
| static int rvu_dbg_npc_exact_show_entries(struct seq_file *s, void *unused) |
| { |
| struct npc_exact_table_entry *mem_entry[NPC_EXACT_TBL_MAX_WAYS] = { 0 }; |
| struct npc_exact_table_entry *cam_entry; |
| struct npc_exact_table *table; |
| struct rvu *rvu = s->private; |
| int i, j; |
| |
| u8 bitmap = 0; |
| |
| table = rvu->hw->table; |
| |
| mutex_lock(&table->lock); |
| |
| /* Check if there is at least one entry in mem table */ |
| if (!table->mem_tbl_entry_cnt) |
| goto dump_cam_table; |
| |
| /* Print table headers */ |
| seq_puts(s, "\n\tExact Match MEM Table\n"); |
| seq_puts(s, "Index\t"); |
| |
| for (i = 0; i < table->mem_table.ways; i++) { |
| mem_entry[i] = list_first_entry_or_null(&table->lhead_mem_tbl_entry[i], |
| struct npc_exact_table_entry, list); |
| |
| seq_printf(s, "Way-%d\t\t\t\t\t", i); |
| } |
| |
| seq_puts(s, "\n"); |
| for (i = 0; i < table->mem_table.ways; i++) |
| seq_puts(s, "\tChan MAC \t"); |
| |
| seq_puts(s, "\n\n"); |
| |
| /* Print mem table entries */ |
| for (i = 0; i < table->mem_table.depth; i++) { |
| bitmap = 0; |
| for (j = 0; j < table->mem_table.ways; j++) { |
| if (!mem_entry[j]) |
| continue; |
| |
| if (mem_entry[j]->index != i) |
| continue; |
| |
| bitmap |= BIT(j); |
| } |
| |
| /* No valid entries */ |
| if (!bitmap) |
| continue; |
| |
| seq_printf(s, "%d\t", i); |
| for (j = 0; j < table->mem_table.ways; j++) { |
| if (!(bitmap & BIT(j))) { |
| seq_puts(s, "nil\t\t\t\t\t"); |
| continue; |
| } |
| |
| seq_printf(s, "0x%x %pM\t\t\t", mem_entry[j]->chan, |
| mem_entry[j]->mac); |
| mem_entry[j] = list_next_entry(mem_entry[j], list); |
| } |
| seq_puts(s, "\n"); |
| } |
| |
| dump_cam_table: |
| |
| if (!table->cam_tbl_entry_cnt) |
| goto done; |
| |
| seq_puts(s, "\n\tExact Match CAM Table\n"); |
| seq_puts(s, "index\tchan\tMAC\n"); |
| |
| /* Traverse cam table entries */ |
| list_for_each_entry(cam_entry, &table->lhead_cam_tbl_entry, list) { |
| seq_printf(s, "%d\t0x%x\t%pM\n", cam_entry->index, cam_entry->chan, |
| cam_entry->mac); |
| } |
| |
| done: |
| mutex_unlock(&table->lock); |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(npc_exact_entries, npc_exact_show_entries, NULL); |
| |
| static int rvu_dbg_npc_exact_show_info(struct seq_file *s, void *unused) |
| { |
| struct npc_exact_table *table; |
| struct rvu *rvu = s->private; |
| int i; |
| |
| table = rvu->hw->table; |
| |
| seq_puts(s, "\n\tExact Table Info\n"); |
| seq_printf(s, "Exact Match Feature : %s\n", |
| rvu->hw->cap.npc_exact_match_enabled ? "enabled" : "disable"); |
| if (!rvu->hw->cap.npc_exact_match_enabled) |
| return 0; |
| |
| seq_puts(s, "\nMCAM Index\tMAC Filter Rules Count\n"); |
| for (i = 0; i < table->num_drop_rules; i++) |
| seq_printf(s, "%d\t\t%d\n", i, table->cnt_cmd_rules[i]); |
| |
| seq_puts(s, "\nMcam Index\tPromisc Mode Status\n"); |
| for (i = 0; i < table->num_drop_rules; i++) |
| seq_printf(s, "%d\t\t%s\n", i, table->promisc_mode[i] ? "on" : "off"); |
| |
| seq_puts(s, "\n\tMEM Table Info\n"); |
| seq_printf(s, "Ways : %d\n", table->mem_table.ways); |
| seq_printf(s, "Depth : %d\n", table->mem_table.depth); |
| seq_printf(s, "Mask : 0x%llx\n", table->mem_table.mask); |
| seq_printf(s, "Hash Mask : 0x%x\n", table->mem_table.hash_mask); |
| seq_printf(s, "Hash Offset : 0x%x\n", table->mem_table.hash_offset); |
| |
| seq_puts(s, "\n\tCAM Table Info\n"); |
| seq_printf(s, "Depth : %d\n", table->cam_table.depth); |
| |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(npc_exact_info, npc_exact_show_info, NULL); |
| |
| static int rvu_dbg_npc_exact_drop_cnt(struct seq_file *s, void *unused) |
| { |
| struct npc_exact_table *table; |
| struct rvu *rvu = s->private; |
| struct npc_key_field *field; |
| u16 chan, pcifunc; |
| int blkaddr, i; |
| u64 cfg, cam1; |
| char *str; |
| |
| blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); |
| table = rvu->hw->table; |
| |
| field = &rvu->hw->mcam.rx_key_fields[NPC_CHAN]; |
| |
| seq_puts(s, "\n\t Exact Hit on drop status\n"); |
| seq_puts(s, "\npcifunc\tmcam_idx\tHits\tchan\tstatus\n"); |
| |
| for (i = 0; i < table->num_drop_rules; i++) { |
| pcifunc = rvu_npc_exact_drop_rule_to_pcifunc(rvu, i); |
| cfg = rvu_read64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_CFG(i, 0)); |
| |
| /* channel will be always in keyword 0 */ |
| cam1 = rvu_read64(rvu, blkaddr, |
| NPC_AF_MCAMEX_BANKX_CAMX_W0(i, 0, 1)); |
| chan = field->kw_mask[0] & cam1; |
| |
| str = (cfg & 1) ? "enabled" : "disabled"; |
| |
| seq_printf(s, "0x%x\t%d\t\t%llu\t0x%x\t%s\n", pcifunc, i, |
| rvu_read64(rvu, blkaddr, |
| NPC_AF_MATCH_STATX(table->counter_idx[i])), |
| chan, str); |
| } |
| |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(npc_exact_drop_cnt, npc_exact_drop_cnt, NULL); |
| |
| static void rvu_dbg_npc_init(struct rvu *rvu) |
| { |
| rvu->rvu_dbg.npc = debugfs_create_dir("npc", rvu->rvu_dbg.root); |
| |
| debugfs_create_file("mcam_info", 0444, rvu->rvu_dbg.npc, rvu, |
| &rvu_dbg_npc_mcam_info_fops); |
| debugfs_create_file("mcam_rules", 0444, rvu->rvu_dbg.npc, rvu, |
| &rvu_dbg_npc_mcam_rules_fops); |
| |
| debugfs_create_file("rx_miss_act_stats", 0444, rvu->rvu_dbg.npc, rvu, |
| &rvu_dbg_npc_rx_miss_act_fops); |
| |
| if (!rvu->hw->cap.npc_exact_match_enabled) |
| return; |
| |
| debugfs_create_file("exact_entries", 0444, rvu->rvu_dbg.npc, rvu, |
| &rvu_dbg_npc_exact_entries_fops); |
| |
| debugfs_create_file("exact_info", 0444, rvu->rvu_dbg.npc, rvu, |
| &rvu_dbg_npc_exact_info_fops); |
| |
| debugfs_create_file("exact_drop_cnt", 0444, rvu->rvu_dbg.npc, rvu, |
| &rvu_dbg_npc_exact_drop_cnt_fops); |
| |
| } |
| |
| static int cpt_eng_sts_display(struct seq_file *filp, u8 eng_type) |
| { |
| struct cpt_ctx *ctx = filp->private; |
| u64 busy_sts = 0, free_sts = 0; |
| u32 e_min = 0, e_max = 0, e, i; |
| u16 max_ses, max_ies, max_aes; |
| struct rvu *rvu = ctx->rvu; |
| int blkaddr = ctx->blkaddr; |
| u64 reg; |
| |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_CONSTANTS1); |
| max_ses = reg & 0xffff; |
| max_ies = (reg >> 16) & 0xffff; |
| max_aes = (reg >> 32) & 0xffff; |
| |
| switch (eng_type) { |
| case CPT_AE_TYPE: |
| e_min = max_ses + max_ies; |
| e_max = max_ses + max_ies + max_aes; |
| break; |
| case CPT_SE_TYPE: |
| e_min = 0; |
| e_max = max_ses; |
| break; |
| case CPT_IE_TYPE: |
| e_min = max_ses; |
| e_max = max_ses + max_ies; |
| break; |
| default: |
| return -EINVAL; |
| } |
| |
| for (e = e_min, i = 0; e < e_max; e++, i++) { |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_EXEX_STS(e)); |
| if (reg & 0x1) |
| busy_sts |= 1ULL << i; |
| |
| if (reg & 0x2) |
| free_sts |= 1ULL << i; |
| } |
| seq_printf(filp, "FREE STS : 0x%016llx\n", free_sts); |
| seq_printf(filp, "BUSY STS : 0x%016llx\n", busy_sts); |
| |
| return 0; |
| } |
| |
| static int rvu_dbg_cpt_ae_sts_display(struct seq_file *filp, void *unused) |
| { |
| return cpt_eng_sts_display(filp, CPT_AE_TYPE); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(cpt_ae_sts, cpt_ae_sts_display, NULL); |
| |
| static int rvu_dbg_cpt_se_sts_display(struct seq_file *filp, void *unused) |
| { |
| return cpt_eng_sts_display(filp, CPT_SE_TYPE); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(cpt_se_sts, cpt_se_sts_display, NULL); |
| |
| static int rvu_dbg_cpt_ie_sts_display(struct seq_file *filp, void *unused) |
| { |
| return cpt_eng_sts_display(filp, CPT_IE_TYPE); |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(cpt_ie_sts, cpt_ie_sts_display, NULL); |
| |
| static int rvu_dbg_cpt_engines_info_display(struct seq_file *filp, void *unused) |
| { |
| struct cpt_ctx *ctx = filp->private; |
| u16 max_ses, max_ies, max_aes; |
| struct rvu *rvu = ctx->rvu; |
| int blkaddr = ctx->blkaddr; |
| u32 e_max, e; |
| u64 reg; |
| |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_CONSTANTS1); |
| max_ses = reg & 0xffff; |
| max_ies = (reg >> 16) & 0xffff; |
| max_aes = (reg >> 32) & 0xffff; |
| |
| e_max = max_ses + max_ies + max_aes; |
| |
| seq_puts(filp, "===========================================\n"); |
| for (e = 0; e < e_max; e++) { |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_EXEX_CTL2(e)); |
| seq_printf(filp, "CPT Engine[%u] Group Enable 0x%02llx\n", e, |
| reg & 0xff); |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_EXEX_ACTIVE(e)); |
| seq_printf(filp, "CPT Engine[%u] Active Info 0x%llx\n", e, |
| reg); |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_EXEX_CTL(e)); |
| seq_printf(filp, "CPT Engine[%u] Control 0x%llx\n", e, |
| reg); |
| seq_puts(filp, "===========================================\n"); |
| } |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(cpt_engines_info, cpt_engines_info_display, NULL); |
| |
| static int rvu_dbg_cpt_lfs_info_display(struct seq_file *filp, void *unused) |
| { |
| struct cpt_ctx *ctx = filp->private; |
| int blkaddr = ctx->blkaddr; |
| struct rvu *rvu = ctx->rvu; |
| struct rvu_block *block; |
| struct rvu_hwinfo *hw; |
| u64 reg; |
| u32 lf; |
| |
| hw = rvu->hw; |
| block = &hw->block[blkaddr]; |
| if (!block->lf.bmap) |
| return -ENODEV; |
| |
| seq_puts(filp, "===========================================\n"); |
| for (lf = 0; lf < block->lf.max; lf++) { |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL(lf)); |
| seq_printf(filp, "CPT Lf[%u] CTL 0x%llx\n", lf, reg); |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL2(lf)); |
| seq_printf(filp, "CPT Lf[%u] CTL2 0x%llx\n", lf, reg); |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_LFX_PTR_CTL(lf)); |
| seq_printf(filp, "CPT Lf[%u] PTR_CTL 0x%llx\n", lf, reg); |
| reg = rvu_read64(rvu, blkaddr, block->lfcfg_reg | |
| (lf << block->lfshift)); |
| seq_printf(filp, "CPT Lf[%u] CFG 0x%llx\n", lf, reg); |
| seq_puts(filp, "===========================================\n"); |
| } |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(cpt_lfs_info, cpt_lfs_info_display, NULL); |
| |
| static int rvu_dbg_cpt_err_info_display(struct seq_file *filp, void *unused) |
| { |
| struct cpt_ctx *ctx = filp->private; |
| struct rvu *rvu = ctx->rvu; |
| int blkaddr = ctx->blkaddr; |
| u64 reg0, reg1; |
| |
| reg0 = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(0)); |
| reg1 = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(1)); |
| seq_printf(filp, "CPT_AF_FLTX_INT: 0x%llx 0x%llx\n", reg0, reg1); |
| reg0 = rvu_read64(rvu, blkaddr, CPT_AF_PSNX_EXE(0)); |
| reg1 = rvu_read64(rvu, blkaddr, CPT_AF_PSNX_EXE(1)); |
| seq_printf(filp, "CPT_AF_PSNX_EXE: 0x%llx 0x%llx\n", reg0, reg1); |
| reg0 = rvu_read64(rvu, blkaddr, CPT_AF_PSNX_LF(0)); |
| seq_printf(filp, "CPT_AF_PSNX_LF: 0x%llx\n", reg0); |
| reg0 = rvu_read64(rvu, blkaddr, CPT_AF_RVU_INT); |
| seq_printf(filp, "CPT_AF_RVU_INT: 0x%llx\n", reg0); |
| reg0 = rvu_read64(rvu, blkaddr, CPT_AF_RAS_INT); |
| seq_printf(filp, "CPT_AF_RAS_INT: 0x%llx\n", reg0); |
| reg0 = rvu_read64(rvu, blkaddr, CPT_AF_EXE_ERR_INFO); |
| seq_printf(filp, "CPT_AF_EXE_ERR_INFO: 0x%llx\n", reg0); |
| |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(cpt_err_info, cpt_err_info_display, NULL); |
| |
| static int rvu_dbg_cpt_pc_display(struct seq_file *filp, void *unused) |
| { |
| struct cpt_ctx *ctx = filp->private; |
| struct rvu *rvu = ctx->rvu; |
| int blkaddr = ctx->blkaddr; |
| u64 reg; |
| |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_INST_REQ_PC); |
| seq_printf(filp, "CPT instruction requests %llu\n", reg); |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_INST_LATENCY_PC); |
| seq_printf(filp, "CPT instruction latency %llu\n", reg); |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_RD_REQ_PC); |
| seq_printf(filp, "CPT NCB read requests %llu\n", reg); |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_RD_LATENCY_PC); |
| seq_printf(filp, "CPT NCB read latency %llu\n", reg); |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_RD_UC_PC); |
| seq_printf(filp, "CPT read requests caused by UC fills %llu\n", reg); |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_ACTIVE_CYCLES_PC); |
| seq_printf(filp, "CPT active cycles pc %llu\n", reg); |
| reg = rvu_read64(rvu, blkaddr, CPT_AF_CPTCLK_CNT); |
| seq_printf(filp, "CPT clock count pc %llu\n", reg); |
| |
| return 0; |
| } |
| |
| RVU_DEBUG_SEQ_FOPS(cpt_pc, cpt_pc_display, NULL); |
| |
| static void rvu_dbg_cpt_init(struct rvu *rvu, int blkaddr) |
| { |
| struct cpt_ctx *ctx; |
| |
| if (!is_block_implemented(rvu->hw, blkaddr)) |
| return; |
| |
| if (blkaddr == BLKADDR_CPT0) { |
| rvu->rvu_dbg.cpt = debugfs_create_dir("cpt", rvu->rvu_dbg.root); |
| ctx = &rvu->rvu_dbg.cpt_ctx[0]; |
| ctx->blkaddr = BLKADDR_CPT0; |
| ctx->rvu = rvu; |
| } else { |
| rvu->rvu_dbg.cpt = debugfs_create_dir("cpt1", |
| rvu->rvu_dbg.root); |
| ctx = &rvu->rvu_dbg.cpt_ctx[1]; |
| ctx->blkaddr = BLKADDR_CPT1; |
| ctx->rvu = rvu; |
| } |
| |
| debugfs_create_file("cpt_pc", 0600, rvu->rvu_dbg.cpt, ctx, |
| &rvu_dbg_cpt_pc_fops); |
| debugfs_create_file("cpt_ae_sts", 0600, rvu->rvu_dbg.cpt, ctx, |
| &rvu_dbg_cpt_ae_sts_fops); |
| debugfs_create_file("cpt_se_sts", 0600, rvu->rvu_dbg.cpt, ctx, |
| &rvu_dbg_cpt_se_sts_fops); |
| debugfs_create_file("cpt_ie_sts", 0600, rvu->rvu_dbg.cpt, ctx, |
| &rvu_dbg_cpt_ie_sts_fops); |
| debugfs_create_file("cpt_engines_info", 0600, rvu->rvu_dbg.cpt, ctx, |
| &rvu_dbg_cpt_engines_info_fops); |
| debugfs_create_file("cpt_lfs_info", 0600, rvu->rvu_dbg.cpt, ctx, |
| &rvu_dbg_cpt_lfs_info_fops); |
| debugfs_create_file("cpt_err_info", 0600, rvu->rvu_dbg.cpt, ctx, |
| &rvu_dbg_cpt_err_info_fops); |
| } |
| |
| static const char *rvu_get_dbg_dir_name(struct rvu *rvu) |
| { |
| if (!is_rvu_otx2(rvu)) |
| return "cn10k"; |
| else |
| return "octeontx2"; |
| } |
| |
| void rvu_dbg_init(struct rvu *rvu) |
| { |
| rvu->rvu_dbg.root = debugfs_create_dir(rvu_get_dbg_dir_name(rvu), NULL); |
| |
| debugfs_create_file("rsrc_alloc", 0444, rvu->rvu_dbg.root, rvu, |
| &rvu_dbg_rsrc_status_fops); |
| |
| if (!is_rvu_otx2(rvu)) |
| debugfs_create_file("lmtst_map_table", 0444, rvu->rvu_dbg.root, |
| rvu, &rvu_dbg_lmtst_map_table_fops); |
| |
| if (!cgx_get_cgxcnt_max()) |
| goto create; |
| |
| if (is_rvu_otx2(rvu)) |
| debugfs_create_file("rvu_pf_cgx_map", 0444, rvu->rvu_dbg.root, |
| rvu, &rvu_dbg_rvu_pf_cgx_map_fops); |
| else |
| debugfs_create_file("rvu_pf_rpm_map", 0444, rvu->rvu_dbg.root, |
| rvu, &rvu_dbg_rvu_pf_cgx_map_fops); |
| |
| create: |
| rvu_dbg_npa_init(rvu); |
| rvu_dbg_nix_init(rvu, BLKADDR_NIX0); |
| |
| rvu_dbg_nix_init(rvu, BLKADDR_NIX1); |
| rvu_dbg_cgx_init(rvu); |
| rvu_dbg_npc_init(rvu); |
| rvu_dbg_cpt_init(rvu, BLKADDR_CPT0); |
| rvu_dbg_cpt_init(rvu, BLKADDR_CPT1); |
| rvu_dbg_mcs_init(rvu); |
| } |
| |
| void rvu_dbg_exit(struct rvu *rvu) |
| { |
| debugfs_remove_recursive(rvu->rvu_dbg.root); |
| } |
| |
| #endif /* CONFIG_DEBUG_FS */ |