1 /*- 2 * Copyright 2007-2009 Solarflare Communications Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include <sys/cdefs.h> 27 __FBSDID("$FreeBSD$"); 28 29 #include "efsys.h" 30 #include "efx.h" 31 #include "efx_types.h" 32 #include "efx_regs.h" 33 #include "efx_impl.h" 34 35 __checkReturn int 36 efx_sram_buf_tbl_set( 37 __in efx_nic_t *enp, 38 __in uint32_t id, 39 __in efsys_mem_t *esmp, 40 __in size_t n) 41 { 42 efx_qword_t qword; 43 uint32_t start = id; 44 uint32_t stop = start + n; 45 efsys_dma_addr_t addr; 46 efx_oword_t oword; 47 unsigned int count; 48 int rc; 49 50 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 51 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 52 53 if (stop >= EFX_BUF_TBL_SIZE) { 54 rc = EFBIG; 55 goto fail1; 56 } 57 58 /* Add the entries into the buffer table */ 59 addr = EFSYS_MEM_ADDR(esmp); 60 for (id = start; id != stop; id++) { 61 EFX_POPULATE_QWORD_5(qword, 62 FRF_AZ_IP_DAT_BUF_SIZE, 0, FRF_AZ_BUF_ADR_REGION, 0, 63 FRF_AZ_BUF_ADR_FBUF_DW0, 64 (uint32_t)((addr >> 12) & 0xffffffff), 65 FRF_AZ_BUF_ADR_FBUF_DW1, 66 (uint32_t)((addr >> 12) >> 32), 67 FRF_AZ_BUF_OWNER_ID_FBUF, 0); 68 69 EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_FULL_TBL, 70 id, &qword); 71 72 addr += EFX_BUF_SIZE; 73 } 74 75 EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1); 76 77 /* Flush the write buffer */ 78 EFX_POPULATE_OWORD_2(oword, FRF_AZ_BUF_UPD_CMD, 1, 79 FRF_AZ_BUF_CLR_CMD, 0); 80 EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword); 81 82 /* Poll for the last entry being written to the buffer table */ 83 EFSYS_ASSERT3U(id, ==, stop); 84 addr -= EFX_BUF_SIZE; 85 86 count = 0; 87 do { 88 EFSYS_PROBE1(wait, unsigned int, count); 89 90 /* Spin for 1 ms */ 91 EFSYS_SPIN(1000); 92 93 EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL, 94 id - 1, &qword); 95 96 if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) == 97 (uint32_t)((addr >> 12) & 0xffffffff) && 98 EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) == 99 (uint32_t)((addr >> 12) >> 32)) 100 goto verify; 101 102 } while (++count < 100); 103 104 rc = ETIMEDOUT; 105 goto fail2; 106 107 verify: 108 /* Verify the rest of the entries in the buffer table */ 109 while (--id != start) { 110 addr -= EFX_BUF_SIZE; 111 112 /* Read the buffer table entry */ 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 rc = EFAULT; 121 goto fail3; 122 } 123 } 124 125 return (0); 126 127 fail3: 128 EFSYS_PROBE(fail3); 129 130 id = stop; 131 132 fail2: 133 EFSYS_PROBE(fail2); 134 135 EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0, 136 FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, id - 1, 137 FRF_AZ_BUF_CLR_START_ID, start); 138 EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword); 139 140 fail1: 141 EFSYS_PROBE1(fail1, int, rc); 142 143 return (rc); 144 } 145 146 void 147 efx_sram_buf_tbl_clear( 148 __in efx_nic_t *enp, 149 __in uint32_t id, 150 __in size_t n) 151 { 152 efx_oword_t oword; 153 uint32_t start = id; 154 uint32_t stop = start + n; 155 156 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 157 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 158 159 EFSYS_ASSERT3U(stop, <, EFX_BUF_TBL_SIZE); 160 161 EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1); 162 163 EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0, 164 FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, stop - 1, 165 FRF_AZ_BUF_CLR_START_ID, start); 166 EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword); 167 } 168 169 170 #if EFSYS_OPT_DIAG 171 172 static void 173 efx_sram_byte_increment_set( 174 __in size_t row, 175 __in boolean_t negate, 176 __out efx_qword_t *eqp) 177 { 178 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 179 unsigned int index; 180 181 _NOTE(ARGUNUSED(negate)) 182 183 for (index = 0; index < sizeof (efx_qword_t); index++) 184 eqp->eq_u8[index] = offset + index; 185 } 186 187 static void 188 efx_sram_all_the_same_set( 189 __in size_t row, 190 __in boolean_t negate, 191 __out efx_qword_t *eqp) 192 { 193 _NOTE(ARGUNUSED(row)) 194 195 if (negate) 196 EFX_SET_QWORD(*eqp); 197 else 198 EFX_ZERO_QWORD(*eqp); 199 } 200 201 static void 202 efx_sram_bit_alternate_set( 203 __in size_t row, 204 __in boolean_t negate, 205 __out efx_qword_t *eqp) 206 { 207 _NOTE(ARGUNUSED(row)) 208 209 EFX_POPULATE_QWORD_2(*eqp, 210 EFX_DWORD_0, (negate) ? 0x55555555 : 0xaaaaaaaa, 211 EFX_DWORD_1, (negate) ? 0x55555555 : 0xaaaaaaaa); 212 } 213 214 static void 215 efx_sram_byte_alternate_set( 216 __in size_t row, 217 __in boolean_t negate, 218 __out efx_qword_t *eqp) 219 { 220 _NOTE(ARGUNUSED(row)) 221 222 EFX_POPULATE_QWORD_2(*eqp, 223 EFX_DWORD_0, (negate) ? 0x00ff00ff : 0xff00ff00, 224 EFX_DWORD_1, (negate) ? 0x00ff00ff : 0xff00ff00); 225 } 226 227 static void 228 efx_sram_byte_changing_set( 229 __in size_t row, 230 __in boolean_t negate, 231 __out efx_qword_t *eqp) 232 { 233 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 234 unsigned int index; 235 236 for (index = 0; index < sizeof (efx_qword_t); index++) { 237 uint8_t byte; 238 239 if (offset / 256 == 0) 240 byte = (uint8_t)((offset % 257) % 256); 241 else 242 byte = (uint8_t)(~((offset - 8) % 257) % 256); 243 244 eqp->eq_u8[index] = (negate) ? ~byte : byte; 245 } 246 } 247 248 static void 249 efx_sram_bit_sweep_set( 250 __in size_t row, 251 __in boolean_t negate, 252 __out efx_qword_t *eqp) 253 { 254 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 255 256 if (negate) { 257 EFX_SET_QWORD(*eqp); 258 EFX_CLEAR_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64); 259 } else { 260 EFX_ZERO_QWORD(*eqp); 261 EFX_SET_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64); 262 } 263 } 264 265 efx_sram_pattern_fn_t __cs __efx_sram_pattern_fns[] = { 266 efx_sram_byte_increment_set, 267 efx_sram_all_the_same_set, 268 efx_sram_bit_alternate_set, 269 efx_sram_byte_alternate_set, 270 efx_sram_byte_changing_set, 271 efx_sram_bit_sweep_set 272 }; 273 274 __checkReturn int 275 efx_sram_test( 276 __in efx_nic_t *enp, 277 __in efx_pattern_type_t type) 278 { 279 efx_nic_ops_t *enop = enp->en_enop; 280 efx_sram_pattern_fn_t func; 281 282 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 283 284 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 285 286 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX)); 287 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX)); 288 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV)); 289 290 /* Select pattern generator */ 291 EFSYS_ASSERT3U(type, <, EFX_PATTERN_NTYPES); 292 func = __efx_sram_pattern_fns[type]; 293 294 return (enop->eno_sram_test(enp, func)); 295 } 296 297 #endif /* EFSYS_OPT_DIAG */ 298