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 */