1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright (c) 2024, 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 ice_iflib_txrx.c 34 * @brief iflib Tx/Rx hotpath 35 * 36 * Main location for the iflib Tx/Rx hotpath implementation. 37 * 38 * Contains the implementation for the iflib function callbacks and the 39 * if_txrx ops structure. 40 */ 41 42 #include "ice_iflib.h" 43 44 /* Tx/Rx hotpath utility functions */ 45 #include "ice_common_txrx.h" 46 47 /* 48 * Driver private implementations 49 */ 50 static int _ice_ift_txd_encap(struct ice_tx_queue *txq, if_pkt_info_t pi); 51 static int _ice_ift_txd_credits_update(struct ice_softc *sc, struct ice_tx_queue *txq, bool clear); 52 static int _ice_ift_rxd_available(struct ice_rx_queue *rxq, qidx_t pidx, qidx_t budget); 53 static int _ice_ift_rxd_pkt_get(struct ice_rx_queue *rxq, if_rxd_info_t ri); 54 static void _ice_ift_rxd_refill(struct ice_rx_queue *rxq, uint32_t pidx, 55 uint64_t *paddrs, uint16_t count); 56 static void _ice_ift_rxd_flush(struct ice_softc *sc, struct ice_rx_queue *rxq, 57 uint32_t pidx); 58 59 /* 60 * iflib txrx method declarations 61 */ 62 static int ice_ift_txd_encap(void *arg, if_pkt_info_t pi); 63 static int ice_ift_rxd_pkt_get(void *arg, if_rxd_info_t ri); 64 static void ice_ift_txd_flush(void *arg, uint16_t txqid, qidx_t pidx); 65 static int ice_ift_txd_credits_update(void *arg, uint16_t txqid, bool clear); 66 static int ice_ift_rxd_available(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget); 67 static void ice_ift_rxd_flush(void *arg, uint16_t rxqid, uint8_t flidx, qidx_t pidx); 68 static void ice_ift_rxd_refill(void *arg, if_rxd_update_t iru); 69 static qidx_t ice_ift_queue_select(void *arg, struct mbuf *m, if_pkt_info_t pi); 70 static int ice_ift_txd_credits_update_subif(void *arg, uint16_t txqid, bool clear); 71 static int ice_ift_txd_encap_subif(void *arg, if_pkt_info_t pi); 72 static void ice_ift_txd_flush_subif(void *arg, uint16_t txqid, qidx_t pidx); 73 static int ice_ift_rxd_available_subif(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget); 74 static int ice_ift_rxd_pkt_get_subif(void *arg, if_rxd_info_t ri); 75 static void ice_ift_rxd_refill_subif(void *arg, if_rxd_update_t iru); 76 static void ice_ift_rxd_flush_subif(void *arg, uint16_t rxqid, uint8_t flidx, qidx_t pidx); 77 78 /* Macro to help extract the NIC mode flexible Rx descriptor fields from the 79 * advanced 32byte Rx descriptors. 80 */ 81 #define RX_FLEX_NIC(desc, field) \ 82 (((struct ice_32b_rx_flex_desc_nic *)desc)->field) 83 84 /** 85 * @var ice_txrx 86 * @brief Tx/Rx operations for the iflib stack 87 * 88 * Structure defining the Tx and Rx related operations that iflib can request 89 * the driver to perform. These are the main entry points for the hot path of 90 * the transmit and receive paths in the iflib driver. 91 */ 92 struct if_txrx ice_txrx = { 93 .ift_txd_encap = ice_ift_txd_encap, 94 .ift_txd_flush = ice_ift_txd_flush, 95 .ift_txd_credits_update = ice_ift_txd_credits_update, 96 .ift_rxd_available = ice_ift_rxd_available, 97 .ift_rxd_pkt_get = ice_ift_rxd_pkt_get, 98 .ift_rxd_refill = ice_ift_rxd_refill, 99 .ift_rxd_flush = ice_ift_rxd_flush, 100 .ift_txq_select_v2 = ice_ift_queue_select, 101 }; 102 103 /** 104 * @var ice_subif_txrx 105 * @brief Tx/Rx operations for the iflib stack, for subinterfaces 106 * 107 * Structure defining the Tx and Rx related operations that iflib can request 108 * the subinterface driver to perform. These are the main entry points for the 109 * hot path of the transmit and receive paths in the iflib driver. 110 */ 111 struct if_txrx ice_subif_txrx = { 112 .ift_txd_credits_update = ice_ift_txd_credits_update_subif, 113 .ift_txd_encap = ice_ift_txd_encap_subif, 114 .ift_txd_flush = ice_ift_txd_flush_subif, 115 .ift_rxd_available = ice_ift_rxd_available_subif, 116 .ift_rxd_pkt_get = ice_ift_rxd_pkt_get_subif, 117 .ift_rxd_refill = ice_ift_rxd_refill_subif, 118 .ift_rxd_flush = ice_ift_rxd_flush_subif, 119 .ift_txq_select_v2 = NULL, 120 }; 121 122 /** 123 * _ice_ift_txd_encap - prepare Tx descriptors for a packet 124 * @txq: driver's TX queue context 125 * @pi: packet info 126 * 127 * Prepares and encapsulates the given packet into into Tx descriptors, in 128 * preparation for sending to the transmit engine. Sets the necessary context 129 * descriptors for TSO and other offloads, and prepares the last descriptor 130 * for the writeback status. 131 * 132 * Return 0 on success, non-zero error code on failure. 133 */ 134 static int 135 _ice_ift_txd_encap(struct ice_tx_queue *txq, if_pkt_info_t pi) 136 { 137 int nsegs = pi->ipi_nsegs; 138 bus_dma_segment_t *segs = pi->ipi_segs; 139 struct ice_tx_desc *txd = NULL; 140 int i, j, mask, pidx_last; 141 u32 cmd, off, tx_intr, txd_cmd; 142 143 cmd = off = 0; 144 i = pi->ipi_pidx; 145 tx_intr = pi->ipi_flags & IPI_TX_INTR; 146 txd_cmd = ICE_TX_DESC_CMD_EOP; 147 if (tx_intr) 148 txd_cmd |= ICE_TX_DESC_CMD_RS; 149 150 /* Set up the TSO/CSUM offload */ 151 if (pi->ipi_csum_flags & ICE_CSUM_OFFLOAD) { 152 /* Set up the TSO context descriptor if required */ 153 if (pi->ipi_csum_flags & CSUM_TSO) { 154 if (ice_tso_detect_sparse(pi)) 155 return (EFBIG); 156 i = ice_tso_setup(txq, pi); 157 } 158 ice_tx_setup_offload(txq, pi, &cmd, &off); 159 } 160 if (pi->ipi_mflags & M_VLANTAG) 161 cmd |= ICE_TX_DESC_CMD_IL2TAG1; 162 163 mask = txq->desc_count - 1; 164 for (j = 0; j < nsegs; j++) { 165 bus_size_t seglen; 166 167 txd = &txq->tx_base[i]; 168 seglen = segs[j].ds_len; 169 170 txd->buf_addr = htole64(segs[j].ds_addr); 171 txd->cmd_type_offset_bsz = 172 htole64(ICE_TX_DESC_DTYPE_DATA 173 | ((u64)cmd << ICE_TXD_QW1_CMD_S) 174 | ((u64)off << ICE_TXD_QW1_OFFSET_S) 175 | ((u64)seglen << ICE_TXD_QW1_TX_BUF_SZ_S) 176 | ((u64)htole16(pi->ipi_vtag) << ICE_TXD_QW1_L2TAG1_S)); 177 178 txq->stats.tx_bytes += seglen; 179 pidx_last = i; 180 i = (i+1) & mask; 181 } 182 183 /* Set the last descriptor for report */ 184 txd->cmd_type_offset_bsz |= 185 htole64((u64)txd_cmd << ICE_TXD_QW1_CMD_S); 186 187 /* Add to report status array if requesting descriptor writeback. */ 188 if (tx_intr) { 189 txq->tx_rsq[txq->tx_rs_pidx] = pidx_last; 190 txq->tx_rs_pidx = (txq->tx_rs_pidx+1) & mask; 191 MPASS(txq->tx_rs_pidx != txq->tx_rs_cidx); 192 } 193 194 pi->ipi_new_pidx = i; 195 196 ++txq->stats.tx_packets; 197 return (0); 198 } 199 200 /** 201 * ice_ift_txd_encap - prepare Tx descriptors for a packet 202 * @arg: the iflib softc structure pointer 203 * @pi: packet info 204 * 205 * Prepares and encapsulates the given packet into Tx descriptors, in 206 * preparation for sending to the transmit engine. Sets the necessary context 207 * descriptors for TSO and other offloads, and prepares the last descriptor 208 * for the writeback status. 209 * 210 * Return 0 on success, non-zero error code on failure. 211 */ 212 static int 213 ice_ift_txd_encap(void *arg, if_pkt_info_t pi) 214 { 215 struct ice_softc *sc = (struct ice_softc *)arg; 216 struct ice_tx_queue *txq = &sc->pf_vsi.tx_queues[pi->ipi_qsidx]; 217 218 return _ice_ift_txd_encap(txq, pi); 219 } 220 221 /** 222 * ice_ift_txd_flush - Flush Tx descriptors to hardware 223 * @arg: device specific softc pointer 224 * @txqid: the Tx queue to flush 225 * @pidx: descriptor index to advance tail to 226 * 227 * Advance the Transmit Descriptor Tail (TDT). This indicates to hardware that 228 * frames are available for transmit. 229 */ 230 static void 231 ice_ift_txd_flush(void *arg, uint16_t txqid, qidx_t pidx) 232 { 233 struct ice_softc *sc = (struct ice_softc *)arg; 234 struct ice_tx_queue *txq = &sc->pf_vsi.tx_queues[txqid]; 235 struct ice_hw *hw = &sc->hw; 236 237 wr32(hw, txq->tail, pidx); 238 } 239 240 /** 241 * _ice_ift_txd_credits_update - cleanup Tx descriptors 242 * @sc: device private softc 243 * @txq: the Tx queue to update 244 * @clear: if false, only report, do not actually clean 245 * 246 * If clear is false, iflib is asking if we *could* clean up any Tx 247 * descriptors. 248 * 249 * If clear is true, iflib is requesting to cleanup and reclaim used Tx 250 * descriptors. 251 * 252 * Called by other txd_credits_update functions passed to iflib. 253 */ 254 static int 255 _ice_ift_txd_credits_update(struct ice_softc *sc __unused, struct ice_tx_queue *txq, bool clear) 256 { 257 qidx_t processed = 0; 258 qidx_t cur, prev, ntxd, rs_cidx; 259 int32_t delta; 260 bool is_done; 261 262 rs_cidx = txq->tx_rs_cidx; 263 if (rs_cidx == txq->tx_rs_pidx) 264 return (0); 265 cur = txq->tx_rsq[rs_cidx]; 266 MPASS(cur != QIDX_INVALID); 267 is_done = ice_is_tx_desc_done(&txq->tx_base[cur]); 268 269 if (!is_done) 270 return (0); 271 else if (clear == false) 272 return (1); 273 274 prev = txq->tx_cidx_processed; 275 ntxd = txq->desc_count; 276 do { 277 MPASS(prev != cur); 278 delta = (int32_t)cur - (int32_t)prev; 279 if (delta < 0) 280 delta += ntxd; 281 MPASS(delta > 0); 282 processed += delta; 283 prev = cur; 284 rs_cidx = (rs_cidx + 1) & (ntxd-1); 285 if (rs_cidx == txq->tx_rs_pidx) 286 break; 287 cur = txq->tx_rsq[rs_cidx]; 288 MPASS(cur != QIDX_INVALID); 289 is_done = ice_is_tx_desc_done(&txq->tx_base[cur]); 290 } while (is_done); 291 292 txq->tx_rs_cidx = rs_cidx; 293 txq->tx_cidx_processed = prev; 294 295 return (processed); 296 } 297 298 /** 299 * ice_ift_txd_credits_update - cleanup PF VSI Tx descriptors 300 * @arg: device private softc 301 * @txqid: the Tx queue to update 302 * @clear: if false, only report, do not actually clean 303 * 304 * Wrapper for _ice_ift_txd_credits_update() meant for TX queues that 305 * belong to the PF VSI. 306 * 307 * @see _ice_ift_txd_credits_update() 308 */ 309 static int 310 ice_ift_txd_credits_update(void *arg, uint16_t txqid, bool clear) 311 { 312 struct ice_softc *sc = (struct ice_softc *)arg; 313 struct ice_tx_queue *txq = &sc->pf_vsi.tx_queues[txqid]; 314 315 return _ice_ift_txd_credits_update(sc, txq, clear); 316 } 317 318 /** 319 * _ice_ift_rxd_available - Return number of available Rx packets 320 * @rxq: RX queue driver structure 321 * @pidx: descriptor start point 322 * @budget: maximum Rx budget 323 * 324 * Determines how many Rx packets are available on the queue, up to a maximum 325 * of the given budget. 326 */ 327 static int 328 _ice_ift_rxd_available(struct ice_rx_queue *rxq, qidx_t pidx, qidx_t budget) 329 { 330 union ice_32b_rx_flex_desc *rxd; 331 uint16_t status0; 332 int cnt, i, nrxd; 333 334 nrxd = rxq->desc_count; 335 336 for (cnt = 0, i = pidx; cnt < nrxd - 1 && cnt < budget;) { 337 rxd = &rxq->rx_base[i]; 338 status0 = le16toh(rxd->wb.status_error0); 339 340 if ((status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_DD_S)) == 0) 341 break; 342 if (++i == nrxd) 343 i = 0; 344 if (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_EOF_S)) 345 cnt++; 346 } 347 348 return (cnt); 349 } 350 351 /** 352 * ice_ift_rxd_available - Return number of available Rx packets 353 * @arg: device private softc 354 * @rxqid: the Rx queue id 355 * @pidx: descriptor start point 356 * @budget: maximum Rx budget 357 * 358 * Wrapper for _ice_ift_rxd_available() that provides a function pointer 359 * that iflib requires for RX processing. 360 */ 361 static int 362 ice_ift_rxd_available(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget) 363 { 364 struct ice_softc *sc = (struct ice_softc *)arg; 365 struct ice_rx_queue *rxq = &sc->pf_vsi.rx_queues[rxqid]; 366 367 return _ice_ift_rxd_available(rxq, pidx, budget); 368 } 369 370 /** 371 * ice_ift_rxd_pkt_get - Called by iflib to send data to upper layer 372 * @arg: device specific softc 373 * @ri: receive packet info 374 * 375 * Wrapper function for _ice_ift_rxd_pkt_get() that provides a function pointer 376 * used by iflib for RX packet processing. 377 */ 378 static int 379 ice_ift_rxd_pkt_get(void *arg, if_rxd_info_t ri) 380 { 381 struct ice_softc *sc = (struct ice_softc *)arg; 382 struct ice_rx_queue *rxq = &sc->pf_vsi.rx_queues[ri->iri_qsidx]; 383 384 return _ice_ift_rxd_pkt_get(rxq, ri); 385 } 386 387 /** 388 * _ice_ift_rxd_pkt_get - Called by iflib to send data to upper layer 389 * @rxq: RX queue driver structure 390 * @ri: receive packet info 391 * 392 * This function is called by iflib, and executes in ithread context. It is 393 * called by iflib to obtain data which has been DMA'ed into host memory. 394 * Returns zero on success, and EBADMSG on failure. 395 */ 396 static int 397 _ice_ift_rxd_pkt_get(struct ice_rx_queue *rxq, if_rxd_info_t ri) 398 { 399 union ice_32b_rx_flex_desc *cur; 400 u16 status0, plen, ptype; 401 bool eop; 402 size_t cidx; 403 int i; 404 405 cidx = ri->iri_cidx; 406 i = 0; 407 do { 408 /* 5 descriptor receive limit */ 409 MPASS(i < ICE_MAX_RX_SEGS); 410 411 cur = &rxq->rx_base[cidx]; 412 status0 = le16toh(cur->wb.status_error0); 413 plen = le16toh(cur->wb.pkt_len) & 414 ICE_RX_FLX_DESC_PKT_LEN_M; 415 416 /* we should never be called without a valid descriptor */ 417 MPASS((status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_DD_S)) != 0); 418 419 ri->iri_len += plen; 420 421 cur->wb.status_error0 = 0; 422 eop = (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_EOF_S)); 423 424 ri->iri_frags[i].irf_flid = 0; 425 ri->iri_frags[i].irf_idx = cidx; 426 ri->iri_frags[i].irf_len = plen; 427 if (++cidx == rxq->desc_count) 428 cidx = 0; 429 i++; 430 } while (!eop); 431 432 /* End of Packet reached; cur is eop/last descriptor */ 433 434 /* Make sure packets with bad L2 values are discarded. 435 * This bit is only valid in the last descriptor. 436 */ 437 if (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_RXE_S)) { 438 rxq->stats.desc_errs++; 439 return (EBADMSG); 440 } 441 442 /* Get VLAN tag information if one is in descriptor */ 443 if (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_L2TAG1P_S)) { 444 ri->iri_vtag = le16toh(cur->wb.l2tag1); 445 ri->iri_flags |= M_VLANTAG; 446 } 447 448 /* Capture soft statistics for this Rx queue */ 449 rxq->stats.rx_packets++; 450 rxq->stats.rx_bytes += ri->iri_len; 451 452 /* Get packet type and set checksum flags */ 453 ptype = le16toh(cur->wb.ptype_flex_flags0) & 454 ICE_RX_FLEX_DESC_PTYPE_M; 455 if ((if_getcapenable(ri->iri_ifp) & IFCAP_RXCSUM) != 0) 456 ice_rx_checksum(rxq, &ri->iri_csum_flags, 457 &ri->iri_csum_data, status0, ptype); 458 459 /* Set remaining iflib RX descriptor info fields */ 460 ri->iri_flowid = le32toh(RX_FLEX_NIC(&cur->wb, rss_hash)); 461 ri->iri_rsstype = ice_ptype_to_hash(ptype); 462 ri->iri_nfrags = i; 463 return (0); 464 } 465 466 /** 467 * ice_ift_rxd_refill - Prepare Rx descriptors for re-use by hardware 468 * @arg: device specific softc structure 469 * @iru: the Rx descriptor update structure 470 * 471 * Wrapper function for _ice_ift_rxd_refill() that provides a function pointer 472 * used by iflib for RX packet processing. 473 */ 474 static void 475 ice_ift_rxd_refill(void *arg, if_rxd_update_t iru) 476 { 477 struct ice_softc *sc = (struct ice_softc *)arg; 478 struct ice_rx_queue *rxq; 479 uint64_t *paddrs; 480 uint32_t pidx; 481 uint16_t qsidx, count; 482 483 paddrs = iru->iru_paddrs; 484 pidx = iru->iru_pidx; 485 qsidx = iru->iru_qsidx; 486 count = iru->iru_count; 487 488 rxq = &(sc->pf_vsi.rx_queues[qsidx]); 489 490 _ice_ift_rxd_refill(rxq, pidx, paddrs, count); 491 } 492 493 /** 494 * _ice_ift_rxd_refill - Prepare Rx descriptors for re-use by hardware 495 * @rxq: RX queue driver structure 496 * @pidx: first index to refill 497 * @paddrs: physical addresses to use 498 * @count: number of descriptors to refill 499 * 500 * Update the Rx descriptor indices for a given queue, assigning new physical 501 * addresses to the descriptors, preparing them for re-use by the hardware. 502 */ 503 static void 504 _ice_ift_rxd_refill(struct ice_rx_queue *rxq, uint32_t pidx, 505 uint64_t *paddrs, uint16_t count) 506 { 507 uint32_t next_pidx; 508 int i; 509 510 for (i = 0, next_pidx = pidx; i < count; i++) { 511 rxq->rx_base[next_pidx].read.pkt_addr = htole64(paddrs[i]); 512 if (++next_pidx == (uint32_t)rxq->desc_count) 513 next_pidx = 0; 514 } 515 } 516 517 /** 518 * ice_ift_rxd_flush - Flush Rx descriptors to hardware 519 * @arg: device specific softc pointer 520 * @rxqid: the Rx queue to flush 521 * @flidx: unused parameter 522 * @pidx: descriptor index to advance tail to 523 * 524 * Wrapper function for _ice_ift_rxd_flush() that provides a function pointer 525 * used by iflib for RX packet processing. 526 */ 527 static void 528 ice_ift_rxd_flush(void *arg, uint16_t rxqid, uint8_t flidx __unused, 529 qidx_t pidx) 530 { 531 struct ice_softc *sc = (struct ice_softc *)arg; 532 struct ice_rx_queue *rxq = &sc->pf_vsi.rx_queues[rxqid]; 533 534 _ice_ift_rxd_flush(sc, rxq, (uint32_t)pidx); 535 } 536 537 /** 538 * _ice_ift_rxd_flush - Flush Rx descriptors to hardware 539 * @sc: device specific softc pointer 540 * @rxq: RX queue driver structure 541 * @pidx: descriptor index to advance tail to 542 * 543 * Advance the Receive Descriptor Tail (RDT). This indicates to hardware that 544 * software is done with the descriptor and it can be recycled. 545 */ 546 static void 547 _ice_ift_rxd_flush(struct ice_softc *sc, struct ice_rx_queue *rxq, uint32_t pidx) 548 { 549 wr32(&sc->hw, rxq->tail, pidx); 550 } 551 552 /** 553 * ice_ift_queue_select - Select queue index to transmit packet on 554 * @arg: device specific softc 555 * @m: transmit packet data 556 * @pi: transmit packet metadata 557 * 558 * Called by iflib to determine which queue index to transmit the packet 559 * pointed to by @m on. In particular, ensures packets go out on the right 560 * queue index for the right transmit class when multiple traffic classes are 561 * enabled in the driver. 562 */ 563 static qidx_t 564 ice_ift_queue_select(void *arg, struct mbuf *m, if_pkt_info_t pi) 565 { 566 struct ice_softc *sc = (struct ice_softc *)arg; 567 struct ice_dcbx_cfg *local_dcbx_cfg; 568 struct ice_vsi *vsi = &sc->pf_vsi; 569 u16 tc_base_queue, tc_qcount; 570 u8 up, tc; 571 572 #ifdef ALTQ 573 /* Included to match default iflib behavior */ 574 /* Only go out on default queue if ALTQ is enabled */ 575 struct ifnet *ifp = (struct ifnet *)iflib_get_ifp(sc->ctx); 576 if (if_altq_is_enabled(ifp)) 577 return (0); 578 #endif 579 580 if (!ice_test_state(&sc->state, ICE_STATE_MULTIPLE_TCS)) { 581 if (M_HASHTYPE_GET(m)) { 582 /* Default iflib queue selection method */ 583 return (m->m_pkthdr.flowid % sc->pf_vsi.num_tx_queues); 584 } else 585 return (0); 586 } 587 588 /* Use default TC unless overridden later */ 589 tc = 0; /* XXX: Get default TC for traffic if >1 TC? */ 590 591 local_dcbx_cfg = &sc->hw.port_info->qos_cfg.local_dcbx_cfg; 592 593 #if defined(INET) || defined(INET6) 594 if ((local_dcbx_cfg->pfc_mode == ICE_QOS_MODE_DSCP) && 595 (pi->ipi_flags & (IPI_TX_IPV4 | IPI_TX_IPV6))) { 596 u8 dscp_val = pi->ipi_ip_tos >> 2; 597 tc = local_dcbx_cfg->dscp_map[dscp_val]; 598 } else 599 #endif /* defined(INET) || defined(INET6) */ 600 if (m->m_flags & M_VLANTAG) { /* ICE_QOS_MODE_VLAN */ 601 up = EVL_PRIOFTAG(m->m_pkthdr.ether_vtag); 602 tc = local_dcbx_cfg->etscfg.prio_table[up]; 603 } 604 605 tc_base_queue = vsi->tc_info[tc].qoffset; 606 tc_qcount = vsi->tc_info[tc].qcount_tx; 607 608 if (M_HASHTYPE_GET(m)) 609 return ((m->m_pkthdr.flowid % tc_qcount) + tc_base_queue); 610 else 611 return (tc_base_queue); 612 } 613 614 /** 615 * ice_ift_txd_credits_update_subif - cleanup subinterface VSI Tx descriptors 616 * @arg: subinterface private structure (struct ice_mirr_if) 617 * @txqid: the Tx queue to update 618 * @clear: if false, only report, do not actually clean 619 * 620 * Wrapper for _ice_ift_txd_credits_update() meant for TX queues that 621 * do not belong to the PF VSI. 622 * 623 * See _ice_ift_txd_credits_update(). 624 */ 625 static int 626 ice_ift_txd_credits_update_subif(void *arg, uint16_t txqid, bool clear) 627 { 628 struct ice_mirr_if *mif = (struct ice_mirr_if *)arg; 629 struct ice_softc *sc = mif->back; 630 struct ice_tx_queue *txq = &mif->vsi->tx_queues[txqid]; 631 632 return _ice_ift_txd_credits_update(sc, txq, clear); 633 } 634 635 /** 636 * ice_ift_txd_encap_subif - prepare Tx descriptors for a packet 637 * @arg: subinterface private structure (struct ice_mirr_if) 638 * @pi: packet info 639 * 640 * Wrapper for _ice_ift_txd_encap_subif() meant for TX queues that 641 * do not belong to the PF VSI. 642 * 643 * See _ice_ift_txd_encap_subif(). 644 */ 645 static int 646 ice_ift_txd_encap_subif(void *arg, if_pkt_info_t pi) 647 { 648 struct ice_mirr_if *mif = (struct ice_mirr_if *)arg; 649 struct ice_tx_queue *txq = &mif->vsi->tx_queues[pi->ipi_qsidx]; 650 651 return _ice_ift_txd_encap(txq, pi); 652 } 653 654 /** 655 * ice_ift_txd_flush_subif - Flush Tx descriptors to hardware 656 * @arg: subinterface private structure (struct ice_mirr_if) 657 * @txqid: the Tx queue to flush 658 * @pidx: descriptor index to advance tail to 659 * 660 * Advance the Transmit Descriptor Tail (TDT). Functionally identical to 661 * the ice_ift_txd_encap() meant for the main PF VSI, but provides a function 662 * pointer to iflib for use with non-main-PF VSI TX queues. 663 */ 664 static void 665 ice_ift_txd_flush_subif(void *arg, uint16_t txqid, qidx_t pidx) 666 { 667 struct ice_mirr_if *mif = (struct ice_mirr_if *)arg; 668 struct ice_tx_queue *txq = &mif->vsi->tx_queues[txqid]; 669 struct ice_hw *hw = &mif->back->hw; 670 671 wr32(hw, txq->tail, pidx); 672 } 673 674 /** 675 * ice_ift_rxd_available_subif - Return number of available Rx packets 676 * @arg: subinterface private structure (struct ice_mirr_if) 677 * @rxqid: the Rx queue id 678 * @pidx: descriptor start point 679 * @budget: maximum Rx budget 680 * 681 * Determines how many Rx packets are available on the queue, up to a maximum 682 * of the given budget. 683 * 684 * See _ice_ift_rxd_available(). 685 */ 686 static int 687 ice_ift_rxd_available_subif(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget) 688 { 689 struct ice_mirr_if *mif = (struct ice_mirr_if *)arg; 690 struct ice_rx_queue *rxq = &mif->vsi->rx_queues[rxqid]; 691 692 return _ice_ift_rxd_available(rxq, pidx, budget); 693 } 694 695 /** 696 * ice_ift_rxd_pkt_get_subif - Called by iflib to send data to upper layer 697 * @arg: subinterface private structure (struct ice_mirr_if) 698 * @ri: receive packet info 699 * 700 * Wrapper function for _ice_ift_rxd_pkt_get() that provides a function pointer 701 * used by iflib for RX packet processing, for iflib subinterfaces. 702 */ 703 static int 704 ice_ift_rxd_pkt_get_subif(void *arg, if_rxd_info_t ri) 705 { 706 struct ice_mirr_if *mif = (struct ice_mirr_if *)arg; 707 struct ice_rx_queue *rxq = &mif->vsi->rx_queues[ri->iri_qsidx]; 708 709 return _ice_ift_rxd_pkt_get(rxq, ri); 710 } 711 712 /** 713 * ice_ift_rxd_refill_subif - Prepare Rx descriptors for re-use by hardware 714 * @arg: subinterface private structure (struct ice_mirr_if) 715 * @iru: the Rx descriptor update structure 716 * 717 * Wrapper function for _ice_ift_rxd_refill() that provides a function pointer 718 * used by iflib for RX packet processing, for iflib subinterfaces. 719 */ 720 static void 721 ice_ift_rxd_refill_subif(void *arg, if_rxd_update_t iru) 722 { 723 struct ice_mirr_if *mif = (struct ice_mirr_if *)arg; 724 struct ice_rx_queue *rxq = &mif->vsi->rx_queues[iru->iru_qsidx]; 725 726 uint64_t *paddrs; 727 uint32_t pidx; 728 uint16_t count; 729 730 paddrs = iru->iru_paddrs; 731 pidx = iru->iru_pidx; 732 count = iru->iru_count; 733 734 _ice_ift_rxd_refill(rxq, pidx, paddrs, count); 735 } 736 737 /** 738 * ice_ift_rxd_flush_subif - Flush Rx descriptors to hardware 739 * @arg: subinterface private structure (struct ice_mirr_if) 740 * @rxqid: the Rx queue to flush 741 * @flidx: unused parameter 742 * @pidx: descriptor index to advance tail to 743 * 744 * Wrapper function for _ice_ift_rxd_flush() that provides a function pointer 745 * used by iflib for RX packet processing. 746 */ 747 static void 748 ice_ift_rxd_flush_subif(void *arg, uint16_t rxqid, uint8_t flidx __unused, 749 qidx_t pidx) 750 { 751 struct ice_mirr_if *mif = (struct ice_mirr_if *)arg; 752 struct ice_rx_queue *rxq = &mif->vsi->rx_queues[rxqid]; 753 754 _ice_ift_rxd_flush(mif->back, rxq, pidx); 755 } 756