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