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