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 #if EFSYS_OPT_QSTATS
  33 #define EFX_TX_QSTAT_INCR(_etp, _stat)                                  \
  34         do {                                                            \
  35                 (_etp)->et_stat[_stat]++;                            \
  36         _NOTE(CONSTANTCONDITION)                                        \
  37         } while (B_FALSE)
  38 #else
  39 #define EFX_TX_QSTAT_INCR(_etp, _stat)
  40 #endif
  41 
  42 
  43 
  44         __checkReturn   int
  45 efx_tx_init(
  46         __in            efx_nic_t *enp)
  47 {
  48         efx_oword_t oword;
  49         int rc;
  50 
  51         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  52         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
  53 
  54         if (!(enp->en_mod_flags & EFX_MOD_EV)) {
  55                 rc = EINVAL;
  56                 goto fail1;
  57         }
  58 
  59         if (enp->en_mod_flags & EFX_MOD_TX) {
  60                 rc = EINVAL;
  61                 goto fail2;
  62         }
  63 
  64         EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
  65 
  66         /*
  67          * Disable the timer-based TX DMA backoff and allow TX DMA to be
  68          * controlled by the RX FIFO fill level (although always allow a
  69          * minimal trickle).
  70          */
  71         EFX_BAR_READO(enp, FR_AZ_TX_RESERVED_REG, &oword);
  72         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER, 0xfe);
  73         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER_EN, 1);
  74         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_ONE_PKT_PER_Q, 1);
  75         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PUSH_EN, 0);
  76         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DIS_NON_IP_EV, 1);
  77         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_THRESHOLD, 2);
  78         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_WD_TMR, 0x3fffff);
  79 
  80         /*
  81          * Filter all packets less than 14 bytes to avoid parsing
  82          * errors.
  83          */
  84         EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
  85         EFX_BAR_WRITEO(enp, FR_AZ_TX_RESERVED_REG, &oword);
  86 
  87         /*
  88          * Do not set TX_NO_EOP_DISC_EN, since it limits packets to 16
  89          * descriptors (which is bad).
  90          */
  91         EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
  92         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_NO_EOP_DISC_EN, 0);
  93         EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
  94 
  95         enp->en_mod_flags |= EFX_MOD_TX;
  96         return (0);
  97 
  98 fail2:
  99         EFSYS_PROBE(fail2);
 100 fail1:
 101         EFSYS_PROBE1(fail1, int, rc);
 102 
 103         return (rc);
 104 }
 105 
 106 #if EFSYS_OPT_FILTER
 107 extern  __checkReturn   int
 108 efx_tx_filter_insert(
 109         __in            efx_txq_t *etp,
 110         __inout         efx_filter_spec_t *spec)
 111 {
 112         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
 113         EFSYS_ASSERT3P(spec, !=, NULL);
 114 
 115         spec->efs_dmaq_id = (uint16_t)etp->et_index;
 116         return (efx_filter_insert_filter(etp->et_enp, spec, B_FALSE));
 117 }
 118 #endif
 119 
 120 #if EFSYS_OPT_FILTER
 121 extern  __checkReturn   int
 122 efx_tx_filter_remove(
 123         __in            efx_txq_t *etp,
 124         __inout         efx_filter_spec_t *spec)
 125 {
 126         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
 127         EFSYS_ASSERT3P(spec, !=, NULL);
 128 
 129         spec->efs_dmaq_id = (uint16_t)etp->et_index;
 130         return (efx_filter_remove_filter(etp->et_enp, spec));
 131 }
 132 #endif
 133 
 134 #define EFX_TX_DESC(_etp, _addr, _size, _eop, _added)                   \
 135         do {                                                            \
 136                 unsigned int id;                                        \
 137                 size_t offset;                                          \
 138                 efx_qword_t qword;                                      \
 139                                                                         \
 140                 id = (_added)++ & (_etp)->et_mask;                       \
 141                 offset = id * sizeof (efx_qword_t);                     \
 142                                                                         \
 143                 EFSYS_PROBE5(tx_post, unsigned int, (_etp)->et_index,        \
 144                     unsigned int, id, efsys_dma_addr_t, (_addr),        \
 145                     size_t, (_size), boolean_t, (_eop));                \
 146                                                                         \
 147                 EFX_POPULATE_QWORD_4(qword,                             \
 148                     FSF_AZ_TX_KER_CONT, (_eop) ? 0 : 1,                 \
 149                     FSF_AZ_TX_KER_BYTE_COUNT, (uint32_t)(_size),        \
 150                     FSF_AZ_TX_KER_BUF_ADDR_DW0,                         \
 151                     (uint32_t)((_addr) & 0xffffffff),                       \
 152                     FSF_AZ_TX_KER_BUF_ADDR_DW1,                         \
 153                     (uint32_t)((_addr) >> 32));                           \
 154                 EFSYS_MEM_WRITEQ((_etp)->et_esmp, offset, &qword);       \
 155                                                                         \
 156                 _NOTE(CONSTANTCONDITION)                                \
 157         } while (B_FALSE)
 158 
 159         __checkReturn   int
 160 efx_tx_qpost(
 161         __in            efx_txq_t *etp,
 162         __in_ecount(n)  efx_buffer_t *eb,
 163         __in            unsigned int n,
 164         __in            unsigned int completed,
 165         __inout         unsigned int *addedp)
 166 {
 167         unsigned int added = *addedp;
 168         unsigned int i;
 169         int rc = ENOSPC;
 170 
 171         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
 172 
 173         if (added - completed + n > EFX_TXQ_LIMIT(etp->et_mask + 1))
 174                 goto fail1;
 175 
 176         for (i = 0; i < n; i++) {
 177                 efx_buffer_t *ebp = &eb[i];
 178                 efsys_dma_addr_t start = ebp->eb_addr;
 179                 size_t size = ebp->eb_size;
 180                 efsys_dma_addr_t end = start + size;
 181 
 182                 /* Fragments must not span 4k boundaries. */
 183                 EFSYS_ASSERT(P2ROUNDUP(start + 1, 4096) >= end);
 184 
 185                 EFX_TX_DESC(etp, start, size, ebp->eb_eop, added);
 186         }
 187 
 188         EFX_TX_QSTAT_INCR(etp, TX_POST);
 189 
 190         *addedp = added;
 191         return (0);
 192 
 193 fail1:
 194         EFSYS_PROBE1(fail1, int, rc);
 195 
 196         return (rc);
 197 }
 198 
 199                 void
 200 efx_tx_qpush(
 201         __in    efx_txq_t *etp,
 202         __in    unsigned int added)
 203 {
 204         efx_nic_t *enp = etp->et_enp;
 205         uint32_t wptr;
 206         efx_dword_t dword;
 207         efx_oword_t oword;
 208 
 209         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
 210 
 211         /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
 212         EFSYS_PIO_WRITE_BARRIER();
 213 
 214         /* Push the populated descriptors out */
 215         wptr = added & etp->et_mask;
 216 
 217         EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_DESC_WPTR, wptr);
 218 
 219         /* Only write the third DWORD */
 220         EFX_POPULATE_DWORD_1(dword,
 221             EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3));
 222         EFX_BAR_TBL_WRITED3(enp, FR_BZ_TX_DESC_UPD_REGP0,
 223                             etp->et_index, &dword, B_FALSE);
 224 }
 225 
 226 #define EFX_MAX_PACE_VALUE 20
 227 
 228         __checkReturn   int
 229 efx_tx_qpace(
 230         __in            efx_txq_t *etp,
 231         __in            unsigned int ns)
 232 {
 233         efx_nic_t *enp = etp->et_enp;
 234         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 235         efx_oword_t oword;
 236         unsigned int pace_val;
 237         unsigned int timer_period;
 238         int rc;
 239 
 240         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
 241 
 242         if (ns == 0) {
 243                 pace_val = 0;
 244         } else {
 245                 /*
 246                  * The pace_val to write into the table is s.t
 247                  * ns <= timer_period * (2 ^ pace_val)
 248                  */
 249                 timer_period = 104 / encp->enc_clk_mult;
 250                 for (pace_val = 1; pace_val <= EFX_MAX_PACE_VALUE; pace_val++) {
 251                         if ((timer_period << pace_val) >= ns)
 252                                 break;
 253                 }
 254         }
 255         if (pace_val > EFX_MAX_PACE_VALUE) {
 256                 rc = EINVAL;
 257                 goto fail1;
 258         }
 259 
 260         /* Update the pacing table */
 261         EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_PACE, pace_val);
 262         EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_PACE_TBL, etp->et_index, &oword);
 263 
 264         return (0);
 265 
 266 fail1:
 267         EFSYS_PROBE1(fail1, int, rc);
 268 
 269         return (rc);
 270 }
 271 
 272                 void
 273 efx_tx_qflush(
 274         __in    efx_txq_t *etp)
 275 {
 276         efx_nic_t *enp = etp->et_enp;
 277         efx_oword_t oword;
 278         uint32_t label;
 279 
 280         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
 281 
 282         efx_tx_qpace(etp, 0);
 283 
 284         label = etp->et_index;
 285 
 286         /* Flush the queue */
 287         EFX_POPULATE_OWORD_2(oword, FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
 288             FRF_AZ_TX_FLUSH_DESCQ, label);
 289         EFX_BAR_WRITEO(enp, FR_AZ_TX_FLUSH_DESCQ_REG, &oword);
 290 }
 291 
 292                 void
 293 efx_tx_qenable(
 294         __in    efx_txq_t *etp)
 295 {
 296         efx_nic_t *enp = etp->et_enp;
 297         efx_oword_t oword;
 298 
 299         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
 300 
 301         EFX_BAR_TBL_READO(enp, FR_AZ_TX_DESC_PTR_TBL,
 302                             etp->et_index, &oword);
 303 
 304         EFSYS_PROBE5(tx_descq_ptr, unsigned int, etp->et_index,
 305             uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_3),
 306             uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_2),
 307             uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_1),
 308             uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_0));
 309 
 310         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DC_HW_RPTR, 0);
 311         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_HW_RPTR, 0);
 312         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_EN, 1);
 313 
 314         EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
 315                             etp->et_index, &oword);
 316 }
 317 
 318         __checkReturn   int
 319 efx_tx_qcreate(
 320         __in            efx_nic_t *enp,
 321         __in            unsigned int index,
 322         __in            unsigned int label,
 323         __in            efsys_mem_t *esmp,
 324         __in            size_t n,
 325         __in            uint32_t id,
 326         __in            uint16_t flags,
 327         __in            efx_evq_t *eep,
 328         __deref_out     efx_txq_t **etpp)
 329 {
 330         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 331         efx_txq_t *etp;
 332         efx_oword_t oword;
 333         uint32_t size;
 334         int rc;
 335 
 336         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 337         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
 338 
 339         EFX_STATIC_ASSERT(EFX_EV_TX_NLABELS ==
 340             (1 << FRF_AZ_TX_DESCQ_LABEL_WIDTH));
 341         EFSYS_ASSERT3U(label, <, EFX_EV_TX_NLABELS);
 342         EFSYS_ASSERT3U(enp->en_tx_qcount + 1, <, encp->enc_txq_limit);
 343 
 344         if (!ISP2(n) || !(n & EFX_TXQ_NDESCS_MASK)) {
 345                 rc = EINVAL;
 346                 goto fail1;
 347         }
 348         if (index >= encp->enc_txq_limit) {
 349                 rc = EINVAL;
 350                 goto fail2;
 351         }
 352         for (size = 0; (1 << size) <= (EFX_TXQ_MAXNDESCS / EFX_TXQ_MINNDESCS);
 353             size++)
 354                 if ((1 << size) == (int)(n / EFX_TXQ_MINNDESCS))
 355                         break;
 356         if (id + (1 << size) >= encp->enc_buftbl_limit) {
 357                 rc = EINVAL;
 358                 goto fail3;
 359         }
 360 
 361         /* Allocate an TXQ object */
 362         EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_txq_t), etp);
 363 
 364         if (etp == NULL) {
 365                 rc = ENOMEM;
 366                 goto fail4;
 367         }
 368 
 369         etp->et_magic = EFX_TXQ_MAGIC;
 370         etp->et_enp = enp;
 371         etp->et_index = index;
 372         etp->et_mask = n - 1;
 373         etp->et_esmp = esmp;
 374 
 375         /* Set up the new descriptor queue */
 376         EFX_POPULATE_OWORD_6(oword,
 377             FRF_AZ_TX_DESCQ_BUF_BASE_ID, id,
 378             FRF_AZ_TX_DESCQ_EVQ_ID, eep->ee_index,
 379             FRF_AZ_TX_DESCQ_OWNER_ID, 0,
 380             FRF_AZ_TX_DESCQ_LABEL, label,
 381             FRF_AZ_TX_DESCQ_SIZE, size,
 382             FRF_AZ_TX_DESCQ_TYPE, 0);
 383 
 384         EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_NON_IP_DROP_DIS, 1);
 385         EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_IP_CHKSM_DIS,
 386             (flags & EFX_CKSUM_IPV4) ? 0 : 1);
 387         EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_TCP_CHKSM_DIS,
 388             (flags & EFX_CKSUM_TCPUDP) ? 0 : 1);
 389 
 390         EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
 391             etp->et_index, &oword);
 392 
 393         enp->en_tx_qcount++;
 394         *etpp = etp;
 395         return (0);
 396 
 397 fail4:
 398         EFSYS_PROBE(fail4);
 399 fail3:
 400         EFSYS_PROBE(fail3);
 401 fail2:
 402         EFSYS_PROBE(fail2);
 403 fail1:
 404         EFSYS_PROBE1(fail1, int, rc);
 405 
 406         return (rc);
 407 }
 408 
 409 #if EFSYS_OPT_NAMES
 410 /* START MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock 78ca9ab00287fffb */
 411 static const char       __cs * __cs __efx_tx_qstat_name[] = {
 412         "post",
 413         "unaligned_split",
 414 };
 415 /* END MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock */
 416 
 417                 const char __cs *
 418 efx_tx_qstat_name(
 419         __in    efx_nic_t *enp,
 420         __in    unsigned int id)
 421 {
 422         _NOTE(ARGUNUSED(enp))
 423         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 424         EFSYS_ASSERT3U(id, <, TX_NQSTATS);
 425 
 426         return (__efx_tx_qstat_name[id]);
 427 }
 428 #endif  /* EFSYS_OPT_NAMES */
 429 
 430 #if EFSYS_OPT_QSTATS
 431                                         void
 432 efx_tx_qstats_update(
 433         __in                            efx_txq_t *etp,
 434         __inout_ecount(TX_NQSTATS)      efsys_stat_t *stat)
 435 {
 436         unsigned int id;
 437 
 438         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
 439 
 440         for (id = 0; id < TX_NQSTATS; id++) {
 441                 efsys_stat_t *essp = &stat[id];
 442 
 443                 EFSYS_STAT_INCR(essp, etp->et_stat[id]);
 444                 etp->et_stat[id] = 0;
 445         }
 446 }
 447 #endif  /* EFSYS_OPT_QSTATS */
 448 
 449                 void
 450 efx_tx_qdestroy(
 451         __in    efx_txq_t *etp)
 452 {
 453         efx_nic_t *enp = etp->et_enp;
 454         efx_oword_t oword;
 455 
 456         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
 457 
 458         EFSYS_ASSERT(enp->en_tx_qcount != 0);
 459         --enp->en_tx_qcount;
 460 
 461         /* Purge descriptor queue */
 462         EFX_ZERO_OWORD(oword);
 463 
 464         EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
 465                             etp->et_index, &oword);
 466 
 467         /* Free the TXQ object */
 468         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp);
 469 }
 470 
 471                 void
 472 efx_tx_fini(
 473         __in    efx_nic_t *enp)
 474 {
 475         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 476         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
 477         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
 478         EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
 479 
 480         enp->en_mod_flags &= ~EFX_MOD_TX;
 481 }