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 __checkReturn int 36 efx_rx_init( 37 __in efx_nic_t *enp) 38 { 39 efx_oword_t oword; 40 unsigned int index; 41 int rc; 42 43 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 44 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 45 46 if (!(enp->en_mod_flags & EFX_MOD_EV)) { 47 rc = EINVAL; 48 goto fail1; 49 } 50 51 if (enp->en_mod_flags & EFX_MOD_RX) { 52 rc = EINVAL; 53 goto fail2; 54 } 55 56 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword); 57 58 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_DESC_PUSH_EN, 0); 59 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 0); 60 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH, 0); 61 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP, 0); 62 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR, 0); 63 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_USR_BUF_SIZE, 0x3000 / 32); 64 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword); 65 66 /* Zero the RSS table */ 67 for (index = 0; index < FR_BZ_RX_INDIRECTION_TBL_ROWS; 68 index++) { 69 EFX_ZERO_OWORD(oword); 70 EFX_BAR_TBL_WRITEO(enp, FR_BZ_RX_INDIRECTION_TBL, 71 index, &oword); 72 } 73 74 enp->en_mod_flags |= EFX_MOD_RX; 75 return (0); 76 77 fail2: 78 EFSYS_PROBE(fail2); 79 fail1: 80 EFSYS_PROBE1(fail1, int, rc); 81 82 return (rc); 83 } 84 85 #if EFSYS_OPT_RX_HDR_SPLIT 86 __checkReturn int 87 efx_rx_hdr_split_enable( 88 __in efx_nic_t *enp, 89 __in unsigned int hdr_buf_size, 90 __in unsigned int pld_buf_size) 91 { 92 unsigned int nhdr32; 93 unsigned int npld32; 94 efx_oword_t oword; 95 int rc; 96 97 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 98 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX); 99 EFSYS_ASSERT3U(enp->en_family, >=, EFX_FAMILY_SIENA); 100 101 nhdr32 = hdr_buf_size / 32; 102 if ((nhdr32 == 0) || 103 (nhdr32 >= (1 << FRF_CZ_RX_HDR_SPLIT_HDR_BUF_SIZE_WIDTH)) || 104 ((hdr_buf_size % 32) != 0)) { 105 rc = EINVAL; 106 goto fail1; 107 } 108 109 npld32 = pld_buf_size / 32; 110 if ((npld32 == 0) || 111 (npld32 >= (1 << FRF_CZ_RX_HDR_SPLIT_PLD_BUF_SIZE_WIDTH)) || 112 ((pld_buf_size % 32) != 0)) { 113 rc = EINVAL; 114 goto fail2; 115 } 116 117 if (enp->en_rx_qcount > 0) { 118 rc = EBUSY; 119 goto fail3; 120 } 121 122 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword); 123 124 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_HDR_SPLIT_EN, 1); 125 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_HDR_SPLIT_HDR_BUF_SIZE, nhdr32); 126 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_HDR_SPLIT_PLD_BUF_SIZE, npld32); 127 128 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword); 129 130 return (0); 131 132 fail3: 133 EFSYS_PROBE(fail3); 134 fail2: 135 EFSYS_PROBE(fail2); 136 fail1: 137 EFSYS_PROBE1(fail1, int, rc); 138 139 return (rc); 140 } 141 #endif /* EFSYS_OPT_RX_HDR_SPLIT */ 142 143 144 #if EFSYS_OPT_RX_SCATTER 145 __checkReturn int 146 efx_rx_scatter_enable( 147 __in efx_nic_t *enp, 148 __in unsigned int buf_size) 149 { 150 unsigned int nbuf32; 151 efx_oword_t oword; 152 int rc; 153 154 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 155 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX); 156 EFSYS_ASSERT3U(enp->en_family, >=, EFX_FAMILY_FALCON); 157 158 nbuf32 = buf_size / 32; 159 if ((nbuf32 == 0) || 160 (nbuf32 >= (1 << FRF_BZ_RX_USR_BUF_SIZE_WIDTH)) || 161 ((buf_size % 32) != 0)) { 162 rc = EINVAL; 163 goto fail1; 164 } 165 166 if (enp->en_rx_qcount > 0) { 167 rc = EBUSY; 168 goto fail2; 169 } 170 171 /* Set scatter buffer size */ 172 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword); 173 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_USR_BUF_SIZE, nbuf32); 174 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword); 175 176 /* Enable scatter for packets not matching a filter */ 177 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 178 EFX_SET_OWORD_FIELD(oword, FRF_BZ_SCATTER_ENBL_NO_MATCH_Q, 1); 179 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 180 181 return (0); 182 183 fail2: 184 EFSYS_PROBE(fail2); 185 fail1: 186 EFSYS_PROBE1(fail1, int, rc); 187 188 return (rc); 189 } 190 #endif /* EFSYS_OPT_RX_SCATTER */ 191 192 193 #define EFX_RX_LFSR_HASH(_enp, _insert) \ 194 do { \ 195 efx_oword_t oword; \ 196 \ 197 EFX_BAR_READO((_enp), FR_AZ_RX_CFG_REG, &oword); \ 198 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 0); \ 199 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH, 0); \ 200 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP, 0); \ 201 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR, \ 202 (_insert) ? 1 : 0); \ 203 EFX_BAR_WRITEO((_enp), FR_AZ_RX_CFG_REG, &oword); \ 204 \ 205 if ((_enp)->en_family == EFX_FAMILY_SIENA) { \ 206 EFX_BAR_READO((_enp), FR_CZ_RX_RSS_IPV6_REG3, \ 207 &oword); \ 208 EFX_SET_OWORD_FIELD(oword, \ 209 FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 0); \ 210 EFX_BAR_WRITEO((_enp), FR_CZ_RX_RSS_IPV6_REG3, \ 211 &oword); \ 212 } \ 213 \ 214 _NOTE(CONSTANTCONDITION) \ 215 } while (B_FALSE) 216 217 #define EFX_RX_TOEPLITZ_IPV4_HASH(_enp, _insert, _ip, _tcp) \ 218 do { \ 219 efx_oword_t oword; \ 220 \ 221 EFX_BAR_READO((_enp), FR_AZ_RX_CFG_REG, &oword); \ 222 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 1); \ 223 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH, \ 224 (_ip) ? 1 : 0); \ 225 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP, \ 226 (_tcp) ? 0 : 1); \ 227 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR, \ 228 (_insert) ? 1 : 0); \ 229 EFX_BAR_WRITEO((_enp), FR_AZ_RX_CFG_REG, &oword); \ 230 \ 231 _NOTE(CONSTANTCONDITION) \ 232 } while (B_FALSE) 233 234 #define EFX_RX_TOEPLITZ_IPV6_HASH(_enp, _ip, _tcp, _rc) \ 235 do { \ 236 efx_oword_t oword; \ 237 \ 238 if ((_enp)->en_family == EFX_FAMILY_FALCON) { \ 239 (_rc) = ((_ip) || (_tcp)) ? ENOTSUP : 0; \ 240 break; \ 241 } \ 242 \ 243 EFX_BAR_READO((_enp), FR_CZ_RX_RSS_IPV6_REG3, &oword); \ 244 EFX_SET_OWORD_FIELD(oword, \ 245 FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 1); \ 246 EFX_SET_OWORD_FIELD(oword, \ 247 FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE, (_ip) ? 1 : 0); \ 248 EFX_SET_OWORD_FIELD(oword, \ 249 FRF_CZ_RX_RSS_IPV6_TCP_SUPPRESS, (_tcp) ? 0 : 1); \ 250 EFX_BAR_WRITEO((_enp), FR_CZ_RX_RSS_IPV6_REG3, &oword); \ 251 \ 252 (_rc) = 0; \ 253 \ 254 _NOTE(CONSTANTCONDITION) \ 255 } while (B_FALSE) 256 257 258 #if EFSYS_OPT_RX_SCALE 259 __checkReturn int 260 efx_rx_scale_mode_set( 261 __in efx_nic_t *enp, 262 __in efx_rx_hash_alg_t alg, 263 __in efx_rx_hash_type_t type, 264 __in boolean_t insert) 265 { 266 int rc; 267 268 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 269 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX); 270 EFSYS_ASSERT3U(enp->en_family, >=, EFX_FAMILY_FALCON); 271 272 switch (alg) { 273 case EFX_RX_HASHALG_LFSR: 274 EFX_RX_LFSR_HASH(enp, insert); 275 break; 276 277 case EFX_RX_HASHALG_TOEPLITZ: 278 EFX_RX_TOEPLITZ_IPV4_HASH(enp, insert, 279 type & (1 << EFX_RX_HASH_IPV4), 280 type & (1 << EFX_RX_HASH_TCPIPV4)); 281 282 EFX_RX_TOEPLITZ_IPV6_HASH(enp, 283 type & (1 << EFX_RX_HASH_IPV6), 284 type & (1 << EFX_RX_HASH_TCPIPV6), 285 rc); 286 if (rc != 0) 287 goto fail1; 288 289 break; 290 291 default: 292 rc = EINVAL; 293 goto fail2; 294 } 295 296 return (0); 297 298 fail2: 299 EFSYS_PROBE(fail2); 300 fail1: 301 EFSYS_PROBE1(fail1, int, rc); 302 303 EFX_RX_LFSR_HASH(enp, B_FALSE); 304 305 return (rc); 306 } 307 #endif 308 309 #if EFSYS_OPT_RX_SCALE 310 __checkReturn int 311 efx_rx_scale_toeplitz_ipv4_key_set( 312 __in efx_nic_t *enp, 313 __in_ecount(n) uint8_t *key, 314 __in size_t n) 315 { 316 efx_oword_t oword; 317 unsigned int byte; 318 unsigned int offset; 319 int rc; 320 321 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 322 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX); 323 324 byte = 0; 325 326 /* Write toeplitz hash key */ 327 EFX_ZERO_OWORD(oword); 328 for (offset = (FRF_BZ_RX_RSS_TKEY_LBN + FRF_BZ_RX_RSS_TKEY_WIDTH) / 8; 329 offset > 0 && byte < n; 330 --offset) 331 oword.eo_u8[offset - 1] = key[byte++]; 332 333 EFX_BAR_WRITEO(enp, FR_BZ_RX_RSS_TKEY_REG, &oword); 334 335 byte = 0; 336 337 /* Verify toeplitz hash key */ 338 EFX_BAR_READO(enp, FR_BZ_RX_RSS_TKEY_REG, &oword); 339 for (offset = (FRF_BZ_RX_RSS_TKEY_LBN + FRF_BZ_RX_RSS_TKEY_WIDTH) / 8; 340 offset > 0 && byte < n; 341 --offset) { 342 if (oword.eo_u8[offset - 1] != key[byte++]) { 343 rc = EFAULT; 344 goto fail1; 345 } 346 } 347 348 return (0); 349 350 fail1: 351 EFSYS_PROBE1(fail1, int, rc); 352 353 return (rc); 354 } 355 #endif 356 357 #if EFSYS_OPT_RX_SCALE 358 __checkReturn int 359 efx_rx_scale_toeplitz_ipv6_key_set( 360 __in efx_nic_t *enp, 361 __in_ecount(n) uint8_t *key, 362 __in size_t n) 363 { 364 efx_oword_t oword; 365 unsigned int byte; 366 int offset; 367 int rc; 368 369 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 370 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX); 371 372 byte = 0; 373 374 /* Write toeplitz hash key 3 */ 375 EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG3, &oword); 376 for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN + 377 FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH) / 8; 378 offset > 0 && byte < n; 379 --offset) 380 oword.eo_u8[offset - 1] = key[byte++]; 381 382 EFX_BAR_WRITEO(enp, FR_CZ_RX_RSS_IPV6_REG3, &oword); 383 384 /* Write toeplitz hash key 2 */ 385 EFX_ZERO_OWORD(oword); 386 for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_MID_LBN + 387 FRF_CZ_RX_RSS_IPV6_TKEY_MID_WIDTH) / 8; 388 offset > 0 && byte < n; 389 --offset) 390 oword.eo_u8[offset - 1] = key[byte++]; 391 392 EFX_BAR_WRITEO(enp, FR_CZ_RX_RSS_IPV6_REG2, &oword); 393 394 /* Write toeplitz hash key 1 */ 395 EFX_ZERO_OWORD(oword); 396 for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_LO_LBN + 397 FRF_CZ_RX_RSS_IPV6_TKEY_LO_WIDTH) / 8; 398 offset > 0 && byte < n; 399 --offset) 400 oword.eo_u8[offset - 1] = key[byte++]; 401 402 EFX_BAR_WRITEO(enp, FR_CZ_RX_RSS_IPV6_REG1, &oword); 403 404 byte = 0; 405 406 /* Verify toeplitz hash key 3 */ 407 EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG3, &oword); 408 for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN + 409 FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH) / 8; 410 offset > 0 && byte < n; 411 --offset) { 412 if (oword.eo_u8[offset - 1] != key[byte++]) { 413 rc = EFAULT; 414 goto fail1; 415 } 416 } 417 418 /* Verify toeplitz hash key 2 */ 419 EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG2, &oword); 420 for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_MID_LBN + 421 FRF_CZ_RX_RSS_IPV6_TKEY_MID_WIDTH) / 8; 422 offset > 0 && byte < n; 423 --offset) { 424 if (oword.eo_u8[offset - 1] != key[byte++]) { 425 rc = EFAULT; 426 goto fail2; 427 } 428 } 429 430 /* Verify toeplitz hash key 1 */ 431 EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG1, &oword); 432 for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_LO_LBN + 433 FRF_CZ_RX_RSS_IPV6_TKEY_LO_WIDTH) / 8; 434 offset > 0 && byte < n; 435 --offset) { 436 if (oword.eo_u8[offset - 1] != key[byte++]) { 437 rc = EFAULT; 438 goto fail3; 439 } 440 } 441 442 return (0); 443 444 fail3: 445 EFSYS_PROBE(fail3); 446 fail2: 447 EFSYS_PROBE(fail2); 448 fail1: 449 EFSYS_PROBE1(fail1, int, rc); 450 451 return (rc); 452 } 453 #endif 454 455 #if EFSYS_OPT_RX_SCALE 456 __checkReturn int 457 efx_rx_scale_tbl_set( 458 __in efx_nic_t *enp, 459 __in_ecount(n) unsigned int *table, 460 __in size_t n) 461 { 462 efx_oword_t oword; 463 int index; 464 int rc; 465 466 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 467 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX); 468 469 EFX_STATIC_ASSERT(EFX_RSS_TBL_SIZE == FR_BZ_RX_INDIRECTION_TBL_ROWS); 470 EFX_STATIC_ASSERT(EFX_MAXRSS == (1 << FRF_BZ_IT_QUEUE_WIDTH)); 471 472 if (n > FR_BZ_RX_INDIRECTION_TBL_ROWS) { 473 rc = EINVAL; 474 goto fail1; 475 } 476 477 for (index = 0; index < FR_BZ_RX_INDIRECTION_TBL_ROWS; index++) { 478 uint32_t byte; 479 480 /* Calculate the entry to place in the table */ 481 byte = (uint32_t)table[index % n]; 482 483 EFSYS_PROBE2(table, int, index, uint32_t, byte); 484 485 EFX_POPULATE_OWORD_1(oword, FRF_BZ_IT_QUEUE, byte); 486 487 /* Write the table */ 488 EFX_BAR_TBL_WRITEO(enp, FR_BZ_RX_INDIRECTION_TBL, 489 index, &oword); 490 } 491 492 for (index = FR_BZ_RX_INDIRECTION_TBL_ROWS - 1; index >= 0; --index) { 493 uint32_t byte; 494 495 /* Determine if we're starting a new batch */ 496 byte = (uint32_t)table[index % n]; 497 498 /* Read the table */ 499 EFX_BAR_TBL_READO(enp, FR_BZ_RX_INDIRECTION_TBL, 500 index, &oword); 501 502 /* Verify the entry */ 503 if (EFX_OWORD_FIELD(oword, FRF_BZ_IT_QUEUE) != byte) { 504 rc = EFAULT; 505 goto fail2; 506 } 507 } 508 509 return (0); 510 511 fail2: 512 EFSYS_PROBE(fail2); 513 fail1: 514 EFSYS_PROBE1(fail1, int, rc); 515 516 return (rc); 517 } 518 #endif 519 520 #if EFSYS_OPT_FILTER 521 extern __checkReturn int 522 efx_rx_filter_insert( 523 __in efx_rxq_t *erp, 524 __inout efx_filter_spec_t *spec) 525 { 526 EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC); 527 EFSYS_ASSERT3P(spec, !=, NULL); 528 529 spec->efs_dmaq_id = (uint16_t)erp->er_index; 530 return efx_filter_insert_filter(erp->er_enp, spec, B_FALSE); 531 } 532 #endif 533 534 #if EFSYS_OPT_FILTER 535 extern __checkReturn int 536 efx_rx_filter_remove( 537 __in efx_rxq_t *erp, 538 __inout efx_filter_spec_t *spec) 539 { 540 EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC); 541 EFSYS_ASSERT3P(spec, !=, NULL); 542 543 spec->efs_dmaq_id = (uint16_t)erp->er_index; 544 return efx_filter_remove_filter(erp->er_enp, spec); 545 } 546 #endif 547 548 extern void 549 efx_rx_qpost( 550 __in efx_rxq_t *erp, 551 __in_ecount(n) efsys_dma_addr_t *addrp, 552 __in size_t size, 553 __in unsigned int n, 554 __in unsigned int completed, 555 __in unsigned int added) 556 { 557 efx_qword_t qword; 558 unsigned int i; 559 unsigned int offset; 560 unsigned int id; 561 562 EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC); 563 564 /* The client driver must not overfill the queue */ 565 EFSYS_ASSERT3U(added - completed + n, <=, 566 EFX_RXQ_LIMIT(erp->er_mask + 1)); 567 568 id = added & (erp->er_mask); 569 for (i = 0; i < n; i++) { 570 EFSYS_PROBE4(rx_post, unsigned int, erp->er_index, 571 unsigned int, id, efsys_dma_addr_t, addrp[i], 572 size_t, size); 573 574 EFX_POPULATE_QWORD_3(qword, 575 FSF_AZ_RX_KER_BUF_SIZE, (uint32_t)(size), 576 FSF_AZ_RX_KER_BUF_ADDR_DW0, 577 (uint32_t)(addrp[i] & 0xffffffff), 578 FSF_AZ_RX_KER_BUF_ADDR_DW1, 579 (uint32_t)(addrp[i] >> 32)); 580 581 offset = id * sizeof (efx_qword_t); 582 EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword); 583 584 id = (id + 1) & (erp->er_mask); 585 } 586 } 587 588 void 589 efx_rx_qpush( 590 __in efx_rxq_t *erp, 591 __in unsigned int added) 592 { 593 efx_nic_t *enp = erp->er_enp; 594 uint32_t wptr; 595 efx_oword_t oword; 596 efx_dword_t dword; 597 598 EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC); 599 600 /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */ 601 EFSYS_PIO_WRITE_BARRIER(); 602 603 /* Push the populated descriptors out */ 604 wptr = added & erp->er_mask; 605 606 EFX_POPULATE_OWORD_1(oword, FRF_AZ_RX_DESC_WPTR, wptr); 607 608 /* Only write the third DWORD */ 609 EFX_POPULATE_DWORD_1(dword, 610 EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3)); 611 EFX_BAR_TBL_WRITED3(enp, FR_BZ_RX_DESC_UPD_REGP0, 612 erp->er_index, &dword, B_FALSE); 613 } 614 615 void 616 efx_rx_qflush( 617 __in efx_rxq_t *erp) 618 { 619 efx_nic_t *enp = erp->er_enp; 620 efx_oword_t oword; 621 uint32_t label; 622 623 EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC); 624 625 label = erp->er_index; 626 627 /* Flush the queue */ 628 EFX_POPULATE_OWORD_2(oword, FRF_AZ_RX_FLUSH_DESCQ_CMD, 1, 629 FRF_AZ_RX_FLUSH_DESCQ, label); 630 EFX_BAR_WRITEO(enp, FR_AZ_RX_FLUSH_DESCQ_REG, &oword); 631 } 632 633 void 634 efx_rx_qenable( 635 __in efx_rxq_t *erp) 636 { 637 efx_nic_t *enp = erp->er_enp; 638 efx_oword_t oword; 639 640 EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC); 641 642 EFX_BAR_TBL_READO(enp, FR_AZ_RX_DESC_PTR_TBL, 643 erp->er_index, &oword); 644 645 EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DC_HW_RPTR, 0); 646 EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DESCQ_HW_RPTR, 0); 647 EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DESCQ_EN, 1); 648 649 EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL, 650 erp->er_index, &oword); 651 } 652 653 __checkReturn int 654 efx_rx_qcreate( 655 __in efx_nic_t *enp, 656 __in unsigned int index, 657 __in unsigned int label, 658 __in efx_rxq_type_t type, 659 __in efsys_mem_t *esmp, 660 __in size_t n, 661 __in uint32_t id, 662 __in efx_evq_t *eep, 663 __deref_out efx_rxq_t **erpp) 664 { 665 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 666 efx_rxq_t *erp; 667 efx_oword_t oword; 668 uint32_t size; 669 boolean_t split; 670 boolean_t jumbo; 671 int rc; 672 673 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 674 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX); 675 676 EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS == (1 << FRF_AZ_RX_DESCQ_LABEL_WIDTH)); 677 EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS); 678 EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit); 679 680 if (!ISP2(n) || !(n & EFX_RXQ_NDESCS_MASK)) { 681 rc = EINVAL; 682 goto fail1; 683 } 684 if (index >= encp->enc_rxq_limit) { 685 rc = EINVAL; 686 goto fail2; 687 } 688 for (size = 0; (1 << size) <= (EFX_RXQ_MAXNDESCS / EFX_RXQ_MINNDESCS); 689 size++) 690 if ((1 << size) == (int)(n / EFX_RXQ_MINNDESCS)) 691 break; 692 if (id + (1 << size) >= encp->enc_buftbl_limit) { 693 rc = EINVAL; 694 goto fail3; 695 } 696 697 switch (type) { 698 case EFX_RXQ_TYPE_DEFAULT: 699 split = B_FALSE; 700 jumbo = B_FALSE; 701 break; 702 703 #if EFSYS_OPT_RX_HDR_SPLIT 704 case EFX_RXQ_TYPE_SPLIT_HEADER: 705 if ((enp->en_family < EFX_FAMILY_SIENA) || ((index & 1) != 0)) { 706 rc = EINVAL; 707 goto fail4; 708 } 709 split = B_TRUE; 710 jumbo = B_TRUE; 711 break; 712 713 case EFX_RXQ_TYPE_SPLIT_PAYLOAD: 714 if ((enp->en_family < EFX_FAMILY_SIENA) || ((index & 1) == 0)) { 715 rc = EINVAL; 716 goto fail4; 717 } 718 split = B_FALSE; 719 jumbo = B_TRUE; 720 break; 721 #endif /* EFSYS_OPT_RX_HDR_SPLIT */ 722 723 #if EFSYS_OPT_RX_SCATTER 724 case EFX_RXQ_TYPE_SCATTER: 725 if (enp->en_family < EFX_FAMILY_SIENA) { 726 rc = EINVAL; 727 goto fail4; 728 } 729 split = B_FALSE; 730 jumbo = B_TRUE; 731 break; 732 #endif /* EFSYS_OPT_RX_SCATTER */ 733 734 default: 735 rc = EINVAL; 736 goto fail4; 737 } 738 739 /* Allocate an RXQ object */ 740 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_rxq_t), erp); 741 742 if (erp == NULL) { 743 rc = ENOMEM; 744 goto fail5; 745 } 746 747 erp->er_magic = EFX_RXQ_MAGIC; 748 erp->er_enp = enp; 749 erp->er_index = index; 750 erp->er_mask = n - 1; 751 erp->er_esmp = esmp; 752 753 /* Set up the new descriptor queue */ 754 EFX_POPULATE_OWORD_10(oword, 755 FRF_CZ_RX_HDR_SPLIT, split, 756 FRF_AZ_RX_ISCSI_DDIG_EN, 0, 757 FRF_AZ_RX_ISCSI_HDIG_EN, 0, 758 FRF_AZ_RX_DESCQ_BUF_BASE_ID, id, 759 FRF_AZ_RX_DESCQ_EVQ_ID, eep->ee_index, 760 FRF_AZ_RX_DESCQ_OWNER_ID, 0, 761 FRF_AZ_RX_DESCQ_LABEL, label, 762 FRF_AZ_RX_DESCQ_SIZE, size, 763 FRF_AZ_RX_DESCQ_TYPE, 0, 764 FRF_AZ_RX_DESCQ_JUMBO, jumbo); 765 766 EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL, 767 erp->er_index, &oword); 768 769 enp->en_rx_qcount++; 770 *erpp = erp; 771 return (0); 772 773 fail5: 774 EFSYS_PROBE(fail5); 775 fail4: 776 EFSYS_PROBE(fail4); 777 fail3: 778 EFSYS_PROBE(fail3); 779 fail2: 780 EFSYS_PROBE(fail2); 781 fail1: 782 EFSYS_PROBE1(fail1, int, rc); 783 784 return (rc); 785 } 786 787 void 788 efx_rx_qdestroy( 789 __in efx_rxq_t *erp) 790 { 791 efx_nic_t *enp = erp->er_enp; 792 efx_oword_t oword; 793 794 EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC); 795 796 EFSYS_ASSERT(enp->en_rx_qcount != 0); 797 --enp->en_rx_qcount; 798 799 /* Purge descriptor queue */ 800 EFX_ZERO_OWORD(oword); 801 802 EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL, 803 erp->er_index, &oword); 804 805 /* Free the RXQ object */ 806 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp); 807 } 808 809 void 810 efx_rx_fini( 811 __in efx_nic_t *enp) 812 { 813 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 814 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 815 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX); 816 EFSYS_ASSERT3U(enp->en_rx_qcount, ==, 0); 817 818 enp->en_mod_flags &= ~EFX_MOD_RX; 819 } 820