1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2007-2016 Solarflare Communications Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * The views and conclusions contained in the software and documentation are 29 * those of the authors and should not be interpreted as representing official 30 * policies, either expressed or implied, of the FreeBSD Project. 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include "efx.h" 37 #include "efx_impl.h" 38 39 __checkReturn efx_rc_t 40 efx_sram_buf_tbl_set( 41 __in efx_nic_t *enp, 42 __in uint32_t id, 43 __in efsys_mem_t *esmp, 44 __in size_t n) 45 { 46 efx_qword_t qword; 47 uint32_t start = id; 48 uint32_t stop = start + n; 49 efsys_dma_addr_t addr; 50 efx_oword_t oword; 51 unsigned int count; 52 efx_rc_t rc; 53 54 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 55 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 56 57 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 58 if (enp->en_family == EFX_FAMILY_HUNTINGTON || 59 enp->en_family == EFX_FAMILY_MEDFORD || 60 enp->en_family == EFX_FAMILY_MEDFORD2) { 61 /* 62 * FIXME: the efx_sram_buf_tbl_*() functionality needs to be 63 * pulled inside the Falcon/Siena queue create/destroy code, 64 * and then the original functions can be removed (see bug30834 65 * comment #1). But, for now, we just ensure that they are 66 * no-ops for EF10, to allow bringing up existing drivers 67 * without modification. 68 */ 69 70 return (0); 71 } 72 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ 73 74 if (stop >= EFX_BUF_TBL_SIZE) { 75 rc = EFBIG; 76 goto fail1; 77 } 78 79 /* Add the entries into the buffer table */ 80 addr = EFSYS_MEM_ADDR(esmp); 81 for (id = start; id != stop; id++) { 82 EFX_POPULATE_QWORD_5(qword, 83 FRF_AZ_IP_DAT_BUF_SIZE, 0, FRF_AZ_BUF_ADR_REGION, 0, 84 FRF_AZ_BUF_ADR_FBUF_DW0, 85 (uint32_t)((addr >> 12) & 0xffffffff), 86 FRF_AZ_BUF_ADR_FBUF_DW1, 87 (uint32_t)((addr >> 12) >> 32), 88 FRF_AZ_BUF_OWNER_ID_FBUF, 0); 89 90 EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_FULL_TBL, 91 id, &qword); 92 93 addr += EFX_BUF_SIZE; 94 } 95 96 EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1); 97 98 /* Flush the write buffer */ 99 EFX_POPULATE_OWORD_2(oword, FRF_AZ_BUF_UPD_CMD, 1, 100 FRF_AZ_BUF_CLR_CMD, 0); 101 EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword); 102 103 /* Poll for the last entry being written to the buffer table */ 104 EFSYS_ASSERT3U(id, ==, stop); 105 addr -= EFX_BUF_SIZE; 106 107 count = 0; 108 do { 109 EFSYS_PROBE1(wait, unsigned int, count); 110 111 /* Spin for 1 ms */ 112 EFSYS_SPIN(1000); 113 114 EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL, 115 id - 1, &qword); 116 117 if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) == 118 (uint32_t)((addr >> 12) & 0xffffffff) && 119 EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) == 120 (uint32_t)((addr >> 12) >> 32)) 121 goto verify; 122 123 } while (++count < 100); 124 125 rc = ETIMEDOUT; 126 goto fail2; 127 128 verify: 129 /* Verify the rest of the entries in the buffer table */ 130 while (--id != start) { 131 addr -= EFX_BUF_SIZE; 132 133 /* Read the buffer table entry */ 134 EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL, 135 id - 1, &qword); 136 137 if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) != 138 (uint32_t)((addr >> 12) & 0xffffffff) || 139 EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) != 140 (uint32_t)((addr >> 12) >> 32)) { 141 rc = EFAULT; 142 goto fail3; 143 } 144 } 145 146 return (0); 147 148 fail3: 149 EFSYS_PROBE(fail3); 150 151 id = stop; 152 153 fail2: 154 EFSYS_PROBE(fail2); 155 156 EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0, 157 FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, id - 1, 158 FRF_AZ_BUF_CLR_START_ID, start); 159 EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword); 160 161 fail1: 162 EFSYS_PROBE1(fail1, efx_rc_t, rc); 163 164 return (rc); 165 } 166 167 void 168 efx_sram_buf_tbl_clear( 169 __in efx_nic_t *enp, 170 __in uint32_t id, 171 __in size_t n) 172 { 173 efx_oword_t oword; 174 uint32_t start = id; 175 uint32_t stop = start + n; 176 177 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 178 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 179 180 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 181 if (enp->en_family == EFX_FAMILY_HUNTINGTON || 182 enp->en_family == EFX_FAMILY_MEDFORD || 183 enp->en_family == EFX_FAMILY_MEDFORD2) { 184 /* 185 * FIXME: the efx_sram_buf_tbl_*() functionality needs to be 186 * pulled inside the Falcon/Siena queue create/destroy code, 187 * and then the original functions can be removed (see bug30834 188 * comment #1). But, for now, we just ensure that they are 189 * no-ops for EF10, to allow bringing up existing drivers 190 * without modification. 191 */ 192 193 return; 194 } 195 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ 196 197 EFSYS_ASSERT3U(stop, <, EFX_BUF_TBL_SIZE); 198 199 EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1); 200 201 EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0, 202 FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, stop - 1, 203 FRF_AZ_BUF_CLR_START_ID, start); 204 EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword); 205 } 206 207 208 #if EFSYS_OPT_DIAG 209 210 static void 211 efx_sram_byte_increment_set( 212 __in size_t row, 213 __in boolean_t negate, 214 __out efx_qword_t *eqp) 215 { 216 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 217 unsigned int index; 218 219 _NOTE(ARGUNUSED(negate)) 220 221 for (index = 0; index < sizeof (efx_qword_t); index++) 222 eqp->eq_u8[index] = offset + index; 223 } 224 225 static void 226 efx_sram_all_the_same_set( 227 __in size_t row, 228 __in boolean_t negate, 229 __out efx_qword_t *eqp) 230 { 231 _NOTE(ARGUNUSED(row)) 232 233 if (negate) 234 EFX_SET_QWORD(*eqp); 235 else 236 EFX_ZERO_QWORD(*eqp); 237 } 238 239 static void 240 efx_sram_bit_alternate_set( 241 __in size_t row, 242 __in boolean_t negate, 243 __out efx_qword_t *eqp) 244 { 245 _NOTE(ARGUNUSED(row)) 246 247 EFX_POPULATE_QWORD_2(*eqp, 248 EFX_DWORD_0, (negate) ? 0x55555555 : 0xaaaaaaaa, 249 EFX_DWORD_1, (negate) ? 0x55555555 : 0xaaaaaaaa); 250 } 251 252 static void 253 efx_sram_byte_alternate_set( 254 __in size_t row, 255 __in boolean_t negate, 256 __out efx_qword_t *eqp) 257 { 258 _NOTE(ARGUNUSED(row)) 259 260 EFX_POPULATE_QWORD_2(*eqp, 261 EFX_DWORD_0, (negate) ? 0x00ff00ff : 0xff00ff00, 262 EFX_DWORD_1, (negate) ? 0x00ff00ff : 0xff00ff00); 263 } 264 265 static void 266 efx_sram_byte_changing_set( 267 __in size_t row, 268 __in boolean_t negate, 269 __out efx_qword_t *eqp) 270 { 271 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 272 unsigned int index; 273 274 for (index = 0; index < sizeof (efx_qword_t); index++) { 275 uint8_t byte; 276 277 if (offset / 256 == 0) 278 byte = (uint8_t)((offset % 257) % 256); 279 else 280 byte = (uint8_t)(~((offset - 8) % 257) % 256); 281 282 eqp->eq_u8[index] = (negate) ? ~byte : byte; 283 } 284 } 285 286 static void 287 efx_sram_bit_sweep_set( 288 __in size_t row, 289 __in boolean_t negate, 290 __out efx_qword_t *eqp) 291 { 292 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 293 294 if (negate) { 295 EFX_SET_QWORD(*eqp); 296 EFX_CLEAR_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64); 297 } else { 298 EFX_ZERO_QWORD(*eqp); 299 EFX_SET_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64); 300 } 301 } 302 303 efx_sram_pattern_fn_t __efx_sram_pattern_fns[] = { 304 efx_sram_byte_increment_set, 305 efx_sram_all_the_same_set, 306 efx_sram_bit_alternate_set, 307 efx_sram_byte_alternate_set, 308 efx_sram_byte_changing_set, 309 efx_sram_bit_sweep_set 310 }; 311 312 __checkReturn efx_rc_t 313 efx_sram_test( 314 __in efx_nic_t *enp, 315 __in efx_pattern_type_t type) 316 { 317 efx_sram_pattern_fn_t func; 318 319 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 320 321 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 322 323 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX)); 324 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX)); 325 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV)); 326 327 /* SRAM testing is only available on Siena. */ 328 if (enp->en_family != EFX_FAMILY_SIENA) 329 return (0); 330 331 /* Select pattern generator */ 332 EFSYS_ASSERT3U(type, <, EFX_PATTERN_NTYPES); 333 func = __efx_sram_pattern_fns[type]; 334 335 return (siena_sram_test(enp, func)); 336 } 337 338 #endif /* EFSYS_OPT_DIAG */ 339