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