The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sfxge/common/mcdi_mon.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.