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