t4vf_hw.c revision 306664
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: stable/11/sys/dev/cxgbe/common/t4vf_hw.c 306664 2016-10-03 23:49:05Z jhb $"); 29 30#include "common.h" 31#include "t4_regs.h" 32 33#undef msleep 34#define msleep(x) do { \ 35 if (cold) \ 36 DELAY((x) * 1000); \ 37 else \ 38 pause("t4hw", (x) * hz / 1000); \ 39} while (0) 40 41/* 42 * Wait for the device to become ready (signified by our "who am I" register 43 * returning a value other than all 1's). Return an error if it doesn't 44 * become ready ... 45 */ 46int t4vf_wait_dev_ready(struct adapter *adapter) 47{ 48 const u32 whoami = VF_PL_REG(A_PL_VF_WHOAMI); 49 const u32 notready1 = 0xffffffff; 50 const u32 notready2 = 0xeeeeeeee; 51 u32 val; 52 53 val = t4_read_reg(adapter, whoami); 54 if (val != notready1 && val != notready2) 55 return 0; 56 msleep(500); 57 val = t4_read_reg(adapter, whoami); 58 if (val != notready1 && val != notready2) 59 return 0; 60 else 61 return -EIO; 62} 63 64 65/** 66 * t4vf_fw_reset - issue a reset to FW 67 * @adapter: the adapter 68 * 69 * Issues a reset command to FW. For a Physical Function this would 70 * result in the Firmware reseting all of its state. For a Virtual 71 * Function this just resets the state associated with the VF. 72 */ 73int t4vf_fw_reset(struct adapter *adapter) 74{ 75 struct fw_reset_cmd cmd; 76 77 memset(&cmd, 0, sizeof(cmd)); 78 cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_RESET_CMD) | 79 F_FW_CMD_WRITE); 80 cmd.retval_len16 = cpu_to_be32(V_FW_CMD_LEN16(FW_LEN16(cmd))); 81 return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL); 82} 83 84/** 85 * t4vf_get_sge_params - retrieve adapter Scatter gather Engine parameters 86 * @adapter: the adapter 87 * 88 * Retrieves various core SGE parameters in the form of hardware SGE 89 * register values. The caller is responsible for decoding these as 90 * needed. The SGE parameters are stored in @adapter->params.sge. 91 */ 92int t4vf_get_sge_params(struct adapter *adapter) 93{ 94 struct sge_params *sp = &adapter->params.sge; 95 u32 params[7], vals[7]; 96 u32 whoami; 97 unsigned int pf, s_hps; 98 int i, v; 99 100 params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 101 V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL)); 102 params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 103 V_FW_PARAMS_PARAM_XYZ(A_SGE_HOST_PAGE_SIZE)); 104 params[2] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 105 V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_0_AND_1)); 106 params[3] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 107 V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_2_AND_3)); 108 params[4] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 109 V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_4_AND_5)); 110 params[5] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 111 V_FW_PARAMS_PARAM_XYZ(A_SGE_CONM_CTRL)); 112 params[6] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 113 V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_RX_THRESHOLD)); 114 v = t4vf_query_params(adapter, 7, params, vals); 115 if (v != FW_SUCCESS) 116 return v; 117 118 sp->sge_control = vals[0]; 119 sp->counter_val[0] = G_THRESHOLD_0(vals[6]); 120 sp->counter_val[1] = G_THRESHOLD_1(vals[6]); 121 sp->counter_val[2] = G_THRESHOLD_2(vals[6]); 122 sp->counter_val[3] = G_THRESHOLD_3(vals[6]); 123 sp->timer_val[0] = core_ticks_to_us(adapter, G_TIMERVALUE0(vals[2])); 124 sp->timer_val[1] = core_ticks_to_us(adapter, G_TIMERVALUE1(vals[2])); 125 sp->timer_val[2] = core_ticks_to_us(adapter, G_TIMERVALUE2(vals[3])); 126 sp->timer_val[3] = core_ticks_to_us(adapter, G_TIMERVALUE3(vals[3])); 127 sp->timer_val[4] = core_ticks_to_us(adapter, G_TIMERVALUE4(vals[4])); 128 sp->timer_val[5] = core_ticks_to_us(adapter, G_TIMERVALUE5(vals[4])); 129 130 sp->fl_starve_threshold = G_EGRTHRESHOLD(vals[5]) * 2 + 1; 131 if (is_t4(adapter)) 132 sp->fl_starve_threshold2 = sp->fl_starve_threshold; 133 else 134 sp->fl_starve_threshold2 = G_EGRTHRESHOLDPACKING(vals[5]) * 2 + 135 1; 136 137 /* 138 * We need the Queues/Page and Host Page Size for our VF. 139 * This is based on the PF from which we're instantiated. 140 */ 141 whoami = t4_read_reg(adapter, VF_PL_REG(A_PL_VF_WHOAMI)); 142 pf = G_SOURCEPF(whoami); 143 144 s_hps = (S_HOSTPAGESIZEPF0 + 145 (S_HOSTPAGESIZEPF1 - S_HOSTPAGESIZEPF0) * pf); 146 sp->page_shift = ((vals[1] >> s_hps) & M_HOSTPAGESIZEPF0) + 10; 147 148 for (i = 0; i < SGE_FLBUF_SIZES; i++) { 149 params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 150 V_FW_PARAMS_PARAM_XYZ(A_SGE_FL_BUFFER_SIZE0 + (4 * i))); 151 v = t4vf_query_params(adapter, 1, params, vals); 152 if (v != FW_SUCCESS) 153 return v; 154 155 sp->sge_fl_buffer_size[i] = vals[0]; 156 } 157 158 /* 159 * T4 uses a single control field to specify both the PCIe Padding and 160 * Packing Boundary. T5 introduced the ability to specify these 161 * separately with the Padding Boundary in SGE_CONTROL and and Packing 162 * Boundary in SGE_CONTROL2. So for T5 and later we need to grab 163 * SGE_CONTROL in order to determine how ingress packet data will be 164 * laid out in Packed Buffer Mode. Unfortunately, older versions of 165 * the firmware won't let us retrieve SGE_CONTROL2 so if we get a 166 * failure grabbing it we throw an error since we can't figure out the 167 * right value. 168 */ 169 sp->spg_len = sp->sge_control & F_EGRSTATUSPAGESIZE ? 128 : 64; 170 sp->fl_pktshift = G_PKTSHIFT(sp->sge_control); 171 sp->pad_boundary = 1 << (G_INGPADBOUNDARY(sp->sge_control) + 5); 172 if (is_t4(adapter)) 173 sp->pack_boundary = sp->pad_boundary; 174 else { 175 params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 176 V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL2)); 177 v = t4vf_query_params(adapter, 1, params, vals); 178 if (v != FW_SUCCESS) { 179 CH_ERR(adapter, "Unable to get SGE Control2; " 180 "probably old firmware.\n"); 181 return v; 182 } 183 if (G_INGPACKBOUNDARY(vals[0]) == 0) 184 sp->pack_boundary = 16; 185 else 186 sp->pack_boundary = 1 << (G_INGPACKBOUNDARY(vals[0]) + 187 5); 188 } 189 190 /* 191 * For T5 and later we want to use the new BAR2 Doorbells. 192 * Unfortunately, older firmware didn't allow the this register to be 193 * read. 194 */ 195 if (!is_t4(adapter)) { 196 unsigned int s_qpp; 197 198 params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 199 V_FW_PARAMS_PARAM_XYZ(A_SGE_EGRESS_QUEUES_PER_PAGE_VF)); 200 params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | 201 V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_QUEUES_PER_PAGE_VF)); 202 v = t4vf_query_params(adapter, 2, params, vals); 203 if (v != FW_SUCCESS) { 204 CH_WARN(adapter, "Unable to get VF SGE Queues/Page; " 205 "probably old firmware.\n"); 206 return v; 207 } 208 209 s_qpp = (S_QUEUESPERPAGEPF0 + 210 (S_QUEUESPERPAGEPF1 - S_QUEUESPERPAGEPF0) * pf); 211 sp->eq_s_qpp = ((vals[0] >> s_qpp) & M_QUEUESPERPAGEPF0); 212 sp->iq_s_qpp = ((vals[1] >> s_qpp) & M_QUEUESPERPAGEPF0); 213 } 214 215 return 0; 216} 217 218/** 219 * t4vf_get_rss_glb_config - retrieve adapter RSS Global Configuration 220 * @adapter: the adapter 221 * 222 * Retrieves global RSS mode and parameters with which we have to live 223 * and stores them in the @adapter's RSS parameters. 224 */ 225int t4vf_get_rss_glb_config(struct adapter *adapter) 226{ 227 struct rss_params *rss = &adapter->params.rss; 228 struct fw_rss_glb_config_cmd cmd, rpl; 229 int v; 230 231 /* 232 * Execute an RSS Global Configuration read command to retrieve 233 * our RSS configuration. 234 */ 235 memset(&cmd, 0, sizeof(cmd)); 236 cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) | 237 F_FW_CMD_REQUEST | 238 F_FW_CMD_READ); 239 cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); 240 v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl); 241 if (v != FW_SUCCESS) 242 return v; 243 244 /* 245 * Transate the big-endian RSS Global Configuration into our 246 * cpu-endian format based on the RSS mode. We also do first level 247 * filtering at this point to weed out modes which don't support 248 * VF Drivers ... 249 */ 250 rss->mode = G_FW_RSS_GLB_CONFIG_CMD_MODE( 251 be32_to_cpu(rpl.u.manual.mode_pkd)); 252 switch (rss->mode) { 253 case FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL: { 254 u32 word = be32_to_cpu( 255 rpl.u.basicvirtual.synmapen_to_hashtoeplitz); 256 257 rss->u.basicvirtual.synmapen = 258 ((word & F_FW_RSS_GLB_CONFIG_CMD_SYNMAPEN) != 0); 259 rss->u.basicvirtual.syn4tupenipv6 = 260 ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6) != 0); 261 rss->u.basicvirtual.syn2tupenipv6 = 262 ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6) != 0); 263 rss->u.basicvirtual.syn4tupenipv4 = 264 ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4) != 0); 265 rss->u.basicvirtual.syn2tupenipv4 = 266 ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4) != 0); 267 268 rss->u.basicvirtual.ofdmapen = 269 ((word & F_FW_RSS_GLB_CONFIG_CMD_OFDMAPEN) != 0); 270 271 rss->u.basicvirtual.tnlmapen = 272 ((word & F_FW_RSS_GLB_CONFIG_CMD_TNLMAPEN) != 0); 273 rss->u.basicvirtual.tnlalllookup = 274 ((word & F_FW_RSS_GLB_CONFIG_CMD_TNLALLLKP) != 0); 275 276 rss->u.basicvirtual.hashtoeplitz = 277 ((word & F_FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ) != 0); 278 279 /* we need at least Tunnel Map Enable to be set */ 280 if (!rss->u.basicvirtual.tnlmapen) 281 return -EINVAL; 282 break; 283 } 284 285 default: 286 /* all unknown/unsupported RSS modes result in an error */ 287 return -EINVAL; 288 } 289 290 return 0; 291} 292 293/** 294 * t4vf_get_vfres - retrieve VF resource limits 295 * @adapter: the adapter 296 * 297 * Retrieves configured resource limits and capabilities for a virtual 298 * function. The results are stored in @adapter->vfres. 299 */ 300int t4vf_get_vfres(struct adapter *adapter) 301{ 302 struct vf_resources *vfres = &adapter->params.vfres; 303 struct fw_pfvf_cmd cmd, rpl; 304 int v; 305 u32 word; 306 307 /* 308 * Execute PFVF Read command to get VF resource limits; bail out early 309 * with error on command failure. 310 */ 311 memset(&cmd, 0, sizeof(cmd)); 312 cmd.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PFVF_CMD) | 313 F_FW_CMD_REQUEST | 314 F_FW_CMD_READ); 315 cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); 316 v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl); 317 if (v != FW_SUCCESS) 318 return v; 319 320 /* 321 * Extract VF resource limits and return success. 322 */ 323 word = be32_to_cpu(rpl.niqflint_niq); 324 vfres->niqflint = G_FW_PFVF_CMD_NIQFLINT(word); 325 vfres->niq = G_FW_PFVF_CMD_NIQ(word); 326 327 word = be32_to_cpu(rpl.type_to_neq); 328 vfres->neq = G_FW_PFVF_CMD_NEQ(word); 329 vfres->pmask = G_FW_PFVF_CMD_PMASK(word); 330 331 word = be32_to_cpu(rpl.tc_to_nexactf); 332 vfres->tc = G_FW_PFVF_CMD_TC(word); 333 vfres->nvi = G_FW_PFVF_CMD_NVI(word); 334 vfres->nexactf = G_FW_PFVF_CMD_NEXACTF(word); 335 336 word = be32_to_cpu(rpl.r_caps_to_nethctrl); 337 vfres->r_caps = G_FW_PFVF_CMD_R_CAPS(word); 338 vfres->wx_caps = G_FW_PFVF_CMD_WX_CAPS(word); 339 vfres->nethctrl = G_FW_PFVF_CMD_NETHCTRL(word); 340 341 return 0; 342} 343 344/** 345 */ 346int t4vf_prep_adapter(struct adapter *adapter) 347{ 348 int err; 349 350 /* 351 * Wait for the device to become ready before proceeding ... 352 */ 353 err = t4vf_wait_dev_ready(adapter); 354 if (err) 355 return err; 356 357 adapter->params.chipid = pci_get_device(adapter->dev) >> 12; 358 if (adapter->params.chipid >= 0xa) { 359 adapter->params.chipid -= (0xa - 0x4); 360 adapter->params.fpga = 1; 361 } 362 363 /* 364 * Default port and clock for debugging in case we can't reach 365 * firmware. 366 */ 367 adapter->params.nports = 1; 368 adapter->params.vfres.pmask = 1; 369 adapter->params.vpd.cclk = 50000; 370 371 adapter->chip_params = t4_get_chip_params(chip_id(adapter)); 372 if (adapter->chip_params == NULL) 373 return -EINVAL; 374 375 return 0; 376} 377