1175645Sjhb/*- 2175645Sjhb * SPDX-License-Identifier: BSD-2-Clause 3175645Sjhb * 4175645Sjhb * Copyright (c) 2007-2016 Solarflare Communications Inc. 5175645Sjhb * All rights reserved. 6175645Sjhb * 7175645Sjhb * Redistribution and use in source and binary forms, with or without 8175645Sjhb * modification, are permitted provided that the following conditions are met: 9175645Sjhb * 10175645Sjhb * 1. Redistributions of source code must retain the above copyright notice, 11175645Sjhb * this list of conditions and the following disclaimer. 12175645Sjhb * 2. Redistributions in binary form must reproduce the above copyright notice, 13175645Sjhb * this list of conditions and the following disclaimer in the documentation 14175645Sjhb * and/or other materials provided with the distribution. 15175645Sjhb * 16175645Sjhb * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17175645Sjhb * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18175645Sjhb * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19175645Sjhb * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20175645Sjhb * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21175645Sjhb * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22175645Sjhb * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23175645Sjhb * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24175645Sjhb * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25175645Sjhb * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26175645Sjhb * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27175645Sjhb * 28175645Sjhb * The views and conclusions contained in the software and documentation are 29175645Sjhb * those of the authors and should not be interpreted as representing official 30175645Sjhb * policies, either expressed or implied, of the FreeBSD Project. 31175645Sjhb */ 32175809Sjhb 33175809Sjhb#include <sys/cdefs.h> 34175645Sjhb#include "efx.h" 35175645Sjhb#include "efx_impl.h" 36175645Sjhb 37175809Sjhb __checkReturn efx_rc_t 38175809Sjhbefx_sram_buf_tbl_set( 39175809Sjhb __in efx_nic_t *enp, 40183359Sjhb __in uint32_t id, 41175645Sjhb __in efsys_mem_t *esmp, 42175645Sjhb __in size_t n) 43175645Sjhb{ 44175645Sjhb efx_qword_t qword; 45175645Sjhb uint32_t start = id; 46175809Sjhb uint32_t stop = start + n; 47175645Sjhb efsys_dma_addr_t addr; 48175645Sjhb efx_oword_t oword; 49175645Sjhb unsigned int count; 50175809Sjhb efx_rc_t rc; 51175809Sjhb 52175809Sjhb EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 53175774Sjhb EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 54175774Sjhb 55175774Sjhb#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 56175774Sjhb if (enp->en_family == EFX_FAMILY_HUNTINGTON || 57175809Sjhb enp->en_family == EFX_FAMILY_MEDFORD || 58175809Sjhb enp->en_family == EFX_FAMILY_MEDFORD2) { 59178670Sjhb /* 60178670Sjhb * FIXME: the efx_sram_buf_tbl_*() functionality needs to be 61175809Sjhb * pulled inside the Falcon/Siena queue create/destroy code, 62175809Sjhb * and then the original functions can be removed (see bug30834 63175809Sjhb * comment #1). But, for now, we just ensure that they are 64175645Sjhb * no-ops for EF10, to allow bringing up existing drivers 65175645Sjhb * without modification. 66175645Sjhb */ 67175645Sjhb 68175645Sjhb return (0); 69175645Sjhb } 70175645Sjhb#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ 71175645Sjhb 72175645Sjhb if (stop >= EFX_BUF_TBL_SIZE) { 73175645Sjhb rc = EFBIG; 74175645Sjhb goto fail1; 75175774Sjhb } 76175645Sjhb 77175645Sjhb /* Add the entries into the buffer table */ 78175645Sjhb addr = EFSYS_MEM_ADDR(esmp); 79175774Sjhb for (id = start; id != stop; id++) { 80175774Sjhb EFX_POPULATE_QWORD_5(qword, 81175774Sjhb FRF_AZ_IP_DAT_BUF_SIZE, 0, FRF_AZ_BUF_ADR_REGION, 0, 82175774Sjhb FRF_AZ_BUF_ADR_FBUF_DW0, 83175774Sjhb (uint32_t)((addr >> 12) & 0xffffffff), 84175774Sjhb FRF_AZ_BUF_ADR_FBUF_DW1, 85175645Sjhb (uint32_t)((addr >> 12) >> 32), 86175774Sjhb FRF_AZ_BUF_OWNER_ID_FBUF, 0); 87175774Sjhb 88175774Sjhb EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_FULL_TBL, 89175774Sjhb id, &qword); 90175774Sjhb 91175774Sjhb addr += EFX_BUF_SIZE; 92175774Sjhb } 93175774Sjhb 94175774Sjhb EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1); 95175774Sjhb 96175774Sjhb /* Flush the write buffer */ 97175774Sjhb EFX_POPULATE_OWORD_2(oword, FRF_AZ_BUF_UPD_CMD, 1, 98175774Sjhb FRF_AZ_BUF_CLR_CMD, 0); 99175774Sjhb EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword); 100175774Sjhb 101175774Sjhb /* Poll for the last entry being written to the buffer table */ 102175774Sjhb EFSYS_ASSERT3U(id, ==, stop); 103175774Sjhb addr -= EFX_BUF_SIZE; 104175774Sjhb 105175774Sjhb count = 0; 106175774Sjhb do { 107175774Sjhb EFSYS_PROBE1(wait, unsigned int, count); 108175774Sjhb 109175774Sjhb /* Spin for 1 ms */ 110175774Sjhb EFSYS_SPIN(1000); 111175645Sjhb 112175645Sjhb EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL, 113175774Sjhb id - 1, &qword); 114175645Sjhb 115175774Sjhb if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) == 116175645Sjhb (uint32_t)((addr >> 12) & 0xffffffff) && 117178670Sjhb EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) == 118178670Sjhb (uint32_t)((addr >> 12) >> 32)) 119178670Sjhb goto verify; 120178670Sjhb 121178670Sjhb } while (++count < 100); 122178670Sjhb 123178670Sjhb rc = ETIMEDOUT; 124178670Sjhb goto fail2; 125175645Sjhb 126175774Sjhbverify: 127175774Sjhb /* Verify the rest of the entries in the buffer table */ 128175774Sjhb while (--id != start) { 129175774Sjhb addr -= EFX_BUF_SIZE; 130175774Sjhb 131175774Sjhb /* Read the buffer table entry */ 132175774Sjhb EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL, 133175774Sjhb id - 1, &qword); 134175774Sjhb 135175774Sjhb if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) != 136175774Sjhb (uint32_t)((addr >> 12) & 0xffffffff) || 137175774Sjhb EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) != 138175645Sjhb (uint32_t)((addr >> 12) >> 32)) { 139175774Sjhb rc = EFAULT; 140175645Sjhb goto fail3; 141175645Sjhb } 142175645Sjhb } 143175645Sjhb 144175645Sjhb return (0); 145175645Sjhb 146175645Sjhbfail3: 147175645Sjhb EFSYS_PROBE(fail3); 148175645Sjhb 149175807Sjhb id = stop; 150175645Sjhb 151175807Sjhbfail2: 152175807Sjhb EFSYS_PROBE(fail2); 153175807Sjhb 154175807Sjhb EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0, 155175645Sjhb FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, id - 1, 156175645Sjhb FRF_AZ_BUF_CLR_START_ID, start); 157175645Sjhb EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword); 158175645Sjhb 159175645Sjhbfail1: 160175645Sjhb EFSYS_PROBE1(fail1, efx_rc_t, rc); 161175645Sjhb 162175645Sjhb return (rc); 163175774Sjhb} 164175774Sjhb 165175645Sjhb void 166175774Sjhbefx_sram_buf_tbl_clear( 167175645Sjhb __in efx_nic_t *enp, 168178670Sjhb __in uint32_t id, 169178670Sjhb __in size_t n) 170175645Sjhb{ 171175645Sjhb efx_oword_t oword; 172175645Sjhb uint32_t start = id; 173178670Sjhb uint32_t stop = start + n; 174175775Sjhb 175175645Sjhb EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 176175774Sjhb EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 177175774Sjhb 178175774Sjhb#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 179175775Sjhb if (enp->en_family == EFX_FAMILY_HUNTINGTON || 180175645Sjhb enp->en_family == EFX_FAMILY_MEDFORD || 181175645Sjhb enp->en_family == EFX_FAMILY_MEDFORD2) { 182175774Sjhb /* 183175774Sjhb * FIXME: the efx_sram_buf_tbl_*() functionality needs to be 184175775Sjhb * pulled inside the Falcon/Siena queue create/destroy code, 185175774Sjhb * and then the original functions can be removed (see bug30834 186175774Sjhb * comment #1). But, for now, we just ensure that they are 187175645Sjhb * no-ops for EF10, to allow bringing up existing drivers 188175645Sjhb * without modification. 189175645Sjhb */ 190175645Sjhb 191175645Sjhb return; 192175645Sjhb } 193175645Sjhb#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ 194175645Sjhb 195175645Sjhb EFSYS_ASSERT3U(stop, <, EFX_BUF_TBL_SIZE); 196175645Sjhb 197175645Sjhb EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1); 198175645Sjhb 199175645Sjhb EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0, 200175645Sjhb FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, stop - 1, 201210424Savg FRF_AZ_BUF_CLR_START_ID, start); 202210424Savg EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword); 203210424Savg} 204210424Savg 205210424Savg#if EFSYS_OPT_DIAG 206210424Savg 207210424Savgstatic void 208210424Savgefx_sram_byte_increment_set( 209210424Savg __in size_t row, 210210424Savg __in boolean_t negate, 211210424Savg __out efx_qword_t *eqp) 212210424Savg{ 213210424Savg size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 214210424Savg unsigned int index; 215210424Savg 216210424Savg _NOTE(ARGUNUSED(negate)) 217210424Savg 218210424Savg for (index = 0; index < sizeof (efx_qword_t); index++) 219210424Savg eqp->eq_u8[index] = offset + index; 220178634Sjhb} 221175645Sjhb 222183359Sjhbstatic void 223183556Sjhbefx_sram_all_the_same_set( 224175645Sjhb __in size_t row, 225175645Sjhb __in boolean_t negate, 226210424Savg __out efx_qword_t *eqp) 227183359Sjhb{ 228175645Sjhb _NOTE(ARGUNUSED(row)) 229175774Sjhb 230175645Sjhb if (negate) 231175774Sjhb EFX_SET_QWORD(*eqp); 232175645Sjhb else 233175645Sjhb EFX_ZERO_QWORD(*eqp); 234175645Sjhb} 235175645Sjhb 236175774Sjhbstatic void 237175645Sjhbefx_sram_bit_alternate_set( 238175645Sjhb __in size_t row, 239175774Sjhb __in boolean_t negate, 240175774Sjhb __out efx_qword_t *eqp) 241175645Sjhb{ 242175645Sjhb _NOTE(ARGUNUSED(row)) 243183359Sjhb 244183359Sjhb EFX_POPULATE_QWORD_2(*eqp, 245183359Sjhb EFX_DWORD_0, (negate) ? 0x55555555 : 0xaaaaaaaa, 246183359Sjhb EFX_DWORD_1, (negate) ? 0x55555555 : 0xaaaaaaaa); 247210424Savg} 248210424Savg 249210424Savgstatic void 250183359Sjhbefx_sram_byte_alternate_set( 251183359Sjhb __in size_t row, 252183359Sjhb __in boolean_t negate, 253183359Sjhb __out efx_qword_t *eqp) 254183359Sjhb{ 255183359Sjhb _NOTE(ARGUNUSED(row)) 256183359Sjhb 257178634Sjhb EFX_POPULATE_QWORD_2(*eqp, 258183359Sjhb EFX_DWORD_0, (negate) ? 0x00ff00ff : 0xff00ff00, 259183359Sjhb EFX_DWORD_1, (negate) ? 0x00ff00ff : 0xff00ff00); 260183359Sjhb} 261175774Sjhb 262175774Sjhbstatic void 263175774Sjhbefx_sram_byte_changing_set( 264175774Sjhb __in size_t row, 265183359Sjhb __in boolean_t negate, 266175774Sjhb __out efx_qword_t *eqp) 267175774Sjhb{ 268175774Sjhb size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 269175774Sjhb unsigned int index; 270178670Sjhb 271175774Sjhb for (index = 0; index < sizeof (efx_qword_t); index++) { 272175774Sjhb uint8_t byte; 273175774Sjhb 274175774Sjhb if (offset / 256 == 0) 275175774Sjhb byte = (uint8_t)((offset % 257) % 256); 276178670Sjhb else 277178670Sjhb byte = (uint8_t)(~((offset - 8) % 257) % 256); 278178670Sjhb 279175774Sjhb eqp->eq_u8[index] = (negate) ? ~byte : byte; 280175774Sjhb } 281175774Sjhb} 282175774Sjhb 283175774Sjhbstatic void 284175774Sjhbefx_sram_bit_sweep_set( 285175774Sjhb __in size_t row, 286175774Sjhb __in boolean_t negate, 287175774Sjhb __out efx_qword_t *eqp) 288175774Sjhb{ 289175774Sjhb size_t offset = row * FR_AZ_SRM_DBG_REG_STEP; 290175774Sjhb 291175645Sjhb if (negate) { 292175645Sjhb EFX_SET_QWORD(*eqp); 293175774Sjhb EFX_CLEAR_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64); 294175774Sjhb } else { 295175774Sjhb EFX_ZERO_QWORD(*eqp); 296175645Sjhb EFX_SET_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64); 297175645Sjhb } 298178634Sjhb} 299175774Sjhb 300175774Sjhbefx_sram_pattern_fn_t __efx_sram_pattern_fns[] = { 301175774Sjhb efx_sram_byte_increment_set, 302175774Sjhb efx_sram_all_the_same_set, 303175774Sjhb efx_sram_bit_alternate_set, 304175809Sjhb efx_sram_byte_alternate_set, 305175774Sjhb efx_sram_byte_changing_set, 306210424Savg efx_sram_bit_sweep_set 307175809Sjhb}; 308210424Savg 309210424Savg __checkReturn efx_rc_t 310210424Savgefx_sram_test( 311210424Savg __in efx_nic_t *enp, 312175774Sjhb __in efx_pattern_type_t type) 313175774Sjhb{ 314175774Sjhb efx_sram_pattern_fn_t func; 315175809Sjhb 316175774Sjhb EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 317175774Sjhb 318175809Sjhb EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 319175809Sjhb 320175774Sjhb EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX)); 321175809Sjhb EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX)); 322175809Sjhb EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV)); 323175809Sjhb 324175809Sjhb /* SRAM testing is only available on Siena. */ 325175774Sjhb if (enp->en_family != EFX_FAMILY_SIENA) 326175809Sjhb return (0); 327175809Sjhb 328175809Sjhb /* Select pattern generator */ 329175809Sjhb EFSYS_ASSERT3U(type, <, EFX_PATTERN_NTYPES); 330175774Sjhb func = __efx_sram_pattern_fns[type]; 331175809Sjhb 332175809Sjhb return (siena_sram_test(enp, func)); 333175809Sjhb} 334175809Sjhb 335175645Sjhb#endif /* EFSYS_OPT_DIAG */ 336175809Sjhb