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 */
Cache object: c7b0c9537cce9f65efb2540e367b5f94
|