1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) 2 /* 3 * NXP NETC switch driver 4 * Copyright 2025-2026 NXP 5 */ 6 7 #include <linux/ethtool_netlink.h> 8 9 #include "netc_switch.h" 10 11 static const struct ethtool_rmon_hist_range netc_rmon_ranges[] = { 12 { 64, 64 }, 13 { 65, 127 }, 14 { 128, 255 }, 15 { 256, 511 }, 16 { 512, 1023 }, 17 { 1024, 1522 }, 18 { 1523, NETC_MAX_FRAME_LEN }, 19 { } 20 }; 21 22 static void netc_port_pause_stats(struct netc_port *np, int mac, 23 struct ethtool_pause_stats *stats) 24 { 25 if (mac && !np->caps.pmac) 26 return; 27 28 stats->tx_pause_frames = netc_port_rd64(np, NETC_PM_TXPF(mac)); 29 stats->rx_pause_frames = netc_port_rd64(np, NETC_PM_RXPF(mac)); 30 } 31 32 void netc_port_get_pause_stats(struct dsa_switch *ds, int port, 33 struct ethtool_pause_stats *pause_stats) 34 { 35 struct netc_port *np = NETC_PORT(ds, port); 36 struct net_device *ndev; 37 38 switch (pause_stats->src) { 39 case ETHTOOL_MAC_STATS_SRC_EMAC: 40 netc_port_pause_stats(np, 0, pause_stats); 41 break; 42 case ETHTOOL_MAC_STATS_SRC_PMAC: 43 netc_port_pause_stats(np, 1, pause_stats); 44 break; 45 case ETHTOOL_MAC_STATS_SRC_AGGREGATE: 46 ndev = dsa_to_port(ds, port)->user; 47 ethtool_aggregate_pause_stats(ndev, pause_stats); 48 break; 49 } 50 } 51 52 static void netc_port_rmon_stats(struct netc_port *np, int mac, 53 struct ethtool_rmon_stats *stats) 54 { 55 if (mac && !np->caps.pmac) 56 return; 57 58 stats->undersize_pkts = netc_port_rd64(np, NETC_PM_RUND(mac)); 59 stats->oversize_pkts = netc_port_rd64(np, NETC_PM_ROVR(mac)); 60 stats->fragments = netc_port_rd64(np, NETC_PM_RFRG(mac)); 61 stats->jabbers = netc_port_rd64(np, NETC_PM_RJBR(mac)); 62 63 stats->hist[0] = netc_port_rd64(np, NETC_PM_R64(mac)); 64 stats->hist[1] = netc_port_rd64(np, NETC_PM_R127(mac)); 65 stats->hist[2] = netc_port_rd64(np, NETC_PM_R255(mac)); 66 stats->hist[3] = netc_port_rd64(np, NETC_PM_R511(mac)); 67 stats->hist[4] = netc_port_rd64(np, NETC_PM_R1023(mac)); 68 stats->hist[5] = netc_port_rd64(np, NETC_PM_R1522(mac)); 69 stats->hist[6] = netc_port_rd64(np, NETC_PM_R1523X(mac)); 70 71 stats->hist_tx[0] = netc_port_rd64(np, NETC_PM_T64(mac)); 72 stats->hist_tx[1] = netc_port_rd64(np, NETC_PM_T127(mac)); 73 stats->hist_tx[2] = netc_port_rd64(np, NETC_PM_T255(mac)); 74 stats->hist_tx[3] = netc_port_rd64(np, NETC_PM_T511(mac)); 75 stats->hist_tx[4] = netc_port_rd64(np, NETC_PM_T1023(mac)); 76 stats->hist_tx[5] = netc_port_rd64(np, NETC_PM_T1522(mac)); 77 stats->hist_tx[6] = netc_port_rd64(np, NETC_PM_T1523X(mac)); 78 } 79 80 void netc_port_get_rmon_stats(struct dsa_switch *ds, int port, 81 struct ethtool_rmon_stats *rmon_stats, 82 const struct ethtool_rmon_hist_range **ranges) 83 { 84 struct netc_port *np = NETC_PORT(ds, port); 85 struct net_device *ndev; 86 87 *ranges = netc_rmon_ranges; 88 89 switch (rmon_stats->src) { 90 case ETHTOOL_MAC_STATS_SRC_EMAC: 91 netc_port_rmon_stats(np, 0, rmon_stats); 92 break; 93 case ETHTOOL_MAC_STATS_SRC_PMAC: 94 netc_port_rmon_stats(np, 1, rmon_stats); 95 break; 96 case ETHTOOL_MAC_STATS_SRC_AGGREGATE: 97 ndev = dsa_to_port(ds, port)->user; 98 ethtool_aggregate_rmon_stats(ndev, rmon_stats); 99 break; 100 } 101 } 102 103 static void netc_port_ctrl_stats(struct netc_port *np, int mac, 104 struct ethtool_eth_ctrl_stats *stats) 105 { 106 if (mac && !np->caps.pmac) 107 return; 108 109 stats->MACControlFramesTransmitted = 110 netc_port_rd64(np, NETC_PM_TCNP(mac)); 111 stats->MACControlFramesReceived = 112 netc_port_rd64(np, NETC_PM_RCNP(mac)); 113 } 114 115 void netc_port_get_eth_ctrl_stats(struct dsa_switch *ds, int port, 116 struct ethtool_eth_ctrl_stats *ctrl_stats) 117 { 118 struct netc_port *np = NETC_PORT(ds, port); 119 struct net_device *ndev; 120 121 switch (ctrl_stats->src) { 122 case ETHTOOL_MAC_STATS_SRC_EMAC: 123 netc_port_ctrl_stats(np, 0, ctrl_stats); 124 break; 125 case ETHTOOL_MAC_STATS_SRC_PMAC: 126 netc_port_ctrl_stats(np, 1, ctrl_stats); 127 break; 128 case ETHTOOL_MAC_STATS_SRC_AGGREGATE: 129 ndev = dsa_to_port(ds, port)->user; 130 ethtool_aggregate_ctrl_stats(ndev, ctrl_stats); 131 break; 132 } 133 } 134 135 static void netc_port_mac_stats(struct netc_port *np, int mac, 136 struct ethtool_eth_mac_stats *stats) 137 { 138 if (mac && !np->caps.pmac) 139 return; 140 141 stats->FramesTransmittedOK = netc_port_rd64(np, NETC_PM_TFRM(mac)); 142 stats->SingleCollisionFrames = netc_port_rd64(np, NETC_PM_TSCOL(mac)); 143 stats->MultipleCollisionFrames = 144 netc_port_rd64(np, NETC_PM_TMCOL(mac)); 145 stats->FramesReceivedOK = netc_port_rd64(np, NETC_PM_RFRM(mac)); 146 stats->FrameCheckSequenceErrors = 147 netc_port_rd64(np, NETC_PM_RFCS(mac)); 148 stats->AlignmentErrors = netc_port_rd64(np, NETC_PM_RALN(mac)); 149 stats->OctetsTransmittedOK = netc_port_rd64(np, NETC_PM_TEOCT(mac)); 150 stats->FramesWithDeferredXmissions = 151 netc_port_rd64(np, NETC_PM_TDFR(mac)); 152 stats->LateCollisions = netc_port_rd64(np, NETC_PM_TLCOL(mac)); 153 stats->FramesAbortedDueToXSColls = 154 netc_port_rd64(np, NETC_PM_TECOL(mac)); 155 stats->FramesLostDueToIntMACXmitError = 156 netc_port_rd64(np, NETC_PM_TERR(mac)); 157 stats->OctetsReceivedOK = netc_port_rd64(np, NETC_PM_REOCT(mac)); 158 stats->FramesLostDueToIntMACRcvError = 159 netc_port_rd64(np, NETC_PM_RDRNTP(mac)); 160 stats->MulticastFramesXmittedOK = 161 netc_port_rd64(np, NETC_PM_TMCA(mac)); 162 stats->BroadcastFramesXmittedOK = 163 netc_port_rd64(np, NETC_PM_TBCA(mac)); 164 stats->MulticastFramesReceivedOK = 165 netc_port_rd64(np, NETC_PM_RMCA(mac)); 166 stats->BroadcastFramesReceivedOK = 167 netc_port_rd64(np, NETC_PM_RBCA(mac)); 168 stats->FramesWithExcessiveDeferral = 169 netc_port_rd64(np, NETC_PM_TEDFR(mac)); 170 } 171 172 void netc_port_get_eth_mac_stats(struct dsa_switch *ds, int port, 173 struct ethtool_eth_mac_stats *mac_stats) 174 { 175 struct netc_port *np = NETC_PORT(ds, port); 176 struct net_device *ndev; 177 178 switch (mac_stats->src) { 179 case ETHTOOL_MAC_STATS_SRC_EMAC: 180 netc_port_mac_stats(np, 0, mac_stats); 181 break; 182 case ETHTOOL_MAC_STATS_SRC_PMAC: 183 netc_port_mac_stats(np, 1, mac_stats); 184 break; 185 case ETHTOOL_MAC_STATS_SRC_AGGREGATE: 186 ndev = dsa_to_port(ds, port)->user; 187 ethtool_aggregate_mac_stats(ndev, mac_stats); 188 break; 189 } 190 } 191