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 static __checkReturn efx_rc_t 214 efx_mcdi_read_sensors( 215 __in efx_nic_t *enp, 216 __in efsys_mem_t *esmp, 217 __in uint32_t size) 218 { 219 efx_mcdi_req_t req; 220 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_READ_SENSORS_EXT_IN_LEN, 221 MC_CMD_READ_SENSORS_EXT_OUT_LEN); 222 uint32_t addr_lo, addr_hi; 223 efx_rc_t rc; 224 225 if (EFSYS_MEM_SIZE(esmp) < size) { 226 rc = EINVAL; 227 goto fail1; 228 } 229 230 req.emr_cmd = MC_CMD_READ_SENSORS; 231 req.emr_in_buf = payload; 232 req.emr_in_length = MC_CMD_READ_SENSORS_EXT_IN_LEN; 233 req.emr_out_buf = payload; 234 req.emr_out_length = MC_CMD_READ_SENSORS_EXT_OUT_LEN; 235 236 addr_lo = (uint32_t)(EFSYS_MEM_ADDR(esmp) & 0xffffffff); 237 addr_hi = (uint32_t)(EFSYS_MEM_ADDR(esmp) >> 32); 238 239 MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_DMA_ADDR_LO, addr_lo); 240 MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_DMA_ADDR_HI, addr_hi); 241 MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_LENGTH, size); 242 243 efx_mcdi_execute(enp, &req); 244 245 return (req.emr_rc); 246 247 fail1: 248 EFSYS_PROBE1(fail1, efx_rc_t, rc); 249 250 return (rc); 251 } 252 253 static __checkReturn efx_rc_t 254 efx_mcdi_sensor_info_npages( 255 __in efx_nic_t *enp, 256 __out uint32_t *npagesp) 257 { 258 efx_mcdi_req_t req; 259 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN, 260 MC_CMD_SENSOR_INFO_OUT_LENMAX); 261 int page; 262 efx_rc_t rc; 263 264 EFSYS_ASSERT(npagesp != NULL); 265 266 page = 0; 267 do { 268 (void) memset(payload, 0, sizeof (payload)); 269 req.emr_cmd = MC_CMD_SENSOR_INFO; 270 req.emr_in_buf = payload; 271 req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN; 272 req.emr_out_buf = payload; 273 req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX; 274 275 MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page++); 276 277 efx_mcdi_execute_quiet(enp, &req); 278 279 if (req.emr_rc != 0) { 280 rc = req.emr_rc; 281 goto fail1; 282 } 283 } while (MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK) & 284 (1U << MC_CMD_SENSOR_PAGE0_NEXT)); 285 286 *npagesp = page; 287 288 return (0); 289 290 fail1: 291 EFSYS_PROBE1(fail1, efx_rc_t, rc); 292 293 return (rc); 294 } 295 296 static __checkReturn efx_rc_t 297 efx_mcdi_sensor_info( 298 __in efx_nic_t *enp, 299 __out_ecount(npages) uint32_t *sensor_maskp, 300 __in size_t npages) 301 { 302 efx_mcdi_req_t req; 303 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN, 304 MC_CMD_SENSOR_INFO_OUT_LENMAX); 305 uint32_t page; 306 efx_rc_t rc; 307 308 EFSYS_ASSERT(sensor_maskp != NULL); 309 310 if (npages < 1) { 311 rc = EINVAL; 312 goto fail1; 313 } 314 315 for (page = 0; page < npages; page++) { 316 uint32_t mask; 317 318 (void) memset(payload, 0, sizeof (payload)); 319 req.emr_cmd = MC_CMD_SENSOR_INFO; 320 req.emr_in_buf = payload; 321 req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN; 322 req.emr_out_buf = payload; 323 req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX; 324 325 MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page); 326 327 efx_mcdi_execute(enp, &req); 328 329 if (req.emr_rc != 0) { 330 rc = req.emr_rc; 331 goto fail2; 332 } 333 334 mask = MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK); 335 336 if ((page != (npages - 1)) && 337 ((mask & (1U << MC_CMD_SENSOR_PAGE0_NEXT)) == 0)) { 338 rc = EINVAL; 339 goto fail3; 340 } 341 sensor_maskp[page] = mask; 342 } 343 344 if (sensor_maskp[npages - 1] & (1U << MC_CMD_SENSOR_PAGE0_NEXT)) { 345 rc = EINVAL; 346 goto fail4; 347 } 348 349 return (0); 350 351 fail4: 352 EFSYS_PROBE(fail4); 353 fail3: 354 EFSYS_PROBE(fail3); 355 fail2: 356 EFSYS_PROBE(fail2); 357 fail1: 358 EFSYS_PROBE1(fail1, efx_rc_t, rc); 359 360 return (rc); 361 } 362 363 static __checkReturn efx_rc_t 364 efx_mcdi_sensor_info_page( 365 __in efx_nic_t *enp, 366 __in uint32_t page, 367 __out uint32_t *mask_part, 368 __out_ecount((sizeof (*mask_part) * 8) - 1) 369 efx_mon_stat_limits_t *limits) 370 { 371 efx_mcdi_req_t req; 372 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN, 373 MC_CMD_SENSOR_INFO_OUT_LENMAX); 374 efx_rc_t rc; 375 uint32_t mask_copy; 376 efx_dword_t *maskp; 377 efx_qword_t *limit_info; 378 379 EFSYS_ASSERT(mask_part != NULL); 380 EFSYS_ASSERT(limits != NULL); 381 382 memset(limits, 0, 383 ((sizeof (*mask_part) * 8) - 1) * sizeof (efx_mon_stat_limits_t)); 384 385 req.emr_cmd = MC_CMD_SENSOR_INFO; 386 req.emr_in_buf = payload; 387 req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN; 388 req.emr_out_buf = payload; 389 req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX; 390 391 MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page); 392 393 efx_mcdi_execute(enp, &req); 394 395 rc = req.emr_rc; 396 397 if (rc != 0) 398 goto fail1; 399 400 EFSYS_ASSERT(sizeof (*limit_info) == 401 MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_LEN); 402 maskp = MCDI_OUT2(req, efx_dword_t, SENSOR_INFO_OUT_MASK); 403 limit_info = (efx_qword_t *)(maskp + 1); 404 405 *mask_part = maskp->ed_u32[0]; 406 mask_copy = *mask_part; 407 408 /* Copy an entry for all but the highest bit set. */ 409 while (mask_copy) { 410 if (mask_copy == (1U << MC_CMD_SENSOR_PAGE0_NEXT)) { 411 /* Only next page bit set. */ 412 mask_copy = 0; 413 } else { 414 /* Clear lowest bit */ 415 mask_copy = mask_copy & ~(mask_copy ^ (mask_copy - 1)); 416 /* And copy out limit entry into buffer */ 417 limits->emlv_warning_min = EFX_QWORD_FIELD(*limit_info, 418 MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1); 419 420 limits->emlv_warning_max = EFX_QWORD_FIELD(*limit_info, 421 MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1); 422 423 limits->emlv_fatal_min = EFX_QWORD_FIELD(*limit_info, 424 MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2); 425 426 limits->emlv_fatal_max = EFX_QWORD_FIELD(*limit_info, 427 MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2); 428 429 limits++; 430 limit_info++; 431 } 432 } 433 434 return (rc); 435 436 fail1: 437 EFSYS_PROBE1(fail1, efx_rc_t, rc); 438 439 return (rc); 440 } 441 442 __checkReturn efx_rc_t 443 mcdi_mon_stats_update( 444 __in efx_nic_t *enp, 445 __in efsys_mem_t *esmp, 446 __inout_ecount(EFX_MON_NSTATS) efx_mon_stat_value_t *values) 447 { 448 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 449 uint32_t size = encp->enc_mon_stat_dma_buf_size; 450 efx_rc_t rc; 451 452 if ((rc = efx_mcdi_read_sensors(enp, esmp, size)) != 0) 453 goto fail1; 454 455 EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, size); 456 457 mcdi_mon_decode_stats(enp, 458 encp->enc_mcdi_sensor_maskp, 459 encp->enc_mcdi_sensor_mask_size, 460 esmp, NULL, values); 461 462 return (0); 463 464 fail1: 465 EFSYS_PROBE1(fail1, efx_rc_t, rc); 466 467 return (rc); 468 } 469 470 static void 471 lowest_set_bit( 472 __in uint32_t input_mask, 473 __out uint32_t *lowest_bit_mask, 474 __out uint32_t *lowest_bit_num 475 ) 476 { 477 uint32_t x; 478 uint32_t set_bit, bit_index; 479 480 x = (input_mask ^ (input_mask - 1)); 481 set_bit = (x + 1) >> 1; 482 if (!set_bit) 483 set_bit = (1U << 31U); 484 485 bit_index = 0; 486 if (set_bit & 0xFFFF0000) 487 bit_index += 16; 488 if (set_bit & 0xFF00FF00) 489 bit_index += 8; 490 if (set_bit & 0xF0F0F0F0) 491 bit_index += 4; 492 if (set_bit & 0xCCCCCCCC) 493 bit_index += 2; 494 if (set_bit & 0xAAAAAAAA) 495 bit_index += 1; 496 497 *lowest_bit_mask = set_bit; 498 *lowest_bit_num = bit_index; 499 } 500 501 __checkReturn efx_rc_t 502 mcdi_mon_limits_update( 503 __in efx_nic_t *enp, 504 __inout_ecount(EFX_MON_NSTATS) efx_mon_stat_limits_t *values) 505 { 506 efx_rc_t rc; 507 uint32_t page; 508 uint32_t page_mask; 509 uint32_t limit_index; 510 efx_mon_stat_limits_t limits[sizeof (page_mask) * 8]; 511 efx_mon_stat_t stat; 512 513 page = 0; 514 page--; 515 do { 516 page++; 517 518 rc = efx_mcdi_sensor_info_page(enp, page, &page_mask, limits); 519 if (rc != 0) 520 goto fail1; 521 522 limit_index = 0; 523 while (page_mask) { 524 uint32_t set_bit; 525 uint32_t page_index; 526 uint32_t mcdi_index; 527 528 if (page_mask == (1U << MC_CMD_SENSOR_PAGE0_NEXT)) 529 break; 530 531 lowest_set_bit(page_mask, &set_bit, &page_index); 532 page_mask = page_mask & ~set_bit; 533 534 mcdi_index = 535 page_index + (sizeof (page_mask) * 8 * page); 536 537 /* 538 * This can fail if MCDI reports newer stats than the 539 * drivers understand, or the bit is the next page bit. 540 * 541 * Driver needs to be tolerant of this. 542 */ 543 if (!efx_mon_mcdi_to_efx_stat(mcdi_index, &stat)) 544 continue; 545 546 values[stat] = limits[limit_index]; 547 limit_index++; 548 } 549 550 } while (page_mask & (1U << MC_CMD_SENSOR_PAGE0_NEXT)); 551 552 return (rc); 553 554 fail1: 555 EFSYS_PROBE1(fail1, efx_rc_t, rc); 556 557 return (rc); 558 } 559 560 __checkReturn efx_rc_t 561 mcdi_mon_cfg_build( 562 __in efx_nic_t *enp) 563 { 564 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 565 uint32_t npages; 566 efx_rc_t rc; 567 568 switch (enp->en_family) { 569 #if EFSYS_OPT_SIENA 570 case EFX_FAMILY_SIENA: 571 encp->enc_mon_type = EFX_MON_SFC90X0; 572 break; 573 #endif 574 #if EFSYS_OPT_HUNTINGTON 575 case EFX_FAMILY_HUNTINGTON: 576 encp->enc_mon_type = EFX_MON_SFC91X0; 577 break; 578 #endif 579 #if EFSYS_OPT_MEDFORD 580 case EFX_FAMILY_MEDFORD: 581 encp->enc_mon_type = EFX_MON_SFC92X0; 582 break; 583 #endif 584 #if EFSYS_OPT_MEDFORD2 585 case EFX_FAMILY_MEDFORD2: 586 encp->enc_mon_type = EFX_MON_SFC92X0; 587 break; 588 #endif 589 default: 590 rc = EINVAL; 591 goto fail1; 592 } 593 594 /* Get mc sensor mask size */ 595 npages = 0; 596 if ((rc = efx_mcdi_sensor_info_npages(enp, &npages)) != 0) 597 goto fail2; 598 599 encp->enc_mon_stat_dma_buf_size = npages * EFX_MON_STATS_PAGE_SIZE; 600 encp->enc_mcdi_sensor_mask_size = npages * sizeof (uint32_t); 601 602 /* Allocate mc sensor mask */ 603 EFSYS_KMEM_ALLOC(enp->en_esip, 604 encp->enc_mcdi_sensor_mask_size, 605 encp->enc_mcdi_sensor_maskp); 606 607 if (encp->enc_mcdi_sensor_maskp == NULL) { 608 rc = ENOMEM; 609 goto fail3; 610 } 611 612 /* Read mc sensor mask */ 613 if ((rc = efx_mcdi_sensor_info(enp, 614 encp->enc_mcdi_sensor_maskp, 615 npages)) != 0) 616 goto fail4; 617 618 /* Build monitor statistics mask */ 619 mcdi_mon_decode_stats(enp, 620 encp->enc_mcdi_sensor_maskp, 621 encp->enc_mcdi_sensor_mask_size, 622 NULL, encp->enc_mon_stat_mask, NULL); 623 624 return (0); 625 626 fail4: 627 EFSYS_PROBE(fail4); 628 EFSYS_KMEM_FREE(enp->en_esip, 629 encp->enc_mcdi_sensor_mask_size, 630 encp->enc_mcdi_sensor_maskp); 631 632 fail3: 633 EFSYS_PROBE(fail3); 634 635 fail2: 636 EFSYS_PROBE(fail2); 637 638 fail1: 639 EFSYS_PROBE1(fail1, efx_rc_t, rc); 640 641 return (rc); 642 } 643 644 void 645 mcdi_mon_cfg_free( 646 __in efx_nic_t *enp) 647 { 648 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 649 650 if (encp->enc_mcdi_sensor_maskp != NULL) { 651 EFSYS_KMEM_FREE(enp->en_esip, 652 encp->enc_mcdi_sensor_mask_size, 653 encp->enc_mcdi_sensor_maskp); 654 } 655 } 656 657 #endif /* EFSYS_OPT_MON_STATS */ 658 659 #endif /* EFSYS_OPT_MON_MCDI */ 660