1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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 #if EFSYS_OPT_DIAG 208 209 static void 210 efx_sram_byte_increment_set( 211 __in size_t row, 212 __in boolean_t negate, 213 __out efx_qword_t *eqp) 214 { 215 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 216 unsigned int index; 217 218 _NOTE(ARGUNUSED(negate)) 219 220 for (index = 0; index < sizeof (efx_qword_t); index++) 221 eqp->eq_u8[index] = offset + index; 222 } 223 224 static void 225 efx_sram_all_the_same_set( 226 __in size_t row, 227 __in boolean_t negate, 228 __out efx_qword_t *eqp) 229 { 230 _NOTE(ARGUNUSED(row)) 231 232 if (negate) 233 EFX_SET_QWORD(*eqp); 234 else 235 EFX_ZERO_QWORD(*eqp); 236 } 237 238 static void 239 efx_sram_bit_alternate_set( 240 __in size_t row, 241 __in boolean_t negate, 242 __out efx_qword_t *eqp) 243 { 244 _NOTE(ARGUNUSED(row)) 245 246 EFX_POPULATE_QWORD_2(*eqp, 247 EFX_DWORD_0, (negate) ? 0x55555555 : 0xaaaaaaaa, 248 EFX_DWORD_1, (negate) ? 0x55555555 : 0xaaaaaaaa); 249 } 250 251 static void 252 efx_sram_byte_alternate_set( 253 __in size_t row, 254 __in boolean_t negate, 255 __out efx_qword_t *eqp) 256 { 257 _NOTE(ARGUNUSED(row)) 258 259 EFX_POPULATE_QWORD_2(*eqp, 260 EFX_DWORD_0, (negate) ? 0x00ff00ff : 0xff00ff00, 261 EFX_DWORD_1, (negate) ? 0x00ff00ff : 0xff00ff00); 262 } 263 264 static void 265 efx_sram_byte_changing_set( 266 __in size_t row, 267 __in boolean_t negate, 268 __out efx_qword_t *eqp) 269 { 270 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 271 unsigned int index; 272 273 for (index = 0; index < sizeof (efx_qword_t); index++) { 274 uint8_t byte; 275 276 if (offset / 256 == 0) 277 byte = (uint8_t)((offset % 257) % 256); 278 else 279 byte = (uint8_t)(~((offset - 8) % 257) % 256); 280 281 eqp->eq_u8[index] = (negate) ? ~byte : byte; 282 } 283 } 284 285 static void 286 efx_sram_bit_sweep_set( 287 __in size_t row, 288 __in boolean_t negate, 289 __out efx_qword_t *eqp) 290 { 291 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 292 293 if (negate) { 294 EFX_SET_QWORD(*eqp); 295 EFX_CLEAR_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64); 296 } else { 297 EFX_ZERO_QWORD(*eqp); 298 EFX_SET_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64); 299 } 300 } 301 302 efx_sram_pattern_fn_t __efx_sram_pattern_fns[] = { 303 efx_sram_byte_increment_set, 304 efx_sram_all_the_same_set, 305 efx_sram_bit_alternate_set, 306 efx_sram_byte_alternate_set, 307 efx_sram_byte_changing_set, 308 efx_sram_bit_sweep_set 309 }; 310 311 __checkReturn efx_rc_t 312 efx_sram_test( 313 __in efx_nic_t *enp, 314 __in efx_pattern_type_t type) 315 { 316 efx_sram_pattern_fn_t func; 317 318 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 319 320 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 321 322 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX)); 323 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX)); 324 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV)); 325 326 /* SRAM testing is only available on Siena. */ 327 if (enp->en_family != EFX_FAMILY_SIENA) 328 return (0); 329 330 /* Select pattern generator */ 331 EFSYS_ASSERT3U(type, <, EFX_PATTERN_NTYPES); 332 func = __efx_sram_pattern_fns[type]; 333 334 return (siena_sram_test(enp, func)); 335 } 336 337 #endif /* EFSYS_OPT_DIAG */ 338