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