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