1305549Sjhb/*- 2305549Sjhb * Copyright (c) 2016 Chelsio Communications, Inc. 3305549Sjhb * All rights reserved. 4305549Sjhb * 5305549Sjhb * Redistribution and use in source and binary forms, with or without 6305549Sjhb * modification, are permitted provided that the following conditions 7305549Sjhb * are met: 8305549Sjhb * 1. Redistributions of source code must retain the above copyright 9305549Sjhb * notice, this list of conditions and the following disclaimer. 10305549Sjhb * 2. Redistributions in binary form must reproduce the above copyright 11305549Sjhb * notice, this list of conditions and the following disclaimer in the 12305549Sjhb * documentation and/or other materials provided with the distribution. 13305549Sjhb * 14305549Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15305549Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16305549Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17305549Sjhb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18305549Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19305549Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20305549Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21305549Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22305549Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23305549Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24305549Sjhb * SUCH DAMAGE. 25305549Sjhb */ 26305549Sjhb 27305549Sjhb#include <sys/cdefs.h> 28305549Sjhb__FBSDID("$FreeBSD: stable/10/sys/dev/cxgbe/common/t4vf_hw.c 309560 2016-12-05 20:43:25Z jhb $"); 29305549Sjhb 30305549Sjhb#include "common.h" 31305549Sjhb#include "t4_regs.h" 32309560Sjhb#include "t4_regs_values.h" 33305549Sjhb 34305549Sjhb#undef msleep 35305549Sjhb#define msleep(x) do { \ 36305549Sjhb if (cold) \ 37305549Sjhb DELAY((x) * 1000); \ 38305549Sjhb else \ 39305549Sjhb pause("t4hw", (x) * hz / 1000); \ 40305549Sjhb} while (0) 41305549Sjhb 42305549Sjhb/* 43305549Sjhb * Wait for the device to become ready (signified by our "who am I" register 44305549Sjhb * returning a value other than all 1's). Return an error if it doesn't 45305549Sjhb * become ready ... 46305549Sjhb */ 47305549Sjhbint t4vf_wait_dev_ready(struct adapter *adapter) 48305549Sjhb{ 49305549Sjhb const u32 whoami = VF_PL_REG(A_PL_VF_WHOAMI); 50305549Sjhb const u32 notready1 = 0xffffffff; 51305549Sjhb const u32 notready2 = 0xeeeeeeee; 52305549Sjhb u32 val; 53305549Sjhb 54305549Sjhb val = t4_read_reg(adapter, whoami); 55305549Sjhb if (val != notready1 && val != notready2) 56305549Sjhb return 0; 57305549Sjhb msleep(500); 58305549Sjhb val = t4_read_reg(adapter, whoami); 59305549Sjhb if (val != notready1 && val != notready2) 60305549Sjhb return 0; 61305549Sjhb else 62305549Sjhb return -EIO; 63305549Sjhb} 64305549Sjhb 65305549Sjhb 66305549Sjhb/** 67305549Sjhb * t4vf_fw_reset - issue a reset to FW 68305549Sjhb * @adapter: the adapter 69305549Sjhb * 70305549Sjhb * Issues a reset command to FW. For a Physical Function this would 71305549Sjhb * result in the Firmware reseting all of its state. For a Virtual 72305549Sjhb * Function this just resets the state associated with the VF. 73305549Sjhb */ 74305549Sjhbint t4vf_fw_reset(struct adapter *adapter) 75305549Sjhb{ 76305549Sjhb struct fw_reset_cmd cmd; 77305549Sjhb 78305549Sjhb memset(&cmd, 0, sizeof(cmd)); 79305549Sjhb cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_RESET_CMD) | 80305549Sjhb F_FW_CMD_WRITE); 81305549Sjhb cmd.retval_len16 = cpu_to_be32(V_FW_CMD_LEN16(FW_LEN16(cmd))); 82305549Sjhb return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL); 83305549Sjhb} 84305549Sjhb 85305549Sjhb/** 86305549Sjhb * t4vf_get_sge_params - retrieve adapter Scatter gather Engine parameters 87305549Sjhb * @adapter: the adapter 88305549Sjhb * 89305549Sjhb * Retrieves various core SGE parameters in the form of hardware SGE 90305549Sjhb * register values. The caller is responsible for decoding these as 91305549Sjhb * needed. The SGE parameters are stored in @adapter->params.sge. 92305549Sjhb */ 93305549Sjhbint t4vf_get_sge_params(struct adapter *adapter) 94305549Sjhb{ 95305549Sjhb struct sge_params *sp = &adapter->params.sge; 96305549Sjhb u32 params[7], vals[7]; 97305549Sjhb u32 whoami; 98305549Sjhb unsigned int pf, s_hps; 99305549Sjhb int i, v; 100305549Sjhb 101305549Sjhb params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 102305549Sjhb V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL)); 103305549Sjhb params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 104305549Sjhb V_FW_PARAMS_PARAM_XYZ(A_SGE_HOST_PAGE_SIZE)); 105305549Sjhb params[2] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 106305549Sjhb V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_0_AND_1)); 107305549Sjhb params[3] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 108305549Sjhb V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_2_AND_3)); 109305549Sjhb params[4] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 110305549Sjhb V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_4_AND_5)); 111305549Sjhb params[5] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 112305549Sjhb V_FW_PARAMS_PARAM_XYZ(A_SGE_CONM_CTRL)); 113305549Sjhb params[6] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 114305549Sjhb V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_RX_THRESHOLD)); 115305549Sjhb v = t4vf_query_params(adapter, 7, params, vals); 116305549Sjhb if (v != FW_SUCCESS) 117305549Sjhb return v; 118305549Sjhb 119305549Sjhb sp->sge_control = vals[0]; 120305549Sjhb sp->counter_val[0] = G_THRESHOLD_0(vals[6]); 121305549Sjhb sp->counter_val[1] = G_THRESHOLD_1(vals[6]); 122305549Sjhb sp->counter_val[2] = G_THRESHOLD_2(vals[6]); 123305549Sjhb sp->counter_val[3] = G_THRESHOLD_3(vals[6]); 124305549Sjhb sp->timer_val[0] = core_ticks_to_us(adapter, G_TIMERVALUE0(vals[2])); 125305549Sjhb sp->timer_val[1] = core_ticks_to_us(adapter, G_TIMERVALUE1(vals[2])); 126305549Sjhb sp->timer_val[2] = core_ticks_to_us(adapter, G_TIMERVALUE2(vals[3])); 127305549Sjhb sp->timer_val[3] = core_ticks_to_us(adapter, G_TIMERVALUE3(vals[3])); 128305549Sjhb sp->timer_val[4] = core_ticks_to_us(adapter, G_TIMERVALUE4(vals[4])); 129305549Sjhb sp->timer_val[5] = core_ticks_to_us(adapter, G_TIMERVALUE5(vals[4])); 130305549Sjhb 131305549Sjhb sp->fl_starve_threshold = G_EGRTHRESHOLD(vals[5]) * 2 + 1; 132305549Sjhb if (is_t4(adapter)) 133305549Sjhb sp->fl_starve_threshold2 = sp->fl_starve_threshold; 134309560Sjhb else if (is_t5(adapter)) 135309560Sjhb sp->fl_starve_threshold2 = G_EGRTHRESHOLDPACKING(vals[5]) * 2 + 1; 136305549Sjhb else 137309560Sjhb sp->fl_starve_threshold2 = G_T6_EGRTHRESHOLDPACKING(vals[5]) * 2 + 1; 138305549Sjhb 139305549Sjhb /* 140305549Sjhb * We need the Queues/Page and Host Page Size for our VF. 141305549Sjhb * This is based on the PF from which we're instantiated. 142305549Sjhb */ 143305549Sjhb whoami = t4_read_reg(adapter, VF_PL_REG(A_PL_VF_WHOAMI)); 144305549Sjhb pf = G_SOURCEPF(whoami); 145305549Sjhb 146305549Sjhb s_hps = (S_HOSTPAGESIZEPF0 + 147305549Sjhb (S_HOSTPAGESIZEPF1 - S_HOSTPAGESIZEPF0) * pf); 148305549Sjhb sp->page_shift = ((vals[1] >> s_hps) & M_HOSTPAGESIZEPF0) + 10; 149305549Sjhb 150305549Sjhb for (i = 0; i < SGE_FLBUF_SIZES; i++) { 151305549Sjhb params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 152305549Sjhb V_FW_PARAMS_PARAM_XYZ(A_SGE_FL_BUFFER_SIZE0 + (4 * i))); 153305549Sjhb v = t4vf_query_params(adapter, 1, params, vals); 154305549Sjhb if (v != FW_SUCCESS) 155305549Sjhb return v; 156305549Sjhb 157305549Sjhb sp->sge_fl_buffer_size[i] = vals[0]; 158305549Sjhb } 159305549Sjhb 160305549Sjhb /* 161305549Sjhb * T4 uses a single control field to specify both the PCIe Padding and 162305549Sjhb * Packing Boundary. T5 introduced the ability to specify these 163305549Sjhb * separately with the Padding Boundary in SGE_CONTROL and and Packing 164305549Sjhb * Boundary in SGE_CONTROL2. So for T5 and later we need to grab 165305549Sjhb * SGE_CONTROL in order to determine how ingress packet data will be 166305549Sjhb * laid out in Packed Buffer Mode. Unfortunately, older versions of 167305549Sjhb * the firmware won't let us retrieve SGE_CONTROL2 so if we get a 168305549Sjhb * failure grabbing it we throw an error since we can't figure out the 169305549Sjhb * right value. 170305549Sjhb */ 171305549Sjhb sp->spg_len = sp->sge_control & F_EGRSTATUSPAGESIZE ? 128 : 64; 172305549Sjhb sp->fl_pktshift = G_PKTSHIFT(sp->sge_control); 173309560Sjhb if (chip_id(adapter) <= CHELSIO_T5) { 174309560Sjhb sp->pad_boundary = 1 << (G_INGPADBOUNDARY(sp->sge_control) + 175309560Sjhb X_INGPADBOUNDARY_SHIFT); 176309560Sjhb } else { 177309560Sjhb sp->pad_boundary = 1 << (G_INGPADBOUNDARY(sp->sge_control) + 178309560Sjhb X_T6_INGPADBOUNDARY_SHIFT); 179309560Sjhb } 180305549Sjhb if (is_t4(adapter)) 181305549Sjhb sp->pack_boundary = sp->pad_boundary; 182305549Sjhb else { 183305549Sjhb params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 184305549Sjhb V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL2)); 185305549Sjhb v = t4vf_query_params(adapter, 1, params, vals); 186305549Sjhb if (v != FW_SUCCESS) { 187305549Sjhb CH_ERR(adapter, "Unable to get SGE Control2; " 188305549Sjhb "probably old firmware.\n"); 189305549Sjhb return v; 190305549Sjhb } 191305549Sjhb if (G_INGPACKBOUNDARY(vals[0]) == 0) 192305549Sjhb sp->pack_boundary = 16; 193305549Sjhb else 194305549Sjhb sp->pack_boundary = 1 << (G_INGPACKBOUNDARY(vals[0]) + 195305549Sjhb 5); 196305549Sjhb } 197305549Sjhb 198305549Sjhb /* 199305549Sjhb * For T5 and later we want to use the new BAR2 Doorbells. 200305549Sjhb * Unfortunately, older firmware didn't allow the this register to be 201305549Sjhb * read. 202305549Sjhb */ 203305549Sjhb if (!is_t4(adapter)) { 204305549Sjhb unsigned int s_qpp; 205305549Sjhb 206305549Sjhb params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 207305549Sjhb V_FW_PARAMS_PARAM_XYZ(A_SGE_EGRESS_QUEUES_PER_PAGE_VF)); 208305549Sjhb params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 209305549Sjhb V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_QUEUES_PER_PAGE_VF)); 210305549Sjhb v = t4vf_query_params(adapter, 2, params, vals); 211305549Sjhb if (v != FW_SUCCESS) { 212305549Sjhb CH_WARN(adapter, "Unable to get VF SGE Queues/Page; " 213305549Sjhb "probably old firmware.\n"); 214305549Sjhb return v; 215305549Sjhb } 216305549Sjhb 217305549Sjhb s_qpp = (S_QUEUESPERPAGEPF0 + 218305549Sjhb (S_QUEUESPERPAGEPF1 - S_QUEUESPERPAGEPF0) * pf); 219305549Sjhb sp->eq_s_qpp = ((vals[0] >> s_qpp) & M_QUEUESPERPAGEPF0); 220305549Sjhb sp->iq_s_qpp = ((vals[1] >> s_qpp) & M_QUEUESPERPAGEPF0); 221305549Sjhb } 222305549Sjhb 223305549Sjhb return 0; 224305549Sjhb} 225305549Sjhb 226305549Sjhb/** 227305549Sjhb * t4vf_get_rss_glb_config - retrieve adapter RSS Global Configuration 228305549Sjhb * @adapter: the adapter 229305549Sjhb * 230305549Sjhb * Retrieves global RSS mode and parameters with which we have to live 231305549Sjhb * and stores them in the @adapter's RSS parameters. 232305549Sjhb */ 233305549Sjhbint t4vf_get_rss_glb_config(struct adapter *adapter) 234305549Sjhb{ 235305549Sjhb struct rss_params *rss = &adapter->params.rss; 236305549Sjhb struct fw_rss_glb_config_cmd cmd, rpl; 237305549Sjhb int v; 238305549Sjhb 239305549Sjhb /* 240305549Sjhb * Execute an RSS Global Configuration read command to retrieve 241305549Sjhb * our RSS configuration. 242305549Sjhb */ 243305549Sjhb memset(&cmd, 0, sizeof(cmd)); 244305549Sjhb cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) | 245305549Sjhb F_FW_CMD_REQUEST | 246305549Sjhb F_FW_CMD_READ); 247305549Sjhb cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); 248305549Sjhb v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl); 249305549Sjhb if (v != FW_SUCCESS) 250305549Sjhb return v; 251305549Sjhb 252305549Sjhb /* 253305549Sjhb * Transate the big-endian RSS Global Configuration into our 254305549Sjhb * cpu-endian format based on the RSS mode. We also do first level 255305549Sjhb * filtering at this point to weed out modes which don't support 256305549Sjhb * VF Drivers ... 257305549Sjhb */ 258305549Sjhb rss->mode = G_FW_RSS_GLB_CONFIG_CMD_MODE( 259305549Sjhb be32_to_cpu(rpl.u.manual.mode_pkd)); 260305549Sjhb switch (rss->mode) { 261305549Sjhb case FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL: { 262305549Sjhb u32 word = be32_to_cpu( 263305549Sjhb rpl.u.basicvirtual.synmapen_to_hashtoeplitz); 264305549Sjhb 265305549Sjhb rss->u.basicvirtual.synmapen = 266305549Sjhb ((word & F_FW_RSS_GLB_CONFIG_CMD_SYNMAPEN) != 0); 267305549Sjhb rss->u.basicvirtual.syn4tupenipv6 = 268305549Sjhb ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6) != 0); 269305549Sjhb rss->u.basicvirtual.syn2tupenipv6 = 270305549Sjhb ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6) != 0); 271305549Sjhb rss->u.basicvirtual.syn4tupenipv4 = 272305549Sjhb ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4) != 0); 273305549Sjhb rss->u.basicvirtual.syn2tupenipv4 = 274305549Sjhb ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4) != 0); 275305549Sjhb 276305549Sjhb rss->u.basicvirtual.ofdmapen = 277305549Sjhb ((word & F_FW_RSS_GLB_CONFIG_CMD_OFDMAPEN) != 0); 278305549Sjhb 279305549Sjhb rss->u.basicvirtual.tnlmapen = 280305549Sjhb ((word & F_FW_RSS_GLB_CONFIG_CMD_TNLMAPEN) != 0); 281305549Sjhb rss->u.basicvirtual.tnlalllookup = 282305549Sjhb ((word & F_FW_RSS_GLB_CONFIG_CMD_TNLALLLKP) != 0); 283305549Sjhb 284305549Sjhb rss->u.basicvirtual.hashtoeplitz = 285305549Sjhb ((word & F_FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ) != 0); 286305549Sjhb 287305549Sjhb /* we need at least Tunnel Map Enable to be set */ 288305549Sjhb if (!rss->u.basicvirtual.tnlmapen) 289305549Sjhb return -EINVAL; 290305549Sjhb break; 291305549Sjhb } 292305549Sjhb 293305549Sjhb default: 294305549Sjhb /* all unknown/unsupported RSS modes result in an error */ 295305549Sjhb return -EINVAL; 296305549Sjhb } 297305549Sjhb 298305549Sjhb return 0; 299305549Sjhb} 300305549Sjhb 301305549Sjhb/** 302305549Sjhb * t4vf_get_vfres - retrieve VF resource limits 303305549Sjhb * @adapter: the adapter 304305549Sjhb * 305305549Sjhb * Retrieves configured resource limits and capabilities for a virtual 306305549Sjhb * function. The results are stored in @adapter->vfres. 307305549Sjhb */ 308305549Sjhbint t4vf_get_vfres(struct adapter *adapter) 309305549Sjhb{ 310305549Sjhb struct vf_resources *vfres = &adapter->params.vfres; 311305549Sjhb struct fw_pfvf_cmd cmd, rpl; 312305549Sjhb int v; 313305549Sjhb u32 word; 314305549Sjhb 315305549Sjhb /* 316305549Sjhb * Execute PFVF Read command to get VF resource limits; bail out early 317305549Sjhb * with error on command failure. 318305549Sjhb */ 319305549Sjhb memset(&cmd, 0, sizeof(cmd)); 320305549Sjhb cmd.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PFVF_CMD) | 321305549Sjhb F_FW_CMD_REQUEST | 322305549Sjhb F_FW_CMD_READ); 323305549Sjhb cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); 324305549Sjhb v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl); 325305549Sjhb if (v != FW_SUCCESS) 326305549Sjhb return v; 327305549Sjhb 328305549Sjhb /* 329305549Sjhb * Extract VF resource limits and return success. 330305549Sjhb */ 331305549Sjhb word = be32_to_cpu(rpl.niqflint_niq); 332305549Sjhb vfres->niqflint = G_FW_PFVF_CMD_NIQFLINT(word); 333305549Sjhb vfres->niq = G_FW_PFVF_CMD_NIQ(word); 334305549Sjhb 335305549Sjhb word = be32_to_cpu(rpl.type_to_neq); 336305549Sjhb vfres->neq = G_FW_PFVF_CMD_NEQ(word); 337305549Sjhb vfres->pmask = G_FW_PFVF_CMD_PMASK(word); 338305549Sjhb 339305549Sjhb word = be32_to_cpu(rpl.tc_to_nexactf); 340305549Sjhb vfres->tc = G_FW_PFVF_CMD_TC(word); 341305549Sjhb vfres->nvi = G_FW_PFVF_CMD_NVI(word); 342305549Sjhb vfres->nexactf = G_FW_PFVF_CMD_NEXACTF(word); 343305549Sjhb 344305549Sjhb word = be32_to_cpu(rpl.r_caps_to_nethctrl); 345305549Sjhb vfres->r_caps = G_FW_PFVF_CMD_R_CAPS(word); 346305549Sjhb vfres->wx_caps = G_FW_PFVF_CMD_WX_CAPS(word); 347305549Sjhb vfres->nethctrl = G_FW_PFVF_CMD_NETHCTRL(word); 348305549Sjhb 349305549Sjhb return 0; 350305549Sjhb} 351305549Sjhb 352305549Sjhb/** 353305549Sjhb */ 354305549Sjhbint t4vf_prep_adapter(struct adapter *adapter) 355305549Sjhb{ 356305549Sjhb int err; 357305549Sjhb 358305549Sjhb /* 359305549Sjhb * Wait for the device to become ready before proceeding ... 360305549Sjhb */ 361305549Sjhb err = t4vf_wait_dev_ready(adapter); 362305549Sjhb if (err) 363305549Sjhb return err; 364305549Sjhb 365305549Sjhb adapter->params.chipid = pci_get_device(adapter->dev) >> 12; 366305549Sjhb if (adapter->params.chipid >= 0xa) { 367305549Sjhb adapter->params.chipid -= (0xa - 0x4); 368305549Sjhb adapter->params.fpga = 1; 369305549Sjhb } 370305549Sjhb 371305549Sjhb /* 372305549Sjhb * Default port and clock for debugging in case we can't reach 373305549Sjhb * firmware. 374305549Sjhb */ 375305549Sjhb adapter->params.nports = 1; 376305549Sjhb adapter->params.vfres.pmask = 1; 377305549Sjhb adapter->params.vpd.cclk = 50000; 378305549Sjhb 379305549Sjhb adapter->chip_params = t4_get_chip_params(chip_id(adapter)); 380305549Sjhb if (adapter->chip_params == NULL) 381305549Sjhb return -EINVAL; 382305549Sjhb 383305549Sjhb return 0; 384305549Sjhb} 385