1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright (c) 2009-2018 Solarflare Communications Inc.
11 #if EFSYS_OPT_MON_MCDI
13 #if EFSYS_OPT_MON_STATS
15 /* Get port mask from one-based MCDI port number */
16 #define MCDI_MON_PORT_MASK(_emip) (1U << ((_emip)->emi_port - 1))
18 #define MCDI_STATIC_SENSOR_ASSERT(_field) \
19 EFX_STATIC_ASSERT(MC_CMD_SENSOR_STATE_ ## _field \
20 == EFX_MON_STAT_STATE_ ## _field)
23 mcdi_mon_decode_stats(
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)
31 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
32 efx_mon_stat_portmask_t port_mask;
35 uint32_t stat_mask[(EFX_MON_NSTATS + 31) / 32];
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);
46 sensor_max = 8 * sensor_mask_size;
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);
51 memset(stat_mask, 0, sizeof (stat_mask));
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
60 * sensor_mask may legitimately contain MCDI sensors that the driver
61 * does not understand.
63 for (sensor = 0; sensor < sensor_max; ++sensor) {
65 efx_mon_stat_portmask_t stat_portmask = 0;
67 efx_mon_stat_unit_t stat_unit;
69 if ((sensor % (MC_CMD_SENSOR_PAGE0_NEXT + 1)) ==
70 MC_CMD_SENSOR_PAGE0_NEXT) {
73 /* This sensor is one of the page boundary bits. */
76 if (~(sensor_mask[page]) & (1U << sensor))
78 /* This sensor not in DMA buffer */
82 * Valid stat in DMA buffer that we need to increment over, even
83 * if we couldn't look up the id
86 decode_ok = efx_mon_mcdi_to_efx_stat(sensor, &id);
88 decode_ok && efx_mon_get_stat_portmap(id, &stat_portmask);
90 if (!(decode_ok && (stat_portmask & port_mask)))
92 /* Either bad decode, or don't know what port stat is on */
94 EFSYS_ASSERT(id < EFX_MON_NSTATS);
97 * stat_mask is a bitmask indexed by EFX_MON_* monitor statistic
98 * identifiers from efx_mon_stat_t (without NEXT_PAGE bits).
100 * If there is an entry in the MCDI sensor to monitor statistic
101 * map then the sensor reading is used for the value of the
104 stat_mask[id / EFX_MON_MASK_ELEMENT_SIZE] |=
105 (1U << (id % EFX_MON_MASK_ELEMENT_SIZE));
107 if (stat != NULL && esmp != NULL && !EFSYS_MEM_IS_NULL(esmp)) {
110 /* Get MCDI sensor reading from DMA buffer */
111 EFSYS_MEM_READD(esmp, 4 * (idx - 1), &dword);
113 /* Update EFX monitor stat from MCDI sensor reading */
114 stat[id].emsv_value = (uint16_t)EFX_DWORD_FIELD(dword,
115 MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE);
117 stat[id].emsv_state = (uint16_t)EFX_DWORD_FIELD(dword,
118 MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE);
121 efx_mon_get_stat_unit(id, &stat_unit) ?
122 stat_unit : EFX_MON_STAT_UNIT_UNKNOWN;
126 if (stat_maskp != NULL) {
127 memcpy(stat_maskp, stat_mask, sizeof (stat_mask));
131 __checkReturn efx_rc_t
134 __in efx_qword_t *eqp,
135 __out efx_mon_stat_t *idp,
136 __out efx_mon_stat_value_t *valuep)
138 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
139 efx_mon_stat_portmask_t port_mask, sensor_port_mask;
146 EFSYS_ASSERT(emip->emi_port > 0); /* MCDI port number is one-based */
147 port_mask = MCDI_MON_PORT_MASK(emip);
149 sensor = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_MONITOR);
150 state = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_STATE);
151 value = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_VALUE);
153 /* Hardware must support this MCDI sensor */
154 EFSYS_ASSERT3U(sensor, <,
155 (8 * enp->en_nic_cfg.enc_mcdi_sensor_mask_size));
156 EFSYS_ASSERT((sensor % (MC_CMD_SENSOR_PAGE0_NEXT + 1)) !=
157 MC_CMD_SENSOR_PAGE0_NEXT);
158 EFSYS_ASSERT(enp->en_nic_cfg.enc_mcdi_sensor_maskp != NULL);
159 EFSYS_ASSERT((enp->en_nic_cfg.enc_mcdi_sensor_maskp[
160 sensor / (MC_CMD_SENSOR_PAGE0_NEXT + 1)] &
161 (1U << (sensor % (MC_CMD_SENSOR_PAGE0_NEXT + 1)))) != 0);
163 /* And we need to understand it, to get port-map */
164 if (!efx_mon_mcdi_to_efx_stat(sensor, &id)) {
168 if (!(efx_mon_get_stat_portmap(id, &sensor_port_mask) &&
169 (port_mask && sensor_port_mask))) {
172 EFSYS_ASSERT(id < EFX_MON_NSTATS);
175 valuep->emsv_value = value;
176 valuep->emsv_state = state;
181 EFSYS_PROBE1(fail1, efx_rc_t, rc);
187 static __checkReturn efx_rc_t
188 efx_mcdi_read_sensors(
190 __in efsys_mem_t *esmp,
194 uint8_t payload[MAX(MC_CMD_READ_SENSORS_EXT_IN_LEN,
195 MC_CMD_READ_SENSORS_EXT_OUT_LEN)];
196 uint32_t addr_lo, addr_hi;
198 req.emr_cmd = MC_CMD_READ_SENSORS;
199 req.emr_in_buf = payload;
200 req.emr_in_length = MC_CMD_READ_SENSORS_EXT_IN_LEN;
201 req.emr_out_buf = payload;
202 req.emr_out_length = MC_CMD_READ_SENSORS_EXT_OUT_LEN;
204 addr_lo = (uint32_t)(EFSYS_MEM_ADDR(esmp) & 0xffffffff);
205 addr_hi = (uint32_t)(EFSYS_MEM_ADDR(esmp) >> 32);
207 MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_DMA_ADDR_LO, addr_lo);
208 MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_DMA_ADDR_HI, addr_hi);
209 MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_LENGTH, size);
211 efx_mcdi_execute(enp, &req);
216 static __checkReturn efx_rc_t
217 efx_mcdi_sensor_info_npages(
219 __out uint32_t *npagesp)
222 uint8_t payload[MAX(MC_CMD_SENSOR_INFO_EXT_IN_LEN,
223 MC_CMD_SENSOR_INFO_OUT_LENMAX)];
227 EFSYS_ASSERT(npagesp != NULL);
231 (void) memset(payload, 0, sizeof (payload));
232 req.emr_cmd = MC_CMD_SENSOR_INFO;
233 req.emr_in_buf = payload;
234 req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN;
235 req.emr_out_buf = payload;
236 req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX;
238 MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page++);
240 efx_mcdi_execute_quiet(enp, &req);
242 if (req.emr_rc != 0) {
246 } while (MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK) &
247 (1U << MC_CMD_SENSOR_PAGE0_NEXT));
254 EFSYS_PROBE1(fail1, efx_rc_t, rc);
259 static __checkReturn efx_rc_t
260 efx_mcdi_sensor_info(
262 __out_ecount(npages) uint32_t *sensor_maskp,
266 uint8_t payload[MAX(MC_CMD_SENSOR_INFO_EXT_IN_LEN,
267 MC_CMD_SENSOR_INFO_OUT_LENMAX)];
271 EFSYS_ASSERT(sensor_maskp != NULL);
278 for (page = 0; page < npages; page++) {
281 (void) memset(payload, 0, sizeof (payload));
282 req.emr_cmd = MC_CMD_SENSOR_INFO;
283 req.emr_in_buf = payload;
284 req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN;
285 req.emr_out_buf = payload;
286 req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX;
288 MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page);
290 efx_mcdi_execute(enp, &req);
292 if (req.emr_rc != 0) {
297 mask = MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK);
299 if ((page != (npages - 1)) &&
300 ((mask & (1U << MC_CMD_SENSOR_PAGE0_NEXT)) == 0)) {
304 sensor_maskp[page] = mask;
307 if (sensor_maskp[npages - 1] & (1U << MC_CMD_SENSOR_PAGE0_NEXT)) {
321 EFSYS_PROBE1(fail1, efx_rc_t, rc);
326 __checkReturn efx_rc_t
327 mcdi_mon_stats_update(
329 __in efsys_mem_t *esmp,
330 __inout_ecount(EFX_MON_NSTATS) efx_mon_stat_value_t *values)
332 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
333 uint32_t size = encp->enc_mon_stat_dma_buf_size;
336 if ((rc = efx_mcdi_read_sensors(enp, esmp, size)) != 0)
339 EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, size);
341 mcdi_mon_decode_stats(enp,
342 encp->enc_mcdi_sensor_maskp,
343 encp->enc_mcdi_sensor_mask_size,
349 EFSYS_PROBE1(fail1, efx_rc_t, rc);
354 __checkReturn efx_rc_t
358 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
362 switch (enp->en_family) {
364 case EFX_FAMILY_SIENA:
365 encp->enc_mon_type = EFX_MON_SFC90X0;
368 #if EFSYS_OPT_HUNTINGTON
369 case EFX_FAMILY_HUNTINGTON:
370 encp->enc_mon_type = EFX_MON_SFC91X0;
373 #if EFSYS_OPT_MEDFORD
374 case EFX_FAMILY_MEDFORD:
375 encp->enc_mon_type = EFX_MON_SFC92X0;
378 #if EFSYS_OPT_MEDFORD2
379 case EFX_FAMILY_MEDFORD2:
380 encp->enc_mon_type = EFX_MON_SFC92X0;
388 /* Get mc sensor mask size */
390 if ((rc = efx_mcdi_sensor_info_npages(enp, &npages)) != 0)
393 encp->enc_mon_stat_dma_buf_size = npages * EFX_MON_STATS_PAGE_SIZE;
394 encp->enc_mcdi_sensor_mask_size = npages * sizeof (uint32_t);
396 /* Allocate mc sensor mask */
397 EFSYS_KMEM_ALLOC(enp->en_esip,
398 encp->enc_mcdi_sensor_mask_size,
399 encp->enc_mcdi_sensor_maskp);
401 if (encp->enc_mcdi_sensor_maskp == NULL) {
406 /* Read mc sensor mask */
407 if ((rc = efx_mcdi_sensor_info(enp,
408 encp->enc_mcdi_sensor_maskp,
412 /* Build monitor statistics mask */
413 mcdi_mon_decode_stats(enp,
414 encp->enc_mcdi_sensor_maskp,
415 encp->enc_mcdi_sensor_mask_size,
416 NULL, encp->enc_mon_stat_mask, NULL);
422 EFSYS_KMEM_FREE(enp->en_esip,
423 encp->enc_mcdi_sensor_mask_size,
424 encp->enc_mcdi_sensor_maskp);
433 EFSYS_PROBE1(fail1, efx_rc_t, rc);
442 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
444 if (encp->enc_mcdi_sensor_maskp != NULL) {
445 EFSYS_KMEM_FREE(enp->en_esip,
446 encp->enc_mcdi_sensor_mask_size,
447 encp->enc_mcdi_sensor_maskp);
452 #endif /* EFSYS_OPT_MON_STATS */
454 #endif /* EFSYS_OPT_MON_MCDI */