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