1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright (c) 2021, Intel Corporation 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 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the Intel Corporation nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /** 33 * @file iavf_txrx_iflib.c 34 * @brief Tx/Rx hotpath implementation for the iflib driver 35 * 36 * Contains functions used to implement the Tx and Rx hotpaths of the iflib 37 * driver implementation. 38 */ 39 #include "iavf_iflib.h" 40 #include "iavf_txrx_common.h" 41 42 #ifdef RSS 43 #include <net/rss_config.h> 44 #endif 45 46 /* Local Prototypes */ 47 static void iavf_rx_checksum(if_rxd_info_t ri, u32 status, u32 error, u8 ptype); 48 49 static int iavf_isc_txd_encap(void *arg, if_pkt_info_t pi); 50 static void iavf_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx); 51 static int iavf_isc_txd_credits_update_hwb(void *arg, uint16_t txqid, bool clear); 52 static int iavf_isc_txd_credits_update_dwb(void *arg, uint16_t txqid, bool clear); 53 54 static void iavf_isc_rxd_refill(void *arg, if_rxd_update_t iru); 55 static void iavf_isc_rxd_flush(void *arg, uint16_t rxqid, uint8_t flid __unused, 56 qidx_t pidx); 57 static int iavf_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, 58 qidx_t budget); 59 static int iavf_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri); 60 61 /** 62 * @var iavf_txrx_hwb 63 * @brief iflib Tx/Rx operations for head write back 64 * 65 * iflib ops structure for when operating the device in head write back mode. 66 */ 67 struct if_txrx iavf_txrx_hwb = { 68 iavf_isc_txd_encap, 69 iavf_isc_txd_flush, 70 iavf_isc_txd_credits_update_hwb, 71 iavf_isc_rxd_available, 72 iavf_isc_rxd_pkt_get, 73 iavf_isc_rxd_refill, 74 iavf_isc_rxd_flush, 75 NULL 76 }; 77 78 /** 79 * @var iavf_txrx_dwb 80 * @brief iflib Tx/Rx operations for descriptor write back 81 * 82 * iflib ops structure for when operating the device in descriptor write back 83 * mode. 84 */ 85 struct if_txrx iavf_txrx_dwb = { 86 iavf_isc_txd_encap, 87 iavf_isc_txd_flush, 88 iavf_isc_txd_credits_update_dwb, 89 iavf_isc_rxd_available, 90 iavf_isc_rxd_pkt_get, 91 iavf_isc_rxd_refill, 92 iavf_isc_rxd_flush, 93 NULL 94 }; 95 96 /** 97 * iavf_is_tx_desc_done - Check if a Tx descriptor is ready 98 * @txr: the Tx ring to check in 99 * @idx: ring index to check 100 * 101 * @returns true if the descriptor has been written back by hardware, and 102 * false otherwise. 103 */ 104 static bool 105 iavf_is_tx_desc_done(struct tx_ring *txr, int idx) 106 { 107 return (((txr->tx_base[idx].cmd_type_offset_bsz >> IAVF_TXD_QW1_DTYPE_SHIFT) 108 & IAVF_TXD_QW1_DTYPE_MASK) == IAVF_TX_DESC_DTYPE_DESC_DONE); 109 } 110 111 112 /** 113 * iavf_tso_detect_sparse - detect TSO packets with too many segments 114 * @segs: packet segments array 115 * @nsegs: number of packet segments 116 * @pi: packet information 117 * 118 * Hardware only transmits packets with a maximum of 8 descriptors. For TSO 119 * packets, hardware needs to be able to build the split packets using 8 or 120 * fewer descriptors. Additionally, the header must be contained within at 121 * most 3 descriptors. 122 * 123 * To verify this, we walk the headers to find out how many descriptors the 124 * headers require (usually 1). Then we ensure that, for each TSO segment, its 125 * data plus the headers are contained within 8 or fewer descriptors. 126 * 127 * @returns zero if the packet is valid, one otherwise. 128 */ 129 static int 130 iavf_tso_detect_sparse(bus_dma_segment_t *segs, int nsegs, if_pkt_info_t pi) 131 { 132 int count, curseg, i, hlen, segsz, seglen, tsolen; 133 134 if (nsegs <= IAVF_MAX_TX_SEGS-2) 135 return (0); 136 segsz = pi->ipi_tso_segsz; 137 curseg = count = 0; 138 139 hlen = pi->ipi_ehdrlen + pi->ipi_ip_hlen + pi->ipi_tcp_hlen; 140 tsolen = pi->ipi_len - hlen; 141 142 i = 0; 143 curseg = segs[0].ds_len; 144 while (hlen > 0) { 145 count++; 146 if (count > IAVF_MAX_TX_SEGS - 2) 147 return (1); 148 if (curseg == 0) { 149 i++; 150 if (__predict_false(i == nsegs)) 151 return (1); 152 153 curseg = segs[i].ds_len; 154 } 155 seglen = min(curseg, hlen); 156 curseg -= seglen; 157 hlen -= seglen; 158 } 159 while (tsolen > 0) { 160 segsz = pi->ipi_tso_segsz; 161 while (segsz > 0 && tsolen != 0) { 162 count++; 163 if (count > IAVF_MAX_TX_SEGS - 2) { 164 return (1); 165 } 166 if (curseg == 0) { 167 i++; 168 if (__predict_false(i == nsegs)) { 169 return (1); 170 } 171 curseg = segs[i].ds_len; 172 } 173 seglen = min(curseg, segsz); 174 segsz -= seglen; 175 curseg -= seglen; 176 tsolen -= seglen; 177 } 178 count = 0; 179 } 180 181 return (0); 182 } 183 184 /** 185 * iavf_tx_setup_offload - Setup Tx offload parameters 186 * @que: pointer to the Tx queue 187 * @pi: Tx packet info 188 * @cmd: pointer to command descriptor value 189 * @off: pointer to offset descriptor value 190 * 191 * Based on packet type and Tx offloads requested, sets up the command and 192 * offset values for a Tx descriptor to enable the requested offloads. 193 */ 194 static void 195 iavf_tx_setup_offload(struct iavf_tx_queue *que __unused, 196 if_pkt_info_t pi, u32 *cmd, u32 *off) 197 { 198 switch (pi->ipi_etype) { 199 #ifdef INET 200 case ETHERTYPE_IP: 201 if (pi->ipi_csum_flags & IAVF_CSUM_IPV4) 202 *cmd |= IAVF_TX_DESC_CMD_IIPT_IPV4_CSUM; 203 else 204 *cmd |= IAVF_TX_DESC_CMD_IIPT_IPV4; 205 break; 206 #endif 207 #ifdef INET6 208 case ETHERTYPE_IPV6: 209 *cmd |= IAVF_TX_DESC_CMD_IIPT_IPV6; 210 break; 211 #endif 212 default: 213 break; 214 } 215 216 *off |= (pi->ipi_ehdrlen >> 1) << IAVF_TX_DESC_LENGTH_MACLEN_SHIFT; 217 *off |= (pi->ipi_ip_hlen >> 2) << IAVF_TX_DESC_LENGTH_IPLEN_SHIFT; 218 219 switch (pi->ipi_ipproto) { 220 case IPPROTO_TCP: 221 if (pi->ipi_csum_flags & IAVF_CSUM_TCP) { 222 *cmd |= IAVF_TX_DESC_CMD_L4T_EOFT_TCP; 223 *off |= (pi->ipi_tcp_hlen >> 2) << 224 IAVF_TX_DESC_LENGTH_L4_FC_LEN_SHIFT; 225 /* Check for NO_HEAD MDD event */ 226 MPASS(pi->ipi_tcp_hlen != 0); 227 } 228 break; 229 case IPPROTO_UDP: 230 if (pi->ipi_csum_flags & IAVF_CSUM_UDP) { 231 *cmd |= IAVF_TX_DESC_CMD_L4T_EOFT_UDP; 232 *off |= (sizeof(struct udphdr) >> 2) << 233 IAVF_TX_DESC_LENGTH_L4_FC_LEN_SHIFT; 234 } 235 break; 236 case IPPROTO_SCTP: 237 if (pi->ipi_csum_flags & IAVF_CSUM_SCTP) { 238 *cmd |= IAVF_TX_DESC_CMD_L4T_EOFT_SCTP; 239 *off |= (sizeof(struct sctphdr) >> 2) << 240 IAVF_TX_DESC_LENGTH_L4_FC_LEN_SHIFT; 241 } 242 /* Fall Thru */ 243 default: 244 break; 245 } 246 } 247 248 /** 249 * iavf_tso_setup - Setup TSO context descriptor 250 * @txr: the Tx ring to process 251 * @pi: packet info structure 252 * 253 * Enable hardware segmentation offload (TSO) for a given packet by creating 254 * a context descriptor with the necessary details for offloading. 255 * 256 * @returns the new ring index to use for the data descriptor. 257 */ 258 static int 259 iavf_tso_setup(struct tx_ring *txr, if_pkt_info_t pi) 260 { 261 if_softc_ctx_t scctx; 262 struct iavf_tx_context_desc *TXD; 263 u32 cmd, mss, type, tsolen; 264 int idx, total_hdr_len; 265 u64 type_cmd_tso_mss; 266 267 idx = pi->ipi_pidx; 268 TXD = (struct iavf_tx_context_desc *) &txr->tx_base[idx]; 269 total_hdr_len = pi->ipi_ehdrlen + pi->ipi_ip_hlen + pi->ipi_tcp_hlen; 270 tsolen = pi->ipi_len - total_hdr_len; 271 scctx = txr->que->vsi->shared; 272 273 type = IAVF_TX_DESC_DTYPE_CONTEXT; 274 cmd = IAVF_TX_CTX_DESC_TSO; 275 /* 276 * TSO MSS must not be less than 64; this prevents a 277 * BAD_LSO_MSS MDD event when the MSS is too small. 278 */ 279 if (pi->ipi_tso_segsz < IAVF_MIN_TSO_MSS) { 280 txr->mss_too_small++; 281 pi->ipi_tso_segsz = IAVF_MIN_TSO_MSS; 282 } 283 mss = pi->ipi_tso_segsz; 284 285 /* Check for BAD_LS0_MSS MDD event (mss too large) */ 286 MPASS(mss <= IAVF_MAX_TSO_MSS); 287 /* Check for NO_HEAD MDD event (header lengths are 0) */ 288 MPASS(pi->ipi_ehdrlen != 0); 289 MPASS(pi->ipi_ip_hlen != 0); 290 /* Partial check for BAD_LSO_LEN MDD event */ 291 MPASS(tsolen != 0); 292 /* Partial check for WRONG_SIZE MDD event (during TSO) */ 293 MPASS(total_hdr_len + mss <= IAVF_MAX_FRAME); 294 295 type_cmd_tso_mss = ((u64)type << IAVF_TXD_CTX_QW1_DTYPE_SHIFT) | 296 ((u64)cmd << IAVF_TXD_CTX_QW1_CMD_SHIFT) | 297 ((u64)tsolen << IAVF_TXD_CTX_QW1_TSO_LEN_SHIFT) | 298 ((u64)mss << IAVF_TXD_CTX_QW1_MSS_SHIFT); 299 TXD->type_cmd_tso_mss = htole64(type_cmd_tso_mss); 300 301 TXD->tunneling_params = htole32(0); 302 txr->que->tso++; 303 304 return ((idx + 1) & (scctx->isc_ntxd[0]-1)); 305 } 306 307 #define IAVF_TXD_CMD (IAVF_TX_DESC_CMD_EOP | IAVF_TX_DESC_CMD_RS) 308 309 /** 310 * iavf_isc_txd_encap - Encapsulate a Tx packet into descriptors 311 * @arg: void pointer to the VSI structure 312 * @pi: packet info to encapsulate 313 * 314 * This routine maps the mbufs to tx descriptors, allowing the 315 * TX engine to transmit the packets. 316 * 317 * @returns 0 on success, positive on failure 318 */ 319 static int 320 iavf_isc_txd_encap(void *arg, if_pkt_info_t pi) 321 { 322 struct iavf_vsi *vsi = arg; 323 if_softc_ctx_t scctx = vsi->shared; 324 struct iavf_tx_queue *que = &vsi->tx_queues[pi->ipi_qsidx]; 325 struct tx_ring *txr = &que->txr; 326 int nsegs = pi->ipi_nsegs; 327 bus_dma_segment_t *segs = pi->ipi_segs; 328 struct iavf_tx_desc *txd = NULL; 329 int i, j, mask, pidx_last; 330 u32 cmd, off, tx_intr; 331 332 if (__predict_false(pi->ipi_len < IAVF_MIN_FRAME)) { 333 que->pkt_too_small++; 334 return (EINVAL); 335 } 336 337 cmd = off = 0; 338 i = pi->ipi_pidx; 339 340 tx_intr = (pi->ipi_flags & IPI_TX_INTR); 341 342 /* Set up the TSO/CSUM offload */ 343 if (pi->ipi_csum_flags & CSUM_OFFLOAD) { 344 /* Set up the TSO context descriptor if required */ 345 if (pi->ipi_csum_flags & CSUM_TSO) { 346 /* Prevent MAX_BUFF MDD event (for TSO) */ 347 if (iavf_tso_detect_sparse(segs, nsegs, pi)) 348 return (EFBIG); 349 i = iavf_tso_setup(txr, pi); 350 } 351 iavf_tx_setup_offload(que, pi, &cmd, &off); 352 } 353 if (pi->ipi_mflags & M_VLANTAG) 354 cmd |= IAVF_TX_DESC_CMD_IL2TAG1; 355 356 cmd |= IAVF_TX_DESC_CMD_ICRC; 357 mask = scctx->isc_ntxd[0] - 1; 358 /* Check for WRONG_SIZE MDD event */ 359 MPASS(pi->ipi_len >= IAVF_MIN_FRAME); 360 #ifdef INVARIANTS 361 if (!(pi->ipi_csum_flags & CSUM_TSO)) 362 MPASS(pi->ipi_len <= IAVF_MAX_FRAME); 363 #endif 364 for (j = 0; j < nsegs; j++) { 365 bus_size_t seglen; 366 367 txd = &txr->tx_base[i]; 368 seglen = segs[j].ds_len; 369 370 /* Check for ZERO_BSIZE MDD event */ 371 MPASS(seglen != 0); 372 373 txd->buffer_addr = htole64(segs[j].ds_addr); 374 txd->cmd_type_offset_bsz = 375 htole64(IAVF_TX_DESC_DTYPE_DATA 376 | ((u64)cmd << IAVF_TXD_QW1_CMD_SHIFT) 377 | ((u64)off << IAVF_TXD_QW1_OFFSET_SHIFT) 378 | ((u64)seglen << IAVF_TXD_QW1_TX_BUF_SZ_SHIFT) 379 | ((u64)htole16(pi->ipi_vtag) << IAVF_TXD_QW1_L2TAG1_SHIFT)); 380 381 txr->tx_bytes += seglen; 382 pidx_last = i; 383 i = (i+1) & mask; 384 } 385 /* Set the last descriptor for report */ 386 txd->cmd_type_offset_bsz |= 387 htole64(((u64)IAVF_TXD_CMD << IAVF_TXD_QW1_CMD_SHIFT)); 388 /* Add to report status array (if using TX interrupts) */ 389 if (!vsi->enable_head_writeback && tx_intr) { 390 txr->tx_rsq[txr->tx_rs_pidx] = pidx_last; 391 txr->tx_rs_pidx = (txr->tx_rs_pidx+1) & mask; 392 MPASS(txr->tx_rs_pidx != txr->tx_rs_cidx); 393 } 394 pi->ipi_new_pidx = i; 395 396 ++txr->tx_packets; 397 return (0); 398 } 399 400 /** 401 * iavf_isc_txd_flush - Flush Tx ring 402 * @arg: void pointer to the VSI 403 * @txqid: the Tx queue to flush 404 * @pidx: the ring index to flush to 405 * 406 * Advance the Transmit Descriptor Tail (Tdt), this tells the 407 * hardware that this frame is available to transmit. 408 */ 409 static void 410 iavf_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx) 411 { 412 struct iavf_vsi *vsi = arg; 413 struct tx_ring *txr = &vsi->tx_queues[txqid].txr; 414 415 /* Check for ENDLESS_TX MDD event */ 416 MPASS(pidx < vsi->shared->isc_ntxd[0]); 417 wr32(vsi->hw, txr->tail, pidx); 418 } 419 420 /** 421 * iavf_init_tx_ring - Initialize queue Tx ring 422 * @vsi: pointer to the VSI 423 * @que: pointer to queue to initialize 424 * 425 * (Re)Initialize a queue transmit ring by clearing its memory. 426 */ 427 void 428 iavf_init_tx_ring(struct iavf_vsi *vsi, struct iavf_tx_queue *que) 429 { 430 struct tx_ring *txr = &que->txr; 431 432 /* Clear the old ring contents */ 433 bzero((void *)txr->tx_base, 434 (sizeof(struct iavf_tx_desc)) * 435 (vsi->shared->isc_ntxd[0] + (vsi->enable_head_writeback ? 1 : 0))); 436 437 wr32(vsi->hw, txr->tail, 0); 438 } 439 440 /** 441 * iavf_get_tx_head - Get the index of the head of a ring 442 * @que: queue to read 443 * 444 * Retrieve the value from the location the HW records its HEAD index 445 * 446 * @returns the index of the HW head of the Tx queue 447 */ 448 static inline u32 449 iavf_get_tx_head(struct iavf_tx_queue *que) 450 { 451 if_softc_ctx_t scctx = que->vsi->shared; 452 struct tx_ring *txr = &que->txr; 453 void *head = &txr->tx_base[scctx->isc_ntxd[0]]; 454 455 return LE32_TO_CPU(*(volatile __le32 *)head); 456 } 457 458 /** 459 * iavf_isc_txd_credits_update_hwb - Update Tx ring credits 460 * @arg: void pointer to the VSI 461 * @qid: the queue id to update 462 * @clear: whether to update or only report current status 463 * 464 * Checks the number of packets in the queue that could be cleaned up. 465 * 466 * if clear is true, the iflib stack has cleaned the packets and is 467 * notifying the driver to update its processed ring pointer. 468 * 469 * @returns the number of packets in the ring that can be cleaned. 470 * 471 * @remark this function is intended for the head write back mode. 472 */ 473 static int 474 iavf_isc_txd_credits_update_hwb(void *arg, uint16_t qid, bool clear) 475 { 476 struct iavf_vsi *vsi = arg; 477 if_softc_ctx_t scctx = vsi->shared; 478 struct iavf_tx_queue *que = &vsi->tx_queues[qid]; 479 struct tx_ring *txr = &que->txr; 480 int head, credits; 481 482 /* Get the Head WB value */ 483 head = iavf_get_tx_head(que); 484 485 credits = head - txr->tx_cidx_processed; 486 if (credits < 0) 487 credits += scctx->isc_ntxd[0]; 488 if (clear) 489 txr->tx_cidx_processed = head; 490 491 return (credits); 492 } 493 494 /** 495 * iavf_isc_txd_credits_update_dwb - Update Tx ring credits 496 * @arg: void pointer to the VSI 497 * @txqid: the queue id to update 498 * @clear: whether to update or only report current status 499 * 500 * Checks the number of packets in the queue that could be cleaned up. 501 * 502 * if clear is true, the iflib stack has cleaned the packets and is 503 * notifying the driver to update its processed ring pointer. 504 * 505 * @returns the number of packets in the ring that can be cleaned. 506 * 507 * @remark this function is intended for the descriptor write back mode. 508 */ 509 static int 510 iavf_isc_txd_credits_update_dwb(void *arg, uint16_t txqid, bool clear) 511 { 512 struct iavf_vsi *vsi = arg; 513 struct iavf_tx_queue *tx_que = &vsi->tx_queues[txqid]; 514 if_softc_ctx_t scctx = vsi->shared; 515 struct tx_ring *txr = &tx_que->txr; 516 517 qidx_t processed = 0; 518 qidx_t cur, prev, ntxd, rs_cidx; 519 int32_t delta; 520 bool is_done; 521 522 rs_cidx = txr->tx_rs_cidx; 523 if (rs_cidx == txr->tx_rs_pidx) 524 return (0); 525 cur = txr->tx_rsq[rs_cidx]; 526 MPASS(cur != QIDX_INVALID); 527 is_done = iavf_is_tx_desc_done(txr, cur); 528 529 if (!is_done) 530 return (0); 531 532 /* If clear is false just let caller know that there 533 * are descriptors to reclaim */ 534 if (!clear) 535 return (1); 536 537 prev = txr->tx_cidx_processed; 538 ntxd = scctx->isc_ntxd[0]; 539 do { 540 MPASS(prev != cur); 541 delta = (int32_t)cur - (int32_t)prev; 542 if (delta < 0) 543 delta += ntxd; 544 MPASS(delta > 0); 545 processed += delta; 546 prev = cur; 547 rs_cidx = (rs_cidx + 1) & (ntxd-1); 548 if (rs_cidx == txr->tx_rs_pidx) 549 break; 550 cur = txr->tx_rsq[rs_cidx]; 551 MPASS(cur != QIDX_INVALID); 552 is_done = iavf_is_tx_desc_done(txr, cur); 553 } while (is_done); 554 555 txr->tx_rs_cidx = rs_cidx; 556 txr->tx_cidx_processed = prev; 557 558 return (processed); 559 } 560 561 /** 562 * iavf_isc_rxd_refill - Prepare descriptors for re-use 563 * @arg: void pointer to the VSI 564 * @iru: the Rx descriptor update structure 565 * 566 * Update Rx descriptors for a given queue so that they can be re-used by 567 * hardware for future packets. 568 */ 569 static void 570 iavf_isc_rxd_refill(void *arg, if_rxd_update_t iru) 571 { 572 struct iavf_vsi *vsi = arg; 573 if_softc_ctx_t scctx = vsi->shared; 574 struct rx_ring *rxr = &((vsi->rx_queues[iru->iru_qsidx]).rxr); 575 uint64_t *paddrs; 576 uint16_t next_pidx, pidx; 577 uint16_t count; 578 int i; 579 580 paddrs = iru->iru_paddrs; 581 pidx = iru->iru_pidx; 582 count = iru->iru_count; 583 584 for (i = 0, next_pidx = pidx; i < count; i++) { 585 rxr->rx_base[next_pidx].read.pkt_addr = htole64(paddrs[i]); 586 if (++next_pidx == scctx->isc_nrxd[0]) 587 next_pidx = 0; 588 } 589 } 590 591 /** 592 * iavf_isc_rxd_flush - Notify hardware of new Rx descriptors 593 * @arg: void pointer to the VSI 594 * @rxqid: Rx queue to update 595 * @flid: unused parameter 596 * @pidx: ring index to update to 597 * 598 * Updates the tail pointer of the Rx ring, notifying hardware of new 599 * descriptors available for receiving packets. 600 */ 601 static void 602 iavf_isc_rxd_flush(void * arg, uint16_t rxqid, uint8_t flid __unused, qidx_t pidx) 603 { 604 struct iavf_vsi *vsi = arg; 605 struct rx_ring *rxr = &vsi->rx_queues[rxqid].rxr; 606 607 wr32(vsi->hw, rxr->tail, pidx); 608 } 609 610 /** 611 * iavf_isc_rxd_available - Calculate number of available Rx descriptors 612 * @arg: void pointer to the VSI 613 * @rxqid: Rx queue to check 614 * @idx: starting index to check from 615 * @budget: maximum Rx budget 616 * 617 * Determines how many packets are ready to be processed in the Rx queue, up 618 * to the specified budget. 619 * 620 * @returns the number of packets ready to be processed, up to the budget. 621 */ 622 static int 623 iavf_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, qidx_t budget) 624 { 625 struct iavf_vsi *vsi = arg; 626 struct rx_ring *rxr = &vsi->rx_queues[rxqid].rxr; 627 union iavf_rx_desc *rxd; 628 u64 qword; 629 uint32_t status; 630 int cnt, i, nrxd; 631 632 nrxd = vsi->shared->isc_nrxd[0]; 633 634 for (cnt = 0, i = idx; cnt < nrxd - 1 && cnt <= budget;) { 635 rxd = &rxr->rx_base[i]; 636 qword = le64toh(rxd->wb.qword1.status_error_len); 637 status = (qword & IAVF_RXD_QW1_STATUS_MASK) 638 >> IAVF_RXD_QW1_STATUS_SHIFT; 639 640 if ((status & (1 << IAVF_RX_DESC_STATUS_DD_SHIFT)) == 0) 641 break; 642 if (++i == nrxd) 643 i = 0; 644 if (status & (1 << IAVF_RX_DESC_STATUS_EOF_SHIFT)) 645 cnt++; 646 } 647 648 return (cnt); 649 } 650 651 /** 652 * iavf_isc_rxd_pkt_get - Decapsulate packet from Rx descriptors 653 * @arg: void pointer to the VSI 654 * @ri: packet info structure 655 * 656 * Read packet data from the Rx ring descriptors and fill in the packet info 657 * structure so that the iflib stack can process the packet. 658 * 659 * @remark this routine executes in ithread context. 660 * 661 * @returns zero success, or EBADMSG if the packet is corrupted. 662 */ 663 static int 664 iavf_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri) 665 { 666 struct iavf_vsi *vsi = arg; 667 if_softc_ctx_t scctx = vsi->shared; 668 struct iavf_rx_queue *que = &vsi->rx_queues[ri->iri_qsidx]; 669 struct rx_ring *rxr = &que->rxr; 670 union iavf_rx_desc *cur; 671 u32 status, error; 672 u16 plen; 673 u64 qword; 674 u8 ptype; 675 bool eop; 676 int i, cidx; 677 678 cidx = ri->iri_cidx; 679 i = 0; 680 do { 681 /* 5 descriptor receive limit */ 682 MPASS(i < IAVF_MAX_RX_SEGS); 683 684 cur = &rxr->rx_base[cidx]; 685 qword = le64toh(cur->wb.qword1.status_error_len); 686 status = (qword & IAVF_RXD_QW1_STATUS_MASK) 687 >> IAVF_RXD_QW1_STATUS_SHIFT; 688 error = (qword & IAVF_RXD_QW1_ERROR_MASK) 689 >> IAVF_RXD_QW1_ERROR_SHIFT; 690 plen = (qword & IAVF_RXD_QW1_LENGTH_PBUF_MASK) 691 >> IAVF_RXD_QW1_LENGTH_PBUF_SHIFT; 692 ptype = (qword & IAVF_RXD_QW1_PTYPE_MASK) 693 >> IAVF_RXD_QW1_PTYPE_SHIFT; 694 695 /* we should never be called without a valid descriptor */ 696 MPASS((status & (1 << IAVF_RX_DESC_STATUS_DD_SHIFT)) != 0); 697 698 ri->iri_len += plen; 699 rxr->rx_bytes += plen; 700 701 cur->wb.qword1.status_error_len = 0; 702 eop = (status & (1 << IAVF_RX_DESC_STATUS_EOF_SHIFT)); 703 704 /* 705 ** Make sure bad packets are discarded, 706 ** note that only EOP descriptor has valid 707 ** error results. 708 */ 709 if (eop && (error & (1 << IAVF_RX_DESC_ERROR_RXE_SHIFT))) { 710 rxr->desc_errs++; 711 return (EBADMSG); 712 } 713 ri->iri_frags[i].irf_flid = 0; 714 ri->iri_frags[i].irf_idx = cidx; 715 ri->iri_frags[i].irf_len = plen; 716 if (++cidx == vsi->shared->isc_nrxd[0]) 717 cidx = 0; 718 i++; 719 } while (!eop); 720 721 /* capture data for dynamic ITR adjustment */ 722 rxr->packets++; 723 rxr->rx_packets++; 724 725 if ((scctx->isc_capenable & IFCAP_RXCSUM) != 0) 726 iavf_rx_checksum(ri, status, error, ptype); 727 ri->iri_flowid = le32toh(cur->wb.qword0.hi_dword.rss); 728 ri->iri_rsstype = iavf_ptype_to_hash(ptype); 729 if (status & (1 << IAVF_RX_DESC_STATUS_L2TAG1P_SHIFT)) { 730 ri->iri_vtag = le16toh(cur->wb.qword0.lo_dword.l2tag1); 731 ri->iri_flags |= M_VLANTAG; 732 } 733 ri->iri_nfrags = i; 734 return (0); 735 } 736 737 /** 738 * iavf_rx_checksum - Handle Rx hardware checksum indication 739 * @ri: Rx packet info structure 740 * @status: status from Rx descriptor 741 * @error: error from Rx descriptor 742 * @ptype: packet type 743 * 744 * Verify that the hardware indicated that the checksum is valid. 745 * Inform the stack about the status of checksum so that stack 746 * doesn't spend time verifying the checksum. 747 */ 748 static void 749 iavf_rx_checksum(if_rxd_info_t ri, u32 status, u32 error, u8 ptype) 750 { 751 struct iavf_rx_ptype_decoded decoded; 752 753 ri->iri_csum_flags = 0; 754 755 /* No L3 or L4 checksum was calculated */ 756 if (!(status & (1 << IAVF_RX_DESC_STATUS_L3L4P_SHIFT))) 757 return; 758 759 decoded = decode_rx_desc_ptype(ptype); 760 761 /* IPv6 with extension headers likely have bad csum */ 762 if (decoded.outer_ip == IAVF_RX_PTYPE_OUTER_IP && 763 decoded.outer_ip_ver == IAVF_RX_PTYPE_OUTER_IPV6) { 764 if (status & 765 (1 << IAVF_RX_DESC_STATUS_IPV6EXADD_SHIFT)) { 766 ri->iri_csum_flags = 0; 767 return; 768 } 769 } 770 771 ri->iri_csum_flags |= CSUM_L3_CALC; 772 773 /* IPv4 checksum error */ 774 if (error & (1 << IAVF_RX_DESC_ERROR_IPE_SHIFT)) 775 return; 776 777 ri->iri_csum_flags |= CSUM_L3_VALID; 778 ri->iri_csum_flags |= CSUM_L4_CALC; 779 780 /* L4 checksum error */ 781 if (error & (1 << IAVF_RX_DESC_ERROR_L4E_SHIFT)) 782 return; 783 784 ri->iri_csum_flags |= CSUM_L4_VALID; 785 ri->iri_csum_data |= htons(0xffff); 786 } 787