1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2024 Oxide Computer Company 14 */ 15 16 /* 17 * This implements the stat routines that interface with the hardware directly. 18 */ 19 20 #include "igc.h" 21 22 void 23 igc_stats_fini(igc_t *igc) 24 { 25 if (igc->igc_ksp != NULL) { 26 kstat_delete(igc->igc_ksp); 27 igc->igc_ksp = NULL; 28 } 29 } 30 31 /* 32 * Read a pair of low and high registers to get a stat. The low register must 33 * come ahead of the high. 34 */ 35 void 36 igc_stats_update_u64(igc_t *igc, kstat_named_t *ks, uint32_t reg) 37 { 38 uint64_t val = igc_read32(igc, reg); 39 val += (uint64_t)igc_read32(igc, reg + 4) << 32UL; 40 ks->value.ui64 += val; 41 } 42 43 static int 44 igc_stats_update(kstat_t *ksp, int rw) 45 { 46 igc_t *igc; 47 igc_stats_t *stats; 48 49 if (rw != KSTAT_READ) 50 return (EACCES); 51 52 igc = ksp->ks_private; 53 stats = &igc->igc_stats; 54 55 mutex_enter(&igc->igc_lock); 56 57 stats->is_crcerrs.value.ui64 += igc_read32(igc, IGC_CRCERRS); 58 stats->is_algnerrc.value.ui64 += igc_read32(igc, IGC_ALGNERRC); 59 stats->is_mpc.value.ui64 += igc_read32(igc, IGC_MPC); 60 stats->is_scc.value.ui64 += igc_read32(igc, IGC_SCC); 61 stats->is_ecol.value.ui64 += igc_read32(igc, IGC_ECOL); 62 stats->is_mcc.value.ui64 += igc_read32(igc, IGC_MCC); 63 stats->is_latecol.value.ui64 += igc_read32(igc, IGC_LATECOL); 64 stats->is_colc.value.ui64 += igc_read32(igc, IGC_COLC); 65 stats->is_rerc.value.ui64 += igc_read32(igc, IGC_RERC); 66 stats->is_dc.value.ui64 += igc_read32(igc, IGC_DC); 67 stats->is_tncrs.value.ui64 += igc_read32(igc, IGC_TNCRS); 68 stats->is_htdpmc.value.ui64 += igc_read32(igc, IGC_HTDPMC); 69 stats->is_rlec.value.ui64 += igc_read32(igc, IGC_RLEC); 70 stats->is_xonrxc.value.ui64 += igc_read32(igc, IGC_XONRXC); 71 stats->is_xontxc.value.ui64 += igc_read32(igc, IGC_XONTXC); 72 stats->is_xoffrxc.value.ui64 += igc_read32(igc, IGC_XOFFRXC); 73 stats->is_xofftxc.value.ui64 += igc_read32(igc, IGC_XOFFTXC); 74 stats->is_fcruc.value.ui64 += igc_read32(igc, IGC_FCRUC); 75 stats->is_prc64.value.ui64 += igc_read32(igc, IGC_PRC64); 76 stats->is_prc127.value.ui64 += igc_read32(igc, IGC_PRC127); 77 stats->is_prc255.value.ui64 += igc_read32(igc, IGC_PRC255); 78 stats->is_prc1023.value.ui64 += igc_read32(igc, IGC_PRC1023); 79 stats->is_prc1522.value.ui64 += igc_read32(igc, IGC_PRC1522); 80 stats->is_gprc.value.ui64 += igc_read32(igc, IGC_GPRC); 81 stats->is_bprc.value.ui64 += igc_read32(igc, IGC_BPRC); 82 stats->is_mprc.value.ui64 += igc_read32(igc, IGC_MPRC); 83 stats->is_gptc.value.ui64 += igc_read32(igc, IGC_GPTC); 84 igc_stats_update_u64(igc, &stats->is_gorc, IGC_GORCL); 85 igc_stats_update_u64(igc, &stats->is_gotc, IGC_GOTCL); 86 stats->is_rnbc.value.ui64 += igc_read32(igc, IGC_RNBC); 87 stats->is_ruc.value.ui64 += igc_read32(igc, IGC_RUC); 88 stats->is_rfc.value.ui64 += igc_read32(igc, IGC_RFC); 89 stats->is_roc.value.ui64 += igc_read32(igc, IGC_ROC); 90 stats->is_rjc.value.ui64 += igc_read32(igc, IGC_RJC); 91 stats->is_mgtprc.value.ui64 += igc_read32(igc, IGC_MGTPRC); 92 stats->is_mgtpdc.value.ui64 += igc_read32(igc, IGC_MGTPDC); 93 stats->is_mgtptc.value.ui64 += igc_read32(igc, IGC_MGTPTC); 94 igc_stats_update_u64(igc, &stats->is_tor, IGC_TORL); 95 igc_stats_update_u64(igc, &stats->is_tot, IGC_TOTL); 96 stats->is_tpr.value.ui64 += igc_read32(igc, IGC_TPR); 97 stats->is_tpt.value.ui64 += igc_read32(igc, IGC_TPT); 98 stats->is_ptc64.value.ui64 += igc_read32(igc, IGC_PTC64); 99 stats->is_ptc127.value.ui64 += igc_read32(igc, IGC_PTC127); 100 stats->is_ptc255.value.ui64 += igc_read32(igc, IGC_PTC255); 101 stats->is_ptc511.value.ui64 += igc_read32(igc, IGC_PTC511); 102 stats->is_ptc1023.value.ui64 += igc_read32(igc, IGC_PTC1023); 103 stats->is_ptc1522.value.ui64 += igc_read32(igc, IGC_PTC1522); 104 stats->is_mptc.value.ui64 += igc_read32(igc, IGC_MPTC); 105 stats->is_bptc.value.ui64 += igc_read32(igc, IGC_BPTC); 106 stats->is_tsctc.value.ui64 += igc_read32(igc, IGC_TSCTC); 107 stats->is_iac.value.ui64 += igc_read32(igc, IGC_IAC); 108 stats->is_rxdmtc.value.ui64 += igc_read32(igc, IGC_RXDMTC); 109 mutex_exit(&igc->igc_lock); 110 111 return (0); 112 } 113 114 bool 115 igc_stats_init(igc_t *igc) 116 { 117 kstat_t *ksp; 118 igc_stats_t *stats = &igc->igc_stats; 119 120 ksp = kstat_create(IGC_MOD_NAME, ddi_get_instance(igc->igc_dip), 121 "stats", "net", KSTAT_TYPE_NAMED, sizeof (igc_stats_t) / 122 sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL); 123 if (ksp == NULL) { 124 dev_err(igc->igc_dip, CE_WARN, "failed to create kstats"); 125 return (false); 126 } 127 128 igc->igc_ksp = ksp; 129 ksp->ks_update = igc_stats_update; 130 ksp->ks_private = igc; 131 ksp->ks_data = stats; 132 133 kstat_named_init(&stats->is_crcerrs, "crcerrs", 134 KSTAT_DATA_UINT64); 135 kstat_named_init(&stats->is_algnerrc, "algnerrc", 136 KSTAT_DATA_UINT64); 137 kstat_named_init(&stats->is_mpc, "mpc", 138 KSTAT_DATA_UINT64); 139 kstat_named_init(&stats->is_scc, "scc", 140 KSTAT_DATA_UINT64); 141 kstat_named_init(&stats->is_ecol, "ecol", 142 KSTAT_DATA_UINT64); 143 kstat_named_init(&stats->is_mcc, "mcc", 144 KSTAT_DATA_UINT64); 145 kstat_named_init(&stats->is_latecol, "latecol", 146 KSTAT_DATA_UINT64); 147 kstat_named_init(&stats->is_colc, "colc", 148 KSTAT_DATA_UINT64); 149 kstat_named_init(&stats->is_rerc, "rerc", 150 KSTAT_DATA_UINT64); 151 kstat_named_init(&stats->is_dc, "dc", 152 KSTAT_DATA_UINT64); 153 kstat_named_init(&stats->is_tncrs, "tncrs", 154 KSTAT_DATA_UINT64); 155 kstat_named_init(&stats->is_htdpmc, "htdpmc", 156 KSTAT_DATA_UINT64); 157 kstat_named_init(&stats->is_rlec, "rlec", 158 KSTAT_DATA_UINT64); 159 kstat_named_init(&stats->is_xonrxc, "xonrxc", 160 KSTAT_DATA_UINT64); 161 kstat_named_init(&stats->is_xontxc, "xontxc", 162 KSTAT_DATA_UINT64); 163 kstat_named_init(&stats->is_xoffrxc, "xoffrxc", 164 KSTAT_DATA_UINT64); 165 kstat_named_init(&stats->is_xofftxc, "xofftxc", 166 KSTAT_DATA_UINT64); 167 kstat_named_init(&stats->is_fcruc, "fcruc", 168 KSTAT_DATA_UINT64); 169 kstat_named_init(&stats->is_prc64, "prc64", 170 KSTAT_DATA_UINT64); 171 kstat_named_init(&stats->is_prc127, "prc127", 172 KSTAT_DATA_UINT64); 173 kstat_named_init(&stats->is_prc255, "prc255", 174 KSTAT_DATA_UINT64); 175 kstat_named_init(&stats->is_prc1023, "prc1023", 176 KSTAT_DATA_UINT64); 177 kstat_named_init(&stats->is_prc1522, "prc1522", 178 KSTAT_DATA_UINT64); 179 kstat_named_init(&stats->is_gprc, "gprc", 180 KSTAT_DATA_UINT64); 181 kstat_named_init(&stats->is_bprc, "bprc", 182 KSTAT_DATA_UINT64); 183 kstat_named_init(&stats->is_mprc, "mprc", 184 KSTAT_DATA_UINT64); 185 kstat_named_init(&stats->is_gptc, "gptc", 186 KSTAT_DATA_UINT64); 187 kstat_named_init(&stats->is_gorc, "gorc", 188 KSTAT_DATA_UINT64); 189 kstat_named_init(&stats->is_gotc, "gotc", 190 KSTAT_DATA_UINT64); 191 kstat_named_init(&stats->is_rnbc, "rnbc", 192 KSTAT_DATA_UINT64); 193 kstat_named_init(&stats->is_ruc, "ruc", 194 KSTAT_DATA_UINT64); 195 kstat_named_init(&stats->is_rfc, "rfc", 196 KSTAT_DATA_UINT64); 197 kstat_named_init(&stats->is_roc, "roc", 198 KSTAT_DATA_UINT64); 199 kstat_named_init(&stats->is_rjc, "rjc", 200 KSTAT_DATA_UINT64); 201 kstat_named_init(&stats->is_mgtprc, "mgtprc", 202 KSTAT_DATA_UINT64); 203 kstat_named_init(&stats->is_mgtpdc, "mgtpdc", 204 KSTAT_DATA_UINT64); 205 kstat_named_init(&stats->is_mgtptc, "mgtptc", 206 KSTAT_DATA_UINT64); 207 kstat_named_init(&stats->is_tor, "tor", 208 KSTAT_DATA_UINT64); 209 kstat_named_init(&stats->is_tot, "tot", 210 KSTAT_DATA_UINT64); 211 kstat_named_init(&stats->is_tpr, "tpr", 212 KSTAT_DATA_UINT64); 213 kstat_named_init(&stats->is_tpt, "tpt", 214 KSTAT_DATA_UINT64); 215 kstat_named_init(&stats->is_ptc64, "ptc64", 216 KSTAT_DATA_UINT64); 217 kstat_named_init(&stats->is_ptc127, "ptc127", 218 KSTAT_DATA_UINT64); 219 kstat_named_init(&stats->is_ptc255, "ptc255", 220 KSTAT_DATA_UINT64); 221 kstat_named_init(&stats->is_ptc511, "ptc511", 222 KSTAT_DATA_UINT64); 223 kstat_named_init(&stats->is_ptc1023, "ptc1023", 224 KSTAT_DATA_UINT64); 225 kstat_named_init(&stats->is_ptc1522, "ptc1522", 226 KSTAT_DATA_UINT64); 227 kstat_named_init(&stats->is_mptc, "mptc", 228 KSTAT_DATA_UINT64); 229 kstat_named_init(&stats->is_bptc, "bptc", 230 KSTAT_DATA_UINT64); 231 kstat_named_init(&stats->is_tsctc, "tsctc", 232 KSTAT_DATA_UINT64); 233 kstat_named_init(&stats->is_iac, "iac", 234 KSTAT_DATA_UINT64); 235 kstat_named_init(&stats->is_rxdmtc, "rxdmtc", 236 KSTAT_DATA_UINT64); 237 238 kstat_install(ksp); 239 240 return (true); 241 } 242 243 void 244 igc_rx_ring_stats_fini(igc_rx_ring_t *ring) 245 { 246 if (ring->irr_kstat != NULL) { 247 kstat_delete(ring->irr_kstat); 248 ring->irr_kstat = NULL; 249 } 250 } 251 252 bool 253 igc_rx_ring_stats_init(igc_t *igc, igc_rx_ring_t *ring) 254 { 255 kstat_t *ksp; 256 igc_rx_stats_t *stats = &ring->irr_stat; 257 char name[32]; 258 259 (void) snprintf(name, sizeof (name), "rxring%u", ring->irr_idx); 260 ksp = kstat_create(IGC_MOD_NAME, ddi_get_instance(igc->igc_dip), 261 name, "net", KSTAT_TYPE_NAMED, sizeof (igc_rx_stats_t) / 262 sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL); 263 if (ksp == NULL) { 264 dev_err(igc->igc_dip, CE_WARN, "failed to create rx ring %u " 265 "kstats", ring->irr_idx); 266 return (false); 267 } 268 269 ring->irr_kstat = ksp; 270 ksp->ks_data = stats; 271 272 kstat_named_init(&stats->irs_rbytes, "rbytes", KSTAT_DATA_UINT64); 273 kstat_named_init(&stats->irs_ipackets, "ipackets", KSTAT_DATA_UINT64); 274 kstat_named_init(&stats->irs_desc_error, "desc_error", 275 KSTAT_DATA_UINT64); 276 kstat_named_init(&stats->irs_copy_nomem, "copy_nomem", 277 KSTAT_DATA_UINT64); 278 kstat_named_init(&stats->irs_bind_nobuf, "bind_nobuf", 279 KSTAT_DATA_UINT64); 280 kstat_named_init(&stats->irs_bind_nomp, "bind_nomp", KSTAT_DATA_UINT64); 281 kstat_named_init(&stats->irs_nbind, "nbind", KSTAT_DATA_UINT64); 282 kstat_named_init(&stats->irs_ncopy, "ncopy", KSTAT_DATA_UINT64); 283 kstat_named_init(&stats->irs_ixsm, "ixsm", KSTAT_DATA_UINT64); 284 kstat_named_init(&stats->irs_l3cksum_err, "l3cksum_err", 285 KSTAT_DATA_UINT64); 286 kstat_named_init(&stats->irs_l4cksum_err, "l4cksum_err", 287 KSTAT_DATA_UINT64); 288 kstat_named_init(&stats->irs_hcksum_miss, "hcksum_miss", 289 KSTAT_DATA_UINT64); 290 kstat_named_init(&stats->irs_hcksum_hit, "hcksum_hit", 291 KSTAT_DATA_UINT64); 292 293 kstat_install(ksp); 294 295 return (true); 296 } 297 298 void 299 igc_tx_ring_stats_fini(igc_tx_ring_t *ring) 300 { 301 if (ring->itr_kstat != NULL) { 302 kstat_delete(ring->itr_kstat); 303 ring->itr_kstat = NULL; 304 } 305 } 306 307 bool 308 igc_tx_ring_stats_init(igc_t *igc, igc_tx_ring_t *ring) 309 { 310 kstat_t *ksp; 311 igc_tx_stats_t *stats = &ring->itr_stat; 312 char name[32]; 313 314 (void) snprintf(name, sizeof (name), "txring%u", ring->itr_idx); 315 ksp = kstat_create(IGC_MOD_NAME, ddi_get_instance(igc->igc_dip), 316 name, "net", KSTAT_TYPE_NAMED, sizeof (igc_tx_stats_t) / 317 sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL); 318 if (ksp == NULL) { 319 dev_err(igc->igc_dip, CE_WARN, "failed to create tx ring %u " 320 "kstats", ring->itr_idx); 321 return (false); 322 } 323 324 ring->itr_kstat = ksp; 325 ksp->ks_data = stats; 326 327 kstat_named_init(&stats->its_obytes, "obytes", KSTAT_DATA_UINT64); 328 kstat_named_init(&stats->its_opackets, "opackets", KSTAT_DATA_UINT64); 329 kstat_named_init(&stats->its_bad_meo, "bad_meo", KSTAT_DATA_UINT64); 330 kstat_named_init(&stats->its_ring_full, "ring_full", KSTAT_DATA_UINT64); 331 kstat_named_init(&stats->its_no_tx_bufs, "no_tx_bufs", 332 KSTAT_DATA_UINT64); 333 kstat_named_init(&stats->its_tx_copy, "tx_copy", KSTAT_DATA_UINT64); 334 kstat_named_init(&stats->its_tx_bind, "tx_bind", KSTAT_DATA_UINT64); 335 kstat_named_init(&stats->its_tx_bind_fail, "tx_bind_fail", 336 KSTAT_DATA_UINT64); 337 338 kstat_install(ksp); 339 340 return (true); 341 } 342