xref: /freebsd/sys/dev/sfxge/common/mcdi_mon.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
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
mcdi_mon_decode_stats(__in efx_nic_t * enp,__in_bcount (sensor_mask_size)uint32_t * sensor_mask,__in size_t sensor_mask_size,__in_opt efsys_mem_t * esmp,__out_bcount_opt (sensor_mask_size)uint32_t * stat_maskp,__inout_ecount_opt (EFX_MON_NSTATS)efx_mon_stat_value_t * stat)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
mcdi_mon_ev(__in efx_nic_t * enp,__in efx_qword_t * eqp,__out efx_mon_stat_t * idp,__out efx_mon_stat_value_t * valuep)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
efx_mcdi_read_sensors(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__in uint32_t size)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
efx_mcdi_sensor_info_npages(__in efx_nic_t * enp,__out uint32_t * npagesp)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
efx_mcdi_sensor_info(__in efx_nic_t * enp,__out_ecount (npages)uint32_t * sensor_maskp,__in size_t npages)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
mcdi_mon_stats_update(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__inout_ecount (EFX_MON_NSTATS)efx_mon_stat_value_t * values)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
lowest_set_bit(__in uint32_t input_mask,__out uint32_t * lowest_bit_mask,__out uint32_t * lowest_bit_num)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
mcdi_mon_limits_update(__in efx_nic_t * enp,__inout_ecount (EFX_MON_NSTATS)efx_mon_stat_limits_t * values)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
mcdi_mon_cfg_build(__in efx_nic_t * enp)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
mcdi_mon_cfg_free(__in efx_nic_t * enp)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