1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright(c) 2019-2021 Xilinx, Inc. 4 * Copyright(c) 2009-2019 Solarflare Communications Inc. 5 */ 6 7 #include "efx.h" 8 #include "efx_impl.h" 9 #include "mcdi_mon.h" 10 11 #if EFSYS_OPT_MON_MCDI 12 13 #if EFSYS_OPT_MON_STATS 14 15 /* Get port mask from one-based MCDI port number */ 16 #define MCDI_MON_PORT_MASK(_emip) (1U << ((_emip)->emi_port - 1)) 17 18 #define MCDI_STATIC_SENSOR_ASSERT(_field) \ 19 EFX_STATIC_ASSERT(MC_CMD_SENSOR_STATE_ ## _field \ 20 == EFX_MON_STAT_STATE_ ## _field) 21 22 static void 23 mcdi_mon_decode_stats( 24 __in efx_nic_t *enp, 25 __in_bcount(sensor_mask_size) uint32_t *sensor_mask, 26 __in size_t sensor_mask_size, 27 __in_opt efsys_mem_t *esmp, 28 __out_bcount_opt(sensor_mask_size) uint32_t *stat_maskp, 29 __inout_ecount_opt(EFX_MON_NSTATS) efx_mon_stat_value_t *stat) 30 { 31 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 32 efx_mon_stat_portmask_t port_mask; 33 uint16_t sensor; 34 size_t sensor_max; 35 uint32_t stat_mask[(EFX_MON_NSTATS + 31) / 32]; 36 uint32_t idx = 0; 37 uint32_t page = 0; 38 39 /* Assert the MC_CMD_SENSOR and EFX_MON_STATE namespaces agree */ 40 MCDI_STATIC_SENSOR_ASSERT(OK); 41 MCDI_STATIC_SENSOR_ASSERT(WARNING); 42 MCDI_STATIC_SENSOR_ASSERT(FATAL); 43 MCDI_STATIC_SENSOR_ASSERT(BROKEN); 44 MCDI_STATIC_SENSOR_ASSERT(NO_READING); 45 46 sensor_max = 8 * sensor_mask_size; 47 48 EFSYS_ASSERT(emip->emi_port > 0); /* MCDI port number is one-based */ 49 port_mask = (efx_mon_stat_portmask_t)MCDI_MON_PORT_MASK(emip); 50 51 memset(stat_mask, 0, sizeof (stat_mask)); 52 53 /* 54 * The MCDI sensor readings in the DMA buffer are a packed array of 55 * MC_CMD_SENSOR_VALUE_ENTRY structures, which only includes entries for 56 * supported sensors (bit set in sensor_mask). The sensor_mask and 57 * sensor readings do not include entries for the per-page NEXT_PAGE 58 * flag. 59 * 60 * sensor_mask may legitimately contain MCDI sensors that the driver 61 * does not understand. 62 */ 63 for (sensor = 0; sensor < sensor_max; ++sensor) { 64 efx_mon_stat_t id; 65 efx_mon_stat_portmask_t stat_portmask = 0; 66 efx_mon_stat_unit_t stat_unit; 67 68 if ((sensor % (MC_CMD_SENSOR_PAGE0_NEXT + 1)) == 69 MC_CMD_SENSOR_PAGE0_NEXT) { 70 /* This sensor is one of the page boundary bits. */ 71 page++; 72 continue; 73 } 74 75 if (~(sensor_mask[page]) & 76 (1U << (sensor % (sizeof (sensor_mask[page]) * 8)))) { 77 /* This sensor is not supported. */ 78 continue; 79 } 80 81 /* Supported sensor, so it is present in the DMA buffer. */ 82 idx++; 83 84 if ((efx_mon_mcdi_to_efx_stat(sensor, &id) != B_TRUE) || 85 (efx_mon_get_stat_portmap(id, &stat_portmask) != B_TRUE)) { 86 /* The sensor is not known to the driver. */ 87 continue; 88 } 89 90 if ((stat_portmask & port_mask) == 0) { 91 /* The sensor is not for this port. */ 92 continue; 93 } 94 95 EFSYS_ASSERT(id < EFX_MON_NSTATS); 96 97 /* 98 * stat_mask is a bitmask indexed by EFX_MON_* monitor statistic 99 * identifiers from efx_mon_stat_t (without NEXT_PAGE bits). 100 * 101 * If there is an entry in the MCDI sensor to monitor statistic 102 * map then the sensor reading is used for the value of the 103 * monitor statistic. 104 */ 105 stat_mask[id / EFX_MON_MASK_ELEMENT_SIZE] |= 106 (1U << (id % EFX_MON_MASK_ELEMENT_SIZE)); 107 108 if (stat != NULL && esmp != NULL && !EFSYS_MEM_IS_NULL(esmp)) { 109 efx_dword_t dword; 110 111 /* Get MCDI sensor reading from DMA buffer */ 112 EFSYS_MEM_READD(esmp, 4 * (idx - 1), &dword); 113 114 /* Update EFX monitor stat from MCDI sensor reading */ 115 stat[id].emsv_value = (uint16_t)EFX_DWORD_FIELD(dword, 116 MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE); 117 118 stat[id].emsv_state = (uint16_t)EFX_DWORD_FIELD(dword, 119 MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE); 120 121 stat[id].emsv_unit = 122 efx_mon_get_stat_unit(id, &stat_unit) ? 123 stat_unit : EFX_MON_STAT_UNIT_UNKNOWN; 124 } 125 } 126 127 if (stat_maskp != NULL) { 128 memcpy(stat_maskp, stat_mask, sizeof (stat_mask)); 129 } 130 } 131 132 __checkReturn efx_rc_t 133 mcdi_mon_ev( 134 __in efx_nic_t *enp, 135 __in efx_qword_t *eqp, 136 __out efx_mon_stat_t *idp, 137 __out efx_mon_stat_value_t *valuep) 138 { 139 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 140 efx_mon_stat_portmask_t port_mask, sensor_port_mask; 141 uint16_t sensor; 142 uint16_t state; 143 uint16_t value; 144 efx_mon_stat_t id; 145 efx_rc_t rc; 146 147 EFSYS_ASSERT(emip->emi_port > 0); /* MCDI port number is one-based */ 148 port_mask = MCDI_MON_PORT_MASK(emip); 149 150 sensor = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_MONITOR); 151 state = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_STATE); 152 value = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_VALUE); 153 154 /* Hardware must support this MCDI sensor */ 155 EFSYS_ASSERT3U(sensor, <, 156 (8 * enp->en_nic_cfg.enc_mcdi_sensor_mask_size)); 157 EFSYS_ASSERT((sensor % (MC_CMD_SENSOR_PAGE0_NEXT + 1)) != 158 MC_CMD_SENSOR_PAGE0_NEXT); 159 EFSYS_ASSERT(enp->en_nic_cfg.enc_mcdi_sensor_maskp != NULL); 160 EFSYS_ASSERT((enp->en_nic_cfg.enc_mcdi_sensor_maskp[ 161 sensor / (MC_CMD_SENSOR_PAGE0_NEXT + 1)] & 162 (1U << (sensor % (MC_CMD_SENSOR_PAGE0_NEXT + 1)))) != 0); 163 164 /* And we need to understand it, to get port-map */ 165 if (!efx_mon_mcdi_to_efx_stat(sensor, &id)) { 166 rc = ENOTSUP; 167 goto fail1; 168 } 169 if (!(efx_mon_get_stat_portmap(id, &sensor_port_mask) && 170 (port_mask && sensor_port_mask))) { 171 return (ENODEV); 172 } 173 EFSYS_ASSERT(id < EFX_MON_NSTATS); 174 175 *idp = id; 176 valuep->emsv_value = value; 177 valuep->emsv_state = state; 178 179 return (0); 180 181 fail1: 182 EFSYS_PROBE1(fail1, efx_rc_t, rc); 183 184 return (rc); 185 } 186 187 188 static __checkReturn efx_rc_t 189 efx_mcdi_read_sensors( 190 __in efx_nic_t *enp, 191 __in efsys_mem_t *esmp, 192 __in uint32_t size) 193 { 194 efx_mcdi_req_t req; 195 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_READ_SENSORS_EXT_IN_LEN, 196 MC_CMD_READ_SENSORS_EXT_OUT_LEN); 197 uint32_t addr_lo, addr_hi; 198 efx_rc_t rc; 199 200 if (EFSYS_MEM_SIZE(esmp) < size) { 201 rc = EINVAL; 202 goto fail1; 203 } 204 205 req.emr_cmd = MC_CMD_READ_SENSORS; 206 req.emr_in_buf = payload; 207 req.emr_in_length = MC_CMD_READ_SENSORS_EXT_IN_LEN; 208 req.emr_out_buf = payload; 209 req.emr_out_length = MC_CMD_READ_SENSORS_EXT_OUT_LEN; 210 211 addr_lo = (uint32_t)(EFSYS_MEM_ADDR(esmp) & 0xffffffff); 212 addr_hi = (uint32_t)(EFSYS_MEM_ADDR(esmp) >> 32); 213 214 MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_DMA_ADDR_LO, addr_lo); 215 MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_DMA_ADDR_HI, addr_hi); 216 MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_LENGTH, size); 217 218 efx_mcdi_execute(enp, &req); 219 220 return (req.emr_rc); 221 222 fail1: 223 EFSYS_PROBE1(fail1, efx_rc_t, rc); 224 225 return (rc); 226 } 227 228 static __checkReturn efx_rc_t 229 efx_mcdi_sensor_info_npages( 230 __in efx_nic_t *enp, 231 __out uint32_t *npagesp) 232 { 233 efx_mcdi_req_t req; 234 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN, 235 MC_CMD_SENSOR_INFO_OUT_LENMAX); 236 int page; 237 efx_rc_t rc; 238 239 EFSYS_ASSERT(npagesp != NULL); 240 241 page = 0; 242 do { 243 (void) memset(payload, 0, sizeof (payload)); 244 req.emr_cmd = MC_CMD_SENSOR_INFO; 245 req.emr_in_buf = payload; 246 req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN; 247 req.emr_out_buf = payload; 248 req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX; 249 250 MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page++); 251 252 efx_mcdi_execute_quiet(enp, &req); 253 254 if (req.emr_rc != 0) { 255 rc = req.emr_rc; 256 goto fail1; 257 } 258 } while (MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK) & 259 (1U << MC_CMD_SENSOR_PAGE0_NEXT)); 260 261 *npagesp = page; 262 263 return (0); 264 265 fail1: 266 EFSYS_PROBE1(fail1, efx_rc_t, rc); 267 268 return (rc); 269 } 270 271 static __checkReturn efx_rc_t 272 efx_mcdi_sensor_info( 273 __in efx_nic_t *enp, 274 __out_ecount(npages) uint32_t *sensor_maskp, 275 __in size_t npages) 276 { 277 efx_mcdi_req_t req; 278 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN, 279 MC_CMD_SENSOR_INFO_OUT_LENMAX); 280 uint32_t page; 281 efx_rc_t rc; 282 283 EFSYS_ASSERT(sensor_maskp != NULL); 284 285 if (npages < 1) { 286 rc = EINVAL; 287 goto fail1; 288 } 289 290 for (page = 0; page < npages; page++) { 291 uint32_t mask; 292 293 (void) memset(payload, 0, sizeof (payload)); 294 req.emr_cmd = MC_CMD_SENSOR_INFO; 295 req.emr_in_buf = payload; 296 req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN; 297 req.emr_out_buf = payload; 298 req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX; 299 300 MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page); 301 302 efx_mcdi_execute(enp, &req); 303 304 if (req.emr_rc != 0) { 305 rc = req.emr_rc; 306 goto fail2; 307 } 308 309 mask = MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK); 310 311 if ((page != (npages - 1)) && 312 ((mask & (1U << MC_CMD_SENSOR_PAGE0_NEXT)) == 0)) { 313 rc = EINVAL; 314 goto fail3; 315 } 316 sensor_maskp[page] = mask; 317 } 318 319 if (sensor_maskp[npages - 1] & (1U << MC_CMD_SENSOR_PAGE0_NEXT)) { 320 rc = EINVAL; 321 goto fail4; 322 } 323 324 return (0); 325 326 fail4: 327 EFSYS_PROBE(fail4); 328 fail3: 329 EFSYS_PROBE(fail3); 330 fail2: 331 EFSYS_PROBE(fail2); 332 fail1: 333 EFSYS_PROBE1(fail1, efx_rc_t, rc); 334 335 return (rc); 336 } 337 338 static __checkReturn efx_rc_t 339 efx_mcdi_sensor_info_page( 340 __in efx_nic_t *enp, 341 __in uint32_t page, 342 __out uint32_t *mask_part, 343 __out_ecount((sizeof (*mask_part) * 8) - 1) 344 efx_mon_stat_limits_t *limits) 345 { 346 efx_mcdi_req_t req; 347 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN, 348 MC_CMD_SENSOR_INFO_OUT_LENMAX); 349 efx_rc_t rc; 350 uint32_t mask_copy; 351 efx_dword_t *maskp; 352 efx_qword_t *limit_info; 353 354 EFSYS_ASSERT(mask_part != NULL); 355 EFSYS_ASSERT(limits != NULL); 356 357 memset(limits, 0, 358 ((sizeof (*mask_part) * 8) - 1) * sizeof (efx_mon_stat_limits_t)); 359 360 req.emr_cmd = MC_CMD_SENSOR_INFO; 361 req.emr_in_buf = payload; 362 req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN; 363 req.emr_out_buf = payload; 364 req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX; 365 366 MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page); 367 368 efx_mcdi_execute(enp, &req); 369 370 rc = req.emr_rc; 371 372 if (rc != 0) 373 goto fail1; 374 375 EFSYS_ASSERT(sizeof (*limit_info) == 376 MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_LEN); 377 maskp = MCDI_OUT2(req, efx_dword_t, SENSOR_INFO_OUT_MASK); 378 limit_info = (efx_qword_t *)(maskp + 1); 379 380 *mask_part = maskp->ed_u32[0]; 381 mask_copy = *mask_part; 382 383 /* Copy an entry for all but the highest bit set. */ 384 while (mask_copy) { 385 386 if (mask_copy == (1U << MC_CMD_SENSOR_PAGE0_NEXT)) { 387 /* Only next page bit set. */ 388 mask_copy = 0; 389 } else { 390 /* Clear lowest bit */ 391 mask_copy = mask_copy & ~(mask_copy ^ (mask_copy - 1)); 392 /* And copy out limit entry into buffer */ 393 limits->emlv_warning_min = EFX_QWORD_FIELD(*limit_info, 394 MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1); 395 396 limits->emlv_warning_max = EFX_QWORD_FIELD(*limit_info, 397 MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1); 398 399 limits->emlv_fatal_min = EFX_QWORD_FIELD(*limit_info, 400 MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2); 401 402 limits->emlv_fatal_max = EFX_QWORD_FIELD(*limit_info, 403 MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2); 404 405 limits++; 406 limit_info++; 407 } 408 } 409 410 return (rc); 411 412 fail1: 413 EFSYS_PROBE1(fail1, efx_rc_t, rc); 414 415 return (rc); 416 } 417 418 __checkReturn efx_rc_t 419 mcdi_mon_stats_update( 420 __in efx_nic_t *enp, 421 __in efsys_mem_t *esmp, 422 __inout_ecount(EFX_MON_NSTATS) efx_mon_stat_value_t *values) 423 { 424 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 425 uint32_t size = encp->enc_mon_stat_dma_buf_size; 426 efx_rc_t rc; 427 428 if ((rc = efx_mcdi_read_sensors(enp, esmp, size)) != 0) 429 goto fail1; 430 431 EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, size); 432 433 mcdi_mon_decode_stats(enp, 434 encp->enc_mcdi_sensor_maskp, 435 encp->enc_mcdi_sensor_mask_size, 436 esmp, NULL, values); 437 438 return (0); 439 440 fail1: 441 EFSYS_PROBE1(fail1, efx_rc_t, rc); 442 443 return (rc); 444 } 445 446 static void 447 lowest_set_bit( 448 __in uint32_t input_mask, 449 __out uint32_t *lowest_bit_mask, 450 __out uint32_t *lowest_bit_num 451 ) 452 { 453 uint32_t x; 454 uint32_t set_bit, bit_index; 455 456 x = (input_mask ^ (input_mask - 1)); 457 set_bit = (x + 1) >> 1; 458 if (!set_bit) 459 set_bit = (1U << 31U); 460 461 bit_index = 0; 462 if (set_bit & 0xFFFF0000) 463 bit_index += 16; 464 if (set_bit & 0xFF00FF00) 465 bit_index += 8; 466 if (set_bit & 0xF0F0F0F0) 467 bit_index += 4; 468 if (set_bit & 0xCCCCCCCC) 469 bit_index += 2; 470 if (set_bit & 0xAAAAAAAA) 471 bit_index += 1; 472 473 *lowest_bit_mask = set_bit; 474 *lowest_bit_num = bit_index; 475 } 476 477 __checkReturn efx_rc_t 478 mcdi_mon_limits_update( 479 __in efx_nic_t *enp, 480 __inout_ecount(EFX_MON_NSTATS) efx_mon_stat_limits_t *values) 481 { 482 efx_rc_t rc; 483 uint32_t page; 484 uint32_t page_mask; 485 uint32_t limit_index; 486 efx_mon_stat_limits_t limits[sizeof (page_mask) * 8]; 487 efx_mon_stat_t stat; 488 489 page = 0; 490 page--; 491 do { 492 page++; 493 494 rc = efx_mcdi_sensor_info_page(enp, page, &page_mask, limits); 495 if (rc != 0) 496 goto fail1; 497 498 limit_index = 0; 499 while (page_mask) { 500 uint32_t set_bit; 501 uint32_t page_index; 502 uint32_t mcdi_index; 503 504 if (page_mask == (1U << MC_CMD_SENSOR_PAGE0_NEXT)) 505 break; 506 507 lowest_set_bit(page_mask, &set_bit, &page_index); 508 page_mask = page_mask & ~set_bit; 509 510 mcdi_index = 511 page_index + (sizeof (page_mask) * 8 * page); 512 513 /* 514 * This can fail if MCDI reports newer stats than the 515 * drivers understand, or the bit is the next page bit. 516 * 517 * Driver needs to be tolerant of this. 518 */ 519 if (!efx_mon_mcdi_to_efx_stat(mcdi_index, &stat)) 520 continue; 521 522 values[stat] = limits[limit_index]; 523 limit_index++; 524 } 525 526 } while (page_mask & (1U << MC_CMD_SENSOR_PAGE0_NEXT)); 527 528 return (rc); 529 530 fail1: 531 EFSYS_PROBE1(fail1, efx_rc_t, rc); 532 533 return (rc); 534 } 535 536 __checkReturn efx_rc_t 537 mcdi_mon_cfg_build( 538 __in efx_nic_t *enp) 539 { 540 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 541 uint32_t npages; 542 efx_rc_t rc; 543 544 switch (enp->en_family) { 545 #if EFSYS_OPT_SIENA 546 case EFX_FAMILY_SIENA: 547 encp->enc_mon_type = EFX_MON_SFC90X0; 548 break; 549 #endif 550 #if EFSYS_OPT_HUNTINGTON 551 case EFX_FAMILY_HUNTINGTON: 552 encp->enc_mon_type = EFX_MON_SFC91X0; 553 break; 554 #endif 555 #if EFSYS_OPT_MEDFORD 556 case EFX_FAMILY_MEDFORD: 557 encp->enc_mon_type = EFX_MON_SFC92X0; 558 break; 559 #endif 560 #if EFSYS_OPT_MEDFORD2 561 case EFX_FAMILY_MEDFORD2: 562 encp->enc_mon_type = EFX_MON_SFC92X0; 563 break; 564 #endif 565 default: 566 rc = EINVAL; 567 goto fail1; 568 } 569 570 /* Get mc sensor mask size */ 571 npages = 0; 572 if ((rc = efx_mcdi_sensor_info_npages(enp, &npages)) != 0) 573 goto fail2; 574 575 encp->enc_mon_stat_dma_buf_size = npages * EFX_MON_STATS_PAGE_SIZE; 576 encp->enc_mcdi_sensor_mask_size = npages * sizeof (uint32_t); 577 578 /* Allocate mc sensor mask */ 579 EFSYS_KMEM_ALLOC(enp->en_esip, 580 encp->enc_mcdi_sensor_mask_size, 581 encp->enc_mcdi_sensor_maskp); 582 583 if (encp->enc_mcdi_sensor_maskp == NULL) { 584 rc = ENOMEM; 585 goto fail3; 586 } 587 588 /* Read mc sensor mask */ 589 if ((rc = efx_mcdi_sensor_info(enp, 590 encp->enc_mcdi_sensor_maskp, 591 npages)) != 0) 592 goto fail4; 593 594 /* Build monitor statistics mask */ 595 mcdi_mon_decode_stats(enp, 596 encp->enc_mcdi_sensor_maskp, 597 encp->enc_mcdi_sensor_mask_size, 598 NULL, encp->enc_mon_stat_mask, NULL); 599 600 return (0); 601 602 fail4: 603 EFSYS_PROBE(fail4); 604 EFSYS_KMEM_FREE(enp->en_esip, 605 encp->enc_mcdi_sensor_mask_size, 606 encp->enc_mcdi_sensor_maskp); 607 608 fail3: 609 EFSYS_PROBE(fail3); 610 611 fail2: 612 EFSYS_PROBE(fail2); 613 614 fail1: 615 EFSYS_PROBE1(fail1, efx_rc_t, rc); 616 617 return (rc); 618 } 619 620 void 621 mcdi_mon_cfg_free( 622 __in efx_nic_t *enp) 623 { 624 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 625 626 if (encp->enc_mcdi_sensor_maskp != NULL) { 627 EFSYS_KMEM_FREE(enp->en_esip, 628 encp->enc_mcdi_sensor_mask_size, 629 encp->enc_mcdi_sensor_maskp); 630 } 631 } 632 633 634 #endif /* EFSYS_OPT_MON_STATS */ 635 636 #endif /* EFSYS_OPT_MON_MCDI */ 637