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 58 if (enp->en_family == EFX_FAMILY_HUNTINGTON || 59 enp->en_family == EFX_FAMILY_MEDFORD) { 60 /* 61 * FIXME: the efx_sram_buf_tbl_*() functionality needs to be 62 * pulled inside the Falcon/Siena queue create/destroy code, 63 * and then the original functions can be removed (see bug30834 64 * comment #1). But, for now, we just ensure that they are 65 * no-ops for EF10, to allow bringing up existing drivers 66 * without modification. 67 */ 68 69 return (0); 70 } 71 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 72 73 if (stop >= EFX_BUF_TBL_SIZE) { 74 rc = EFBIG; 75 goto fail1; 76 } 77 78 /* Add the entries into the buffer table */ 79 addr = EFSYS_MEM_ADDR(esmp); 80 for (id = start; id != stop; id++) { 81 EFX_POPULATE_QWORD_5(qword, 82 FRF_AZ_IP_DAT_BUF_SIZE, 0, FRF_AZ_BUF_ADR_REGION, 0, 83 FRF_AZ_BUF_ADR_FBUF_DW0, 84 (uint32_t)((addr >> 12) & 0xffffffff), 85 FRF_AZ_BUF_ADR_FBUF_DW1, 86 (uint32_t)((addr >> 12) >> 32), 87 FRF_AZ_BUF_OWNER_ID_FBUF, 0); 88 89 EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_FULL_TBL, 90 id, &qword); 91 92 addr += EFX_BUF_SIZE; 93 } 94 95 EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1); 96 97 /* Flush the write buffer */ 98 EFX_POPULATE_OWORD_2(oword, FRF_AZ_BUF_UPD_CMD, 1, 99 FRF_AZ_BUF_CLR_CMD, 0); 100 EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword); 101 102 /* Poll for the last entry being written to the buffer table */ 103 EFSYS_ASSERT3U(id, ==, stop); 104 addr -= EFX_BUF_SIZE; 105 106 count = 0; 107 do { 108 EFSYS_PROBE1(wait, unsigned int, count); 109 110 /* Spin for 1 ms */ 111 EFSYS_SPIN(1000); 112 113 EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL, 114 id - 1, &qword); 115 116 if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) == 117 (uint32_t)((addr >> 12) & 0xffffffff) && 118 EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) == 119 (uint32_t)((addr >> 12) >> 32)) 120 goto verify; 121 122 } while (++count < 100); 123 124 rc = ETIMEDOUT; 125 goto fail2; 126 127 verify: 128 /* Verify the rest of the entries in the buffer table */ 129 while (--id != start) { 130 addr -= EFX_BUF_SIZE; 131 132 /* Read the buffer table entry */ 133 EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL, 134 id - 1, &qword); 135 136 if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) != 137 (uint32_t)((addr >> 12) & 0xffffffff) || 138 EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) != 139 (uint32_t)((addr >> 12) >> 32)) { 140 rc = EFAULT; 141 goto fail3; 142 } 143 } 144 145 return (0); 146 147 fail3: 148 EFSYS_PROBE(fail3); 149 150 id = stop; 151 152 fail2: 153 EFSYS_PROBE(fail2); 154 155 EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0, 156 FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, id - 1, 157 FRF_AZ_BUF_CLR_START_ID, start); 158 EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword); 159 160 fail1: 161 EFSYS_PROBE1(fail1, efx_rc_t, rc); 162 163 return (rc); 164 } 165 166 void 167 efx_sram_buf_tbl_clear( 168 __in efx_nic_t *enp, 169 __in uint32_t id, 170 __in size_t n) 171 { 172 efx_oword_t oword; 173 uint32_t start = id; 174 uint32_t stop = start + n; 175 176 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 177 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 178 179 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 180 if (enp->en_family == EFX_FAMILY_HUNTINGTON || 181 enp->en_family == EFX_FAMILY_MEDFORD) { 182 /* 183 * FIXME: the efx_sram_buf_tbl_*() functionality needs to be 184 * pulled inside the Falcon/Siena queue create/destroy code, 185 * and then the original functions can be removed (see bug30834 186 * comment #1). But, for now, we just ensure that they are 187 * no-ops for EF10, to allow bringing up existing drivers 188 * without modification. 189 */ 190 191 return; 192 } 193 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 194 195 EFSYS_ASSERT3U(stop, <, EFX_BUF_TBL_SIZE); 196 197 EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1); 198 199 EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0, 200 FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, stop - 1, 201 FRF_AZ_BUF_CLR_START_ID, start); 202 EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword); 203 } 204 205 206 #if EFSYS_OPT_DIAG 207 208 static void 209 efx_sram_byte_increment_set( 210 __in size_t row, 211 __in boolean_t negate, 212 __out efx_qword_t *eqp) 213 { 214 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 215 unsigned int index; 216 217 _NOTE(ARGUNUSED(negate)) 218 219 for (index = 0; index < sizeof (efx_qword_t); index++) 220 eqp->eq_u8[index] = offset + index; 221 } 222 223 static void 224 efx_sram_all_the_same_set( 225 __in size_t row, 226 __in boolean_t negate, 227 __out efx_qword_t *eqp) 228 { 229 _NOTE(ARGUNUSED(row)) 230 231 if (negate) 232 EFX_SET_QWORD(*eqp); 233 else 234 EFX_ZERO_QWORD(*eqp); 235 } 236 237 static void 238 efx_sram_bit_alternate_set( 239 __in size_t row, 240 __in boolean_t negate, 241 __out efx_qword_t *eqp) 242 { 243 _NOTE(ARGUNUSED(row)) 244 245 EFX_POPULATE_QWORD_2(*eqp, 246 EFX_DWORD_0, (negate) ? 0x55555555 : 0xaaaaaaaa, 247 EFX_DWORD_1, (negate) ? 0x55555555 : 0xaaaaaaaa); 248 } 249 250 static void 251 efx_sram_byte_alternate_set( 252 __in size_t row, 253 __in boolean_t negate, 254 __out efx_qword_t *eqp) 255 { 256 _NOTE(ARGUNUSED(row)) 257 258 EFX_POPULATE_QWORD_2(*eqp, 259 EFX_DWORD_0, (negate) ? 0x00ff00ff : 0xff00ff00, 260 EFX_DWORD_1, (negate) ? 0x00ff00ff : 0xff00ff00); 261 } 262 263 static void 264 efx_sram_byte_changing_set( 265 __in size_t row, 266 __in boolean_t negate, 267 __out efx_qword_t *eqp) 268 { 269 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 270 unsigned int index; 271 272 for (index = 0; index < sizeof (efx_qword_t); index++) { 273 uint8_t byte; 274 275 if (offset / 256 == 0) 276 byte = (uint8_t)((offset % 257) % 256); 277 else 278 byte = (uint8_t)(~((offset - 8) % 257) % 256); 279 280 eqp->eq_u8[index] = (negate) ? ~byte : byte; 281 } 282 } 283 284 static void 285 efx_sram_bit_sweep_set( 286 __in size_t row, 287 __in boolean_t negate, 288 __out efx_qword_t *eqp) 289 { 290 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 291 292 if (negate) { 293 EFX_SET_QWORD(*eqp); 294 EFX_CLEAR_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64); 295 } else { 296 EFX_ZERO_QWORD(*eqp); 297 EFX_SET_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64); 298 } 299 } 300 301 efx_sram_pattern_fn_t __efx_sram_pattern_fns[] = { 302 efx_sram_byte_increment_set, 303 efx_sram_all_the_same_set, 304 efx_sram_bit_alternate_set, 305 efx_sram_byte_alternate_set, 306 efx_sram_byte_changing_set, 307 efx_sram_bit_sweep_set 308 }; 309 310 __checkReturn efx_rc_t 311 efx_sram_test( 312 __in efx_nic_t *enp, 313 __in efx_pattern_type_t type) 314 { 315 efx_sram_pattern_fn_t func; 316 317 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 318 319 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 320 321 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX)); 322 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX)); 323 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV)); 324 325 /* SRAM testing is only available on Siena. */ 326 if (enp->en_family != EFX_FAMILY_SIENA) 327 return (0); 328 329 /* Select pattern generator */ 330 EFSYS_ASSERT3U(type, <, EFX_PATTERN_NTYPES); 331 func = __efx_sram_pattern_fns[type]; 332 333 return (siena_sram_test(enp, func)); 334 } 335 336 #endif /* EFSYS_OPT_DIAG */ 337