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