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