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/cxgbe/common/t4vf_hw.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) 2016 Chelsio 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
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include "common.h"
   31 #include "t4_regs.h"
   32 #include "t4_regs_values.h"
   33 
   34 #undef msleep
   35 #define msleep(x) do { \
   36         if (cold) \
   37                 DELAY((x) * 1000); \
   38         else \
   39                 pause("t4hw", (x) * hz / 1000); \
   40 } while (0)
   41 
   42 /*
   43  * Wait for the device to become ready (signified by our "who am I" register
   44  * returning a value other than all 1's).  Return an error if it doesn't
   45  * become ready ...
   46  */
   47 int t4vf_wait_dev_ready(struct adapter *adapter)
   48 {
   49         const u32 whoami = VF_PL_REG(A_PL_VF_WHOAMI);
   50         const u32 notready1 = 0xffffffff;
   51         const u32 notready2 = 0xeeeeeeee;
   52         u32 val;
   53 
   54         val = t4_read_reg(adapter, whoami);
   55         if (val != notready1 && val != notready2)
   56                 return 0;
   57         msleep(500);
   58         val = t4_read_reg(adapter, whoami);
   59         if (val != notready1 && val != notready2)
   60                 return 0;
   61         else
   62                 return -EIO;
   63 }
   64 
   65 
   66 /**
   67  *      t4vf_fw_reset - issue a reset to FW
   68  *      @adapter: the adapter
   69  *
   70  *      Issues a reset command to FW.  For a Physical Function this would
   71  *      result in the Firmware reseting all of its state.  For a Virtual
   72  *      Function this just resets the state associated with the VF.
   73  */
   74 int t4vf_fw_reset(struct adapter *adapter)
   75 {
   76         struct fw_reset_cmd cmd;
   77 
   78         memset(&cmd, 0, sizeof(cmd));
   79         cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_RESET_CMD) |
   80                                       F_FW_CMD_WRITE);
   81         cmd.retval_len16 = cpu_to_be32(V_FW_CMD_LEN16(FW_LEN16(cmd)));
   82         return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL);
   83 }
   84 
   85 /**
   86  *      t4vf_get_sge_params - retrieve adapter Scatter gather Engine parameters
   87  *      @adapter: the adapter
   88  *
   89  *      Retrieves various core SGE parameters in the form of hardware SGE
   90  *      register values.  The caller is responsible for decoding these as
   91  *      needed.  The SGE parameters are stored in @adapter->params.sge.
   92  */
   93 int t4vf_get_sge_params(struct adapter *adapter)
   94 {
   95         struct sge_params *sp = &adapter->params.sge;
   96         u32 params[7], vals[7];
   97         u32 whoami;
   98         unsigned int pf, s_hps;
   99         int i, v;
  100 
  101         params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
  102                      V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL));
  103         params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
  104                      V_FW_PARAMS_PARAM_XYZ(A_SGE_HOST_PAGE_SIZE));
  105         params[2] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
  106                      V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_0_AND_1));
  107         params[3] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
  108                      V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_2_AND_3));
  109         params[4] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
  110                      V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_4_AND_5));
  111         params[5] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
  112                      V_FW_PARAMS_PARAM_XYZ(A_SGE_CONM_CTRL));
  113         params[6] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
  114                      V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_RX_THRESHOLD));
  115         v = t4vf_query_params(adapter, 7, params, vals);
  116         if (v != FW_SUCCESS)
  117                 return v;
  118 
  119         sp->sge_control = vals[0];
  120         sp->counter_val[0] = G_THRESHOLD_0(vals[6]);
  121         sp->counter_val[1] = G_THRESHOLD_1(vals[6]);
  122         sp->counter_val[2] = G_THRESHOLD_2(vals[6]);
  123         sp->counter_val[3] = G_THRESHOLD_3(vals[6]);
  124         sp->timer_val[0] = core_ticks_to_us(adapter, G_TIMERVALUE0(vals[2]));
  125         sp->timer_val[1] = core_ticks_to_us(adapter, G_TIMERVALUE1(vals[2]));
  126         sp->timer_val[2] = core_ticks_to_us(adapter, G_TIMERVALUE2(vals[3]));
  127         sp->timer_val[3] = core_ticks_to_us(adapter, G_TIMERVALUE3(vals[3]));
  128         sp->timer_val[4] = core_ticks_to_us(adapter, G_TIMERVALUE4(vals[4]));
  129         sp->timer_val[5] = core_ticks_to_us(adapter, G_TIMERVALUE5(vals[4]));
  130 
  131         sp->fl_starve_threshold = G_EGRTHRESHOLD(vals[5]) * 2 + 1;
  132         if (is_t4(adapter))
  133                 sp->fl_starve_threshold2 = sp->fl_starve_threshold;
  134         else if (is_t5(adapter))
  135                 sp->fl_starve_threshold2 = G_EGRTHRESHOLDPACKING(vals[5]) * 2 + 1;
  136         else
  137                 sp->fl_starve_threshold2 = G_T6_EGRTHRESHOLDPACKING(vals[5]) * 2 + 1;
  138 
  139         /*
  140          * We need the Queues/Page and Host Page Size for our VF.
  141          * This is based on the PF from which we're instantiated.
  142          */
  143         whoami = t4_read_reg(adapter, VF_PL_REG(A_PL_VF_WHOAMI));
  144         pf = G_SOURCEPF(whoami);
  145 
  146         s_hps = (S_HOSTPAGESIZEPF0 +
  147             (S_HOSTPAGESIZEPF1 - S_HOSTPAGESIZEPF0) * pf);
  148         sp->page_shift = ((vals[1] >> s_hps) & M_HOSTPAGESIZEPF0) + 10;
  149 
  150         for (i = 0; i < SGE_FLBUF_SIZES; i++) {
  151                 params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
  152                     V_FW_PARAMS_PARAM_XYZ(A_SGE_FL_BUFFER_SIZE0 + (4 * i)));
  153                 v = t4vf_query_params(adapter, 1, params, vals);
  154                 if (v != FW_SUCCESS)
  155                         return v;
  156 
  157                 sp->sge_fl_buffer_size[i] = vals[0];
  158         }
  159 
  160         /*
  161          * T4 uses a single control field to specify both the PCIe Padding and
  162          * Packing Boundary.  T5 introduced the ability to specify these
  163          * separately with the Padding Boundary in SGE_CONTROL and and Packing
  164          * Boundary in SGE_CONTROL2.  So for T5 and later we need to grab
  165          * SGE_CONTROL in order to determine how ingress packet data will be
  166          * laid out in Packed Buffer Mode.  Unfortunately, older versions of
  167          * the firmware won't let us retrieve SGE_CONTROL2 so if we get a
  168          * failure grabbing it we throw an error since we can't figure out the
  169          * right value.
  170          */
  171         sp->spg_len = sp->sge_control & F_EGRSTATUSPAGESIZE ? 128 : 64;
  172         sp->fl_pktshift = G_PKTSHIFT(sp->sge_control);
  173         if (chip_id(adapter) <= CHELSIO_T5) {
  174                 sp->pad_boundary = 1 << (G_INGPADBOUNDARY(sp->sge_control) +
  175                     X_INGPADBOUNDARY_SHIFT);
  176         } else {
  177                 sp->pad_boundary = 1 << (G_INGPADBOUNDARY(sp->sge_control) +
  178                     X_T6_INGPADBOUNDARY_SHIFT);
  179         }
  180         if (is_t4(adapter))
  181                 sp->pack_boundary = sp->pad_boundary;
  182         else {
  183                 params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
  184                              V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL2));
  185                 v = t4vf_query_params(adapter, 1, params, vals);
  186                 if (v != FW_SUCCESS) {
  187                         CH_ERR(adapter, "Unable to get SGE Control2; "
  188                                "probably old firmware.\n");
  189                         return v;
  190                 }
  191                 if (G_INGPACKBOUNDARY(vals[0]) == 0)
  192                         sp->pack_boundary = 16;
  193                 else
  194                         sp->pack_boundary = 1 << (G_INGPACKBOUNDARY(vals[0]) +
  195                             5);
  196         }
  197 
  198         /*
  199          * For T5 and later we want to use the new BAR2 Doorbells.
  200          * Unfortunately, older firmware didn't allow the this register to be
  201          * read.
  202          */
  203         if (!is_t4(adapter)) {
  204                 unsigned int s_qpp;
  205 
  206                 params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
  207                              V_FW_PARAMS_PARAM_XYZ(A_SGE_EGRESS_QUEUES_PER_PAGE_VF));
  208                 params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
  209                              V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_QUEUES_PER_PAGE_VF));
  210                 v = t4vf_query_params(adapter, 2, params, vals);
  211                 if (v != FW_SUCCESS) {
  212                         CH_WARN(adapter, "Unable to get VF SGE Queues/Page; "
  213                                 "probably old firmware.\n");
  214                         return v;
  215                 }
  216 
  217                 s_qpp = (S_QUEUESPERPAGEPF0 +
  218                          (S_QUEUESPERPAGEPF1 - S_QUEUESPERPAGEPF0) * pf);
  219                 sp->eq_s_qpp = ((vals[0] >> s_qpp) & M_QUEUESPERPAGEPF0);
  220                 sp->iq_s_qpp = ((vals[1] >> s_qpp) & M_QUEUESPERPAGEPF0);
  221         }
  222 
  223         return 0;
  224 }
  225 
  226 /**
  227  *      t4vf_get_rss_glb_config - retrieve adapter RSS Global Configuration
  228  *      @adapter: the adapter
  229  *
  230  *      Retrieves global RSS mode and parameters with which we have to live
  231  *      and stores them in the @adapter's RSS parameters.
  232  */
  233 int t4vf_get_rss_glb_config(struct adapter *adapter)
  234 {
  235         struct rss_params *rss = &adapter->params.rss;
  236         struct fw_rss_glb_config_cmd cmd, rpl;
  237         int v;
  238 
  239         /*
  240          * Execute an RSS Global Configuration read command to retrieve
  241          * our RSS configuration.
  242          */
  243         memset(&cmd, 0, sizeof(cmd));
  244         cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) |
  245                                       F_FW_CMD_REQUEST |
  246                                       F_FW_CMD_READ);
  247         cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
  248         v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl);
  249         if (v != FW_SUCCESS)
  250                 return v;
  251 
  252         /*
  253          * Transate the big-endian RSS Global Configuration into our
  254          * cpu-endian format based on the RSS mode.  We also do first level
  255          * filtering at this point to weed out modes which don't support
  256          * VF Drivers ...
  257          */
  258         rss->mode = G_FW_RSS_GLB_CONFIG_CMD_MODE(
  259                         be32_to_cpu(rpl.u.manual.mode_pkd));
  260         switch (rss->mode) {
  261         case FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL: {
  262                 u32 word = be32_to_cpu(
  263                                 rpl.u.basicvirtual.synmapen_to_hashtoeplitz);
  264 
  265                 rss->u.basicvirtual.synmapen =
  266                         ((word & F_FW_RSS_GLB_CONFIG_CMD_SYNMAPEN) != 0);
  267                 rss->u.basicvirtual.syn4tupenipv6 =
  268                         ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6) != 0);
  269                 rss->u.basicvirtual.syn2tupenipv6 =
  270                         ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6) != 0);
  271                 rss->u.basicvirtual.syn4tupenipv4 =
  272                         ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4) != 0);
  273                 rss->u.basicvirtual.syn2tupenipv4 =
  274                         ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4) != 0);
  275 
  276                 rss->u.basicvirtual.ofdmapen =
  277                         ((word & F_FW_RSS_GLB_CONFIG_CMD_OFDMAPEN) != 0);
  278 
  279                 rss->u.basicvirtual.tnlmapen =
  280                         ((word & F_FW_RSS_GLB_CONFIG_CMD_TNLMAPEN) != 0);
  281                 rss->u.basicvirtual.tnlalllookup =
  282                         ((word  & F_FW_RSS_GLB_CONFIG_CMD_TNLALLLKP) != 0);
  283 
  284                 rss->u.basicvirtual.hashtoeplitz =
  285                         ((word & F_FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ) != 0);
  286 
  287                 /* we need at least Tunnel Map Enable to be set */
  288                 if (!rss->u.basicvirtual.tnlmapen)
  289                         return -EINVAL;
  290                 break;
  291         }
  292 
  293         default:
  294                 /* all unknown/unsupported RSS modes result in an error */
  295                 return -EINVAL;
  296         }
  297 
  298         return 0;
  299 }
  300 
  301 /**
  302  *      t4vf_get_vfres - retrieve VF resource limits
  303  *      @adapter: the adapter
  304  *
  305  *      Retrieves configured resource limits and capabilities for a virtual
  306  *      function.  The results are stored in @adapter->vfres.
  307  */
  308 int t4vf_get_vfres(struct adapter *adapter)
  309 {
  310         struct vf_resources *vfres = &adapter->params.vfres;
  311         struct fw_pfvf_cmd cmd, rpl;
  312         int v;
  313         u32 word;
  314 
  315         /*
  316          * Execute PFVF Read command to get VF resource limits; bail out early
  317          * with error on command failure.
  318          */
  319         memset(&cmd, 0, sizeof(cmd));
  320         cmd.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PFVF_CMD) |
  321                                     F_FW_CMD_REQUEST |
  322                                     F_FW_CMD_READ);
  323         cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
  324         v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl);
  325         if (v != FW_SUCCESS)
  326                 return v;
  327 
  328         /*
  329          * Extract VF resource limits and return success.
  330          */
  331         word = be32_to_cpu(rpl.niqflint_niq);
  332         vfres->niqflint = G_FW_PFVF_CMD_NIQFLINT(word);
  333         vfres->niq = G_FW_PFVF_CMD_NIQ(word);
  334 
  335         word = be32_to_cpu(rpl.type_to_neq);
  336         vfres->neq = G_FW_PFVF_CMD_NEQ(word);
  337         vfres->pmask = G_FW_PFVF_CMD_PMASK(word);
  338 
  339         word = be32_to_cpu(rpl.tc_to_nexactf);
  340         vfres->tc = G_FW_PFVF_CMD_TC(word);
  341         vfres->nvi = G_FW_PFVF_CMD_NVI(word);
  342         vfres->nexactf = G_FW_PFVF_CMD_NEXACTF(word);
  343 
  344         word = be32_to_cpu(rpl.r_caps_to_nethctrl);
  345         vfres->r_caps = G_FW_PFVF_CMD_R_CAPS(word);
  346         vfres->wx_caps = G_FW_PFVF_CMD_WX_CAPS(word);
  347         vfres->nethctrl = G_FW_PFVF_CMD_NETHCTRL(word);
  348 
  349         return 0;
  350 }
  351 
  352 /**
  353  */
  354 int t4vf_prep_adapter(struct adapter *adapter)
  355 {
  356         int err;
  357 
  358         /*
  359          * Wait for the device to become ready before proceeding ...
  360          */
  361         err = t4vf_wait_dev_ready(adapter);
  362         if (err)
  363                 return err;
  364 
  365         adapter->params.chipid = pci_get_device(adapter->dev) >> 12;
  366         if (adapter->params.chipid >= 0xa) {
  367                 adapter->params.chipid -= (0xa - 0x4);
  368                 adapter->params.fpga = 1;
  369         }
  370         
  371         /*
  372          * Default port and clock for debugging in case we can't reach
  373          * firmware.
  374          */
  375         adapter->params.nports = 1;
  376         adapter->params.vfres.pmask = 1;
  377         adapter->params.vpd.cclk = 50000;
  378 
  379         adapter->chip_params = t4_get_chip_params(chip_id(adapter));
  380         if (adapter->chip_params == NULL)
  381                 return -EINVAL;
  382 
  383         return 0;
  384 }
  385 
  386 /*
  387  *      t4vf_get_vf_mac - Get the MAC address to be set to the VI of this VF.
  388  *      @adapter: The adapter
  389  *      @port: The port associated with vf
  390  *      @naddr: the number of ACL MAC addresses returned in addr
  391  *      @addr: Placeholder for MAC addresses
  392  *
  393  *      Find the MAC address to be set to the VF's VI. The requested MAC address
  394  *      is from the host OS via callback in the PF driver.
  395  */
  396 int t4vf_get_vf_mac(struct adapter *adapter, unsigned int port,
  397                     unsigned int *naddr, u8 *addr)
  398 {
  399         struct fw_acl_mac_cmd cmd;
  400         int ret;
  401 
  402         memset(&cmd, 0, sizeof(cmd));
  403         cmd.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_ACL_MAC_CMD) |
  404                               F_FW_CMD_REQUEST |
  405                               F_FW_CMD_READ);
  406         cmd.en_to_len16 = cpu_to_be32((unsigned int)FW_LEN16(cmd));
  407         ret = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &cmd);
  408         if (ret)
  409                 return ret;
  410 
  411         if (cmd.nmac < *naddr)
  412                 *naddr = cmd.nmac;
  413 
  414         switch (port) {
  415         case 3:
  416                 memcpy(addr, cmd.macaddr3, sizeof(cmd.macaddr3));
  417                 break;
  418         case 2:
  419                 memcpy(addr, cmd.macaddr2, sizeof(cmd.macaddr2));
  420                 break;
  421         case 1:
  422                 memcpy(addr, cmd.macaddr1, sizeof(cmd.macaddr1));
  423                 break;
  424         case 0:
  425                 memcpy(addr, cmd.macaddr0, sizeof(cmd.macaddr0));
  426                 break;
  427         }
  428 
  429         return ret;
  430 }

Cache object: a87c0f3ca6145c1ed9e6b480bd7d584d


[ 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.