1*c58d34ddSKevin Bowling /***************************************************************************** 2758cc3dcSJack F Vogel 38eb6488eSEric Joyner Copyright (c) 2001-2017, Intel Corporation 4758cc3dcSJack F Vogel All rights reserved. 5758cc3dcSJack F Vogel 6758cc3dcSJack F Vogel Redistribution and use in source and binary forms, with or without 7758cc3dcSJack F Vogel modification, are permitted provided that the following conditions are met: 8758cc3dcSJack F Vogel 9758cc3dcSJack F Vogel 1. Redistributions of source code must retain the above copyright notice, 10758cc3dcSJack F Vogel this list of conditions and the following disclaimer. 11758cc3dcSJack F Vogel 12758cc3dcSJack F Vogel 2. Redistributions in binary form must reproduce the above copyright 13758cc3dcSJack F Vogel notice, this list of conditions and the following disclaimer in the 14758cc3dcSJack F Vogel documentation and/or other materials provided with the distribution. 15758cc3dcSJack F Vogel 16758cc3dcSJack F Vogel 3. Neither the name of the Intel Corporation nor the names of its 17758cc3dcSJack F Vogel contributors may be used to endorse or promote products derived from 18758cc3dcSJack F Vogel this software without specific prior written permission. 19758cc3dcSJack F Vogel 20758cc3dcSJack F Vogel THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21758cc3dcSJack F Vogel AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22758cc3dcSJack F Vogel IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23758cc3dcSJack F Vogel ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24758cc3dcSJack F Vogel LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25758cc3dcSJack F Vogel CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26758cc3dcSJack F Vogel SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27758cc3dcSJack F Vogel INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28758cc3dcSJack F Vogel CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29758cc3dcSJack F Vogel ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30758cc3dcSJack F Vogel POSSIBILITY OF SUCH DAMAGE. 31758cc3dcSJack F Vogel 32*c58d34ddSKevin Bowling *****************************************************************************/ 33758cc3dcSJack F Vogel 34758cc3dcSJack F Vogel #ifndef IXGBE_STANDALONE_BUILD 35758cc3dcSJack F Vogel #include "opt_inet.h" 36758cc3dcSJack F Vogel #include "opt_inet6.h" 37758cc3dcSJack F Vogel #include "opt_rss.h" 38758cc3dcSJack F Vogel #endif 39758cc3dcSJack F Vogel 40758cc3dcSJack F Vogel #include "ixgbe.h" 41758cc3dcSJack F Vogel 428eb6488eSEric Joyner /************************************************************************ 43758cc3dcSJack F Vogel * Local Function prototypes 448eb6488eSEric Joyner ************************************************************************/ 45b1d5caf3SKevin Bowling static int ixgbe_isc_txd_encap(void *, if_pkt_info_t); 46b1d5caf3SKevin Bowling static void ixgbe_isc_txd_flush(void *, uint16_t, qidx_t); 47b1d5caf3SKevin Bowling static int ixgbe_isc_txd_credits_update(void *, uint16_t, bool); 48758cc3dcSJack F Vogel 49b1d5caf3SKevin Bowling static void ixgbe_isc_rxd_refill(void *, if_rxd_update_t); 50b1d5caf3SKevin Bowling static void ixgbe_isc_rxd_flush(void *, uint16_t, uint8_t, qidx_t); 51b1d5caf3SKevin Bowling static int ixgbe_isc_rxd_available(void *, uint16_t, qidx_t, qidx_t); 52b1d5caf3SKevin Bowling static int ixgbe_isc_rxd_pkt_get(void *, if_rxd_info_t); 53758cc3dcSJack F Vogel 54b1d5caf3SKevin Bowling static void ixgbe_rx_checksum(uint32_t, if_rxd_info_t, uint32_t); 5551e46835SKevin Bowling static int ixgbe_tx_ctx_setup(struct ixgbe_adv_tx_context_desc *, 5651e46835SKevin Bowling if_pkt_info_t); 57758cc3dcSJack F Vogel 58c19c7afeSEric Joyner extern void ixgbe_if_enable_intr(if_ctx_t ctx); 5951e46835SKevin Bowling static int ixgbe_determine_rsstype(uint16_t pkt_info); 60758cc3dcSJack F Vogel 61c19c7afeSEric Joyner struct if_txrx ixgbe_txrx = { 62fbf8b74cSMark Johnston .ift_txd_encap = ixgbe_isc_txd_encap, 63fbf8b74cSMark Johnston .ift_txd_flush = ixgbe_isc_txd_flush, 64fbf8b74cSMark Johnston .ift_txd_credits_update = ixgbe_isc_txd_credits_update, 65fbf8b74cSMark Johnston .ift_rxd_available = ixgbe_isc_rxd_available, 66fbf8b74cSMark Johnston .ift_rxd_pkt_get = ixgbe_isc_rxd_pkt_get, 67fbf8b74cSMark Johnston .ift_rxd_refill = ixgbe_isc_rxd_refill, 68fbf8b74cSMark Johnston .ift_rxd_flush = ixgbe_isc_rxd_flush, 69fbf8b74cSMark Johnston .ift_legacy_intr = NULL 70c19c7afeSEric Joyner }; 71758cc3dcSJack F Vogel 728eb6488eSEric Joyner /************************************************************************ 738eb6488eSEric Joyner * ixgbe_tx_ctx_setup 74758cc3dcSJack F Vogel * 75758cc3dcSJack F Vogel * Advanced Context Descriptor setup for VLAN, CSUM or TSO 76c19c7afeSEric Joyner * 778eb6488eSEric Joyner ************************************************************************/ 78758cc3dcSJack F Vogel static int 79c19c7afeSEric Joyner ixgbe_tx_ctx_setup(struct ixgbe_adv_tx_context_desc *TXD, if_pkt_info_t pi) 80758cc3dcSJack F Vogel { 8151e46835SKevin Bowling uint32_t vlan_macip_lens, type_tucmd_mlhl; 8251e46835SKevin Bowling uint32_t olinfo_status, mss_l4len_idx, pktlen, offload; 83c19c7afeSEric Joyner u8 ehdrlen; 84a9ca1c79SSean Bruno 8579b36ec9SKevin Bowling offload = true; 86c19c7afeSEric Joyner olinfo_status = mss_l4len_idx = vlan_macip_lens = type_tucmd_mlhl = 0; 87c19c7afeSEric Joyner /* VLAN MACLEN IPLEN */ 88c19c7afeSEric Joyner vlan_macip_lens |= (htole16(pi->ipi_vtag) << IXGBE_ADVTXD_VLAN_SHIFT); 89758cc3dcSJack F Vogel 90758cc3dcSJack F Vogel /* 91c19c7afeSEric Joyner * Some of our VF devices need a context descriptor for every 92c19c7afeSEric Joyner * packet. That means the ehdrlen needs to be non-zero in order 93c19c7afeSEric Joyner * for the host driver not to flag a malicious event. The stack 94c19c7afeSEric Joyner * will most likely populate this for all other reasons of why 95c19c7afeSEric Joyner * this function was called. 96758cc3dcSJack F Vogel */ 97c19c7afeSEric Joyner if (pi->ipi_ehdrlen == 0) { 98758cc3dcSJack F Vogel ehdrlen = ETHER_HDR_LEN; 99c19c7afeSEric Joyner ehdrlen += (pi->ipi_vtag != 0) ? ETHER_VLAN_ENCAP_LEN : 0; 100c19c7afeSEric Joyner } else 101c19c7afeSEric Joyner ehdrlen = pi->ipi_ehdrlen; 102758cc3dcSJack F Vogel vlan_macip_lens |= ehdrlen << IXGBE_ADVTXD_MACLEN_SHIFT; 103758cc3dcSJack F Vogel 104c19c7afeSEric Joyner pktlen = pi->ipi_len; 105c19c7afeSEric Joyner /* First check if TSO is to be used */ 106c19c7afeSEric Joyner if (pi->ipi_csum_flags & CSUM_TSO) { 107c19c7afeSEric Joyner /* This is used in the transmit desc in encap */ 108*c58d34ddSKevin Bowling pktlen = pi->ipi_len - ehdrlen - pi->ipi_ip_hlen - 109*c58d34ddSKevin Bowling pi->ipi_tcp_hlen; 110*c58d34ddSKevin Bowling mss_l4len_idx |= 111*c58d34ddSKevin Bowling (pi->ipi_tso_segsz << IXGBE_ADVTXD_MSS_SHIFT); 112*c58d34ddSKevin Bowling mss_l4len_idx |= 113*c58d34ddSKevin Bowling (pi->ipi_tcp_hlen << IXGBE_ADVTXD_L4LEN_SHIFT); 114a9ca1c79SSean Bruno } 115c19c7afeSEric Joyner 116c19c7afeSEric Joyner olinfo_status |= pktlen << IXGBE_ADVTXD_PAYLEN_SHIFT; 117c19c7afeSEric Joyner 118c19c7afeSEric Joyner if (pi->ipi_flags & IPI_TX_IPV4) { 119c19c7afeSEric Joyner type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4; 120c19c7afeSEric Joyner /* Tell transmit desc to also do IPv4 checksum. */ 121c19c7afeSEric Joyner if (pi->ipi_csum_flags & (CSUM_IP|CSUM_TSO)) 122c19c7afeSEric Joyner olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8; 123c19c7afeSEric Joyner } else if (pi->ipi_flags & IPI_TX_IPV6) 124758cc3dcSJack F Vogel type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6; 125c19c7afeSEric Joyner else 12679b36ec9SKevin Bowling offload = false; 127c19c7afeSEric Joyner 128c19c7afeSEric Joyner vlan_macip_lens |= pi->ipi_ip_hlen; 129c19c7afeSEric Joyner 130c19c7afeSEric Joyner switch (pi->ipi_ipproto) { 131c19c7afeSEric Joyner case IPPROTO_TCP: 132*c58d34ddSKevin Bowling if (pi->ipi_csum_flags & 133*c58d34ddSKevin Bowling (CSUM_IP_TCP | CSUM_IP6_TCP | CSUM_TSO)) 134c19c7afeSEric Joyner type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP; 135c19c7afeSEric Joyner else 13679b36ec9SKevin Bowling offload = false; 137758cc3dcSJack F Vogel break; 138c19c7afeSEric Joyner case IPPROTO_UDP: 139c19c7afeSEric Joyner if (pi->ipi_csum_flags & (CSUM_IP_UDP | CSUM_IP6_UDP)) 140c19c7afeSEric Joyner type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_UDP; 141c19c7afeSEric Joyner else 14279b36ec9SKevin Bowling offload = false; 143c19c7afeSEric Joyner break; 144c19c7afeSEric Joyner case IPPROTO_SCTP: 145c19c7afeSEric Joyner if (pi->ipi_csum_flags & (CSUM_IP_SCTP | CSUM_IP6_SCTP)) 146c19c7afeSEric Joyner type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_SCTP; 147c19c7afeSEric Joyner else 14879b36ec9SKevin Bowling offload = false; 149c19c7afeSEric Joyner break; 150758cc3dcSJack F Vogel default: 15179b36ec9SKevin Bowling offload = false; 152758cc3dcSJack F Vogel break; 153758cc3dcSJack F Vogel } 154c19c7afeSEric Joyner /* Insert L4 checksum into data descriptors */ 155c19c7afeSEric Joyner if (offload) 156c19c7afeSEric Joyner olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8; 157758cc3dcSJack F Vogel 158758cc3dcSJack F Vogel type_tucmd_mlhl |= IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT; 159758cc3dcSJack F Vogel 160758cc3dcSJack F Vogel /* Now copy bits into descriptor */ 161758cc3dcSJack F Vogel TXD->vlan_macip_lens = htole32(vlan_macip_lens); 162758cc3dcSJack F Vogel TXD->type_tucmd_mlhl = htole32(type_tucmd_mlhl); 163758cc3dcSJack F Vogel TXD->seqnum_seed = htole32(0); 164c19c7afeSEric Joyner TXD->mss_l4len_idx = htole32(mss_l4len_idx); 165758cc3dcSJack F Vogel 166c19c7afeSEric Joyner return (olinfo_status); 1678eb6488eSEric Joyner } /* ixgbe_tx_ctx_setup */ 168758cc3dcSJack F Vogel 1698eb6488eSEric Joyner /************************************************************************ 170c19c7afeSEric Joyner * ixgbe_isc_txd_encap 1718eb6488eSEric Joyner ************************************************************************/ 172758cc3dcSJack F Vogel static int 173c19c7afeSEric Joyner ixgbe_isc_txd_encap(void *arg, if_pkt_info_t pi) 174758cc3dcSJack F Vogel { 175b1d5caf3SKevin Bowling struct ixgbe_softc *sc = arg; 176c19c7afeSEric Joyner if_softc_ctx_t scctx = sc->shared; 177c19c7afeSEric Joyner struct ix_tx_queue *que = &sc->tx_queues[pi->ipi_qsidx]; 178c19c7afeSEric Joyner struct tx_ring *txr = &que->txr; 179c19c7afeSEric Joyner int nsegs = pi->ipi_nsegs; 180c19c7afeSEric Joyner bus_dma_segment_t *segs = pi->ipi_segs; 181c19c7afeSEric Joyner union ixgbe_adv_tx_desc *txd = NULL; 182758cc3dcSJack F Vogel struct ixgbe_adv_tx_context_desc *TXD; 183c19c7afeSEric Joyner int i, j, first, pidx_last; 18451e46835SKevin Bowling uint32_t olinfo_status, cmd, flags; 185c19c7afeSEric Joyner qidx_t ntxd; 186758cc3dcSJack F Vogel 187c19c7afeSEric Joyner cmd = (IXGBE_ADVTXD_DTYP_DATA | 188c19c7afeSEric Joyner IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT); 189758cc3dcSJack F Vogel 190c19c7afeSEric Joyner if (pi->ipi_mflags & M_VLANTAG) 191c19c7afeSEric Joyner cmd |= IXGBE_ADVTXD_DCMD_VLE; 192758cc3dcSJack F Vogel 193c19c7afeSEric Joyner i = first = pi->ipi_pidx; 194c19c7afeSEric Joyner flags = (pi->ipi_flags & IPI_TX_INTR) ? IXGBE_TXD_CMD_RS : 0; 195c19c7afeSEric Joyner ntxd = scctx->isc_ntxd[0]; 196758cc3dcSJack F Vogel 197c19c7afeSEric Joyner TXD = (struct ixgbe_adv_tx_context_desc *) &txr->tx_base[first]; 198c19c7afeSEric Joyner if ((pi->ipi_csum_flags & CSUM_OFFLOAD) || 199c19c7afeSEric Joyner (sc->feat_en & IXGBE_FEATURE_NEEDS_CTXD) || 200c19c7afeSEric Joyner pi->ipi_vtag) { 201c19c7afeSEric Joyner /********************************************* 202c19c7afeSEric Joyner * Set up the appropriate offload context 203c19c7afeSEric Joyner * this will consume the first descriptor 204c19c7afeSEric Joyner *********************************************/ 205c19c7afeSEric Joyner olinfo_status = ixgbe_tx_ctx_setup(TXD, pi); 206c19c7afeSEric Joyner if (pi->ipi_csum_flags & CSUM_TSO) { 207c19c7afeSEric Joyner cmd |= IXGBE_ADVTXD_DCMD_TSE; 208758cc3dcSJack F Vogel ++txr->tso_tx; 209c19c7afeSEric Joyner } 210c19c7afeSEric Joyner 211c19c7afeSEric Joyner if (++i == scctx->isc_ntxd[0]) 212c19c7afeSEric Joyner i = 0; 213c19c7afeSEric Joyner } else { 214c19c7afeSEric Joyner /* Indicate the whole packet as payload when not doing TSO */ 215c19c7afeSEric Joyner olinfo_status = pi->ipi_len << IXGBE_ADVTXD_PAYLEN_SHIFT; 216c19c7afeSEric Joyner } 217c19c7afeSEric Joyner 218c19c7afeSEric Joyner olinfo_status |= IXGBE_ADVTXD_CC; 21924a7d6d3SMatt Macy pidx_last = 0; 220c19c7afeSEric Joyner for (j = 0; j < nsegs; j++) { 221c19c7afeSEric Joyner bus_size_t seglen; 222c19c7afeSEric Joyner 223c19c7afeSEric Joyner txd = &txr->tx_base[i]; 224c19c7afeSEric Joyner seglen = segs[j].ds_len; 225c19c7afeSEric Joyner 226c19c7afeSEric Joyner txd->read.buffer_addr = htole64(segs[j].ds_addr); 227c19c7afeSEric Joyner txd->read.cmd_type_len = htole32(cmd | seglen); 228c19c7afeSEric Joyner txd->read.olinfo_status = htole32(olinfo_status); 229c19c7afeSEric Joyner 230c19c7afeSEric Joyner pidx_last = i; 231c19c7afeSEric Joyner if (++i == scctx->isc_ntxd[0]) { 232c19c7afeSEric Joyner i = 0; 233c19c7afeSEric Joyner } 234c19c7afeSEric Joyner } 235c19c7afeSEric Joyner 236c19c7afeSEric Joyner if (flags) { 237c19c7afeSEric Joyner txr->tx_rsq[txr->tx_rs_pidx] = pidx_last; 238c19c7afeSEric Joyner txr->tx_rs_pidx = (txr->tx_rs_pidx + 1) & (ntxd - 1); 239c19c7afeSEric Joyner } 240c19c7afeSEric Joyner txd->read.cmd_type_len |= htole32(IXGBE_TXD_CMD_EOP | flags); 241c19c7afeSEric Joyner 242c19c7afeSEric Joyner txr->bytes += pi->ipi_len; 243c19c7afeSEric Joyner pi->ipi_new_pidx = i; 244c19c7afeSEric Joyner 245c19c7afeSEric Joyner ++txr->total_packets; 2468eb6488eSEric Joyner 247758cc3dcSJack F Vogel return (0); 248c19c7afeSEric Joyner } /* ixgbe_isc_txd_encap */ 249758cc3dcSJack F Vogel 2508eb6488eSEric Joyner /************************************************************************ 251c19c7afeSEric Joyner * ixgbe_isc_txd_flush 2528eb6488eSEric Joyner ************************************************************************/ 253c19c7afeSEric Joyner static void 254c19c7afeSEric Joyner ixgbe_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx) 255758cc3dcSJack F Vogel { 256b1d5caf3SKevin Bowling struct ixgbe_softc *sc = arg; 257c19c7afeSEric Joyner struct ix_tx_queue *que = &sc->tx_queues[txqid]; 258c19c7afeSEric Joyner struct tx_ring *txr = &que->txr; 259758cc3dcSJack F Vogel 260c19c7afeSEric Joyner IXGBE_WRITE_REG(&sc->hw, txr->tail, pidx); 261c19c7afeSEric Joyner } /* ixgbe_isc_txd_flush */ 262758cc3dcSJack F Vogel 263c19c7afeSEric Joyner /************************************************************************ 264c19c7afeSEric Joyner * ixgbe_isc_txd_credits_update 265c19c7afeSEric Joyner ************************************************************************/ 266c19c7afeSEric Joyner static int 267c19c7afeSEric Joyner ixgbe_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear) 268c19c7afeSEric Joyner { 269b1d5caf3SKevin Bowling struct ixgbe_softc *sc = arg; 270c19c7afeSEric Joyner if_softc_ctx_t scctx = sc->shared; 271c19c7afeSEric Joyner struct ix_tx_queue *que = &sc->tx_queues[txqid]; 272c19c7afeSEric Joyner struct tx_ring *txr = &que->txr; 273c19c7afeSEric Joyner qidx_t processed = 0; 274c19c7afeSEric Joyner int updated; 275c19c7afeSEric Joyner qidx_t cur, prev, ntxd, rs_cidx; 276c19c7afeSEric Joyner int32_t delta; 277c19c7afeSEric Joyner uint8_t status; 278758cc3dcSJack F Vogel 279c19c7afeSEric Joyner rs_cidx = txr->tx_rs_cidx; 280c19c7afeSEric Joyner if (rs_cidx == txr->tx_rs_pidx) 281c19c7afeSEric Joyner return (0); 282758cc3dcSJack F Vogel 283c19c7afeSEric Joyner cur = txr->tx_rsq[rs_cidx]; 284c19c7afeSEric Joyner status = txr->tx_base[cur].wb.status; 285c19c7afeSEric Joyner updated = !!(status & IXGBE_TXD_STAT_DD); 286758cc3dcSJack F Vogel 287adf93b56SEric Joyner if (!updated) 288adf93b56SEric Joyner return (0); 289adf93b56SEric Joyner 290adf93b56SEric Joyner /* If clear is false just let caller know that there 291adf93b56SEric Joyner * are descriptors to reclaim */ 292adf93b56SEric Joyner if (!clear) 293adf93b56SEric Joyner return (1); 294c19c7afeSEric Joyner 295c19c7afeSEric Joyner prev = txr->tx_cidx_processed; 296c19c7afeSEric Joyner ntxd = scctx->isc_ntxd[0]; 297758cc3dcSJack F Vogel do { 298088a0b27SEric Joyner MPASS(prev != cur); 299c19c7afeSEric Joyner delta = (int32_t)cur - (int32_t)prev; 300c19c7afeSEric Joyner if (delta < 0) 301c19c7afeSEric Joyner delta += ntxd; 302088a0b27SEric Joyner MPASS(delta > 0); 303c19c7afeSEric Joyner 304c19c7afeSEric Joyner processed += delta; 305c19c7afeSEric Joyner prev = cur; 306c19c7afeSEric Joyner rs_cidx = (rs_cidx + 1) & (ntxd - 1); 307c19c7afeSEric Joyner if (rs_cidx == txr->tx_rs_pidx) 308758cc3dcSJack F Vogel break; 309758cc3dcSJack F Vogel 310c19c7afeSEric Joyner cur = txr->tx_rsq[rs_cidx]; 311c19c7afeSEric Joyner status = txr->tx_base[cur].wb.status; 312c19c7afeSEric Joyner } while ((status & IXGBE_TXD_STAT_DD)); 313758cc3dcSJack F Vogel 314c19c7afeSEric Joyner txr->tx_rs_cidx = rs_cidx; 315c19c7afeSEric Joyner txr->tx_cidx_processed = prev; 316758cc3dcSJack F Vogel 317c19c7afeSEric Joyner return (processed); 318c19c7afeSEric Joyner } /* ixgbe_isc_txd_credits_update */ 319758cc3dcSJack F Vogel 3208eb6488eSEric Joyner /************************************************************************ 321c19c7afeSEric Joyner * ixgbe_isc_rxd_refill 3228eb6488eSEric Joyner ************************************************************************/ 323758cc3dcSJack F Vogel static void 324c19c7afeSEric Joyner ixgbe_isc_rxd_refill(void *arg, if_rxd_update_t iru) 325758cc3dcSJack F Vogel { 326b1d5caf3SKevin Bowling struct ixgbe_softc *sc = arg; 327c19c7afeSEric Joyner struct ix_rx_queue *que = &sc->rx_queues[iru->iru_qsidx]; 328c19c7afeSEric Joyner struct rx_ring *rxr = &que->rxr; 329c19c7afeSEric Joyner uint64_t *paddrs; 330c19c7afeSEric Joyner int i; 331c19c7afeSEric Joyner uint32_t next_pidx, pidx; 332c19c7afeSEric Joyner uint16_t count; 333758cc3dcSJack F Vogel 334c19c7afeSEric Joyner paddrs = iru->iru_paddrs; 335c19c7afeSEric Joyner pidx = iru->iru_pidx; 336c19c7afeSEric Joyner count = iru->iru_count; 337c19c7afeSEric Joyner 338c19c7afeSEric Joyner for (i = 0, next_pidx = pidx; i < count; i++) { 339c19c7afeSEric Joyner rxr->rx_base[next_pidx].read.pkt_addr = htole64(paddrs[i]); 340c19c7afeSEric Joyner if (++next_pidx == sc->shared->isc_nrxd[0]) 341c19c7afeSEric Joyner next_pidx = 0; 342758cc3dcSJack F Vogel } 343c19c7afeSEric Joyner } /* ixgbe_isc_rxd_refill */ 344a9ca1c79SSean Bruno 3458eb6488eSEric Joyner /************************************************************************ 346c19c7afeSEric Joyner * ixgbe_isc_rxd_flush 3478eb6488eSEric Joyner ************************************************************************/ 348758cc3dcSJack F Vogel static void 349*c58d34ddSKevin Bowling ixgbe_isc_rxd_flush(void *arg, uint16_t qsidx, uint8_t flidx __unused, 350*c58d34ddSKevin Bowling qidx_t pidx) 351758cc3dcSJack F Vogel { 352b1d5caf3SKevin Bowling struct ixgbe_softc *sc = arg; 353c19c7afeSEric Joyner struct ix_rx_queue *que = &sc->rx_queues[qsidx]; 354c19c7afeSEric Joyner struct rx_ring *rxr = &que->rxr; 355758cc3dcSJack F Vogel 356c19c7afeSEric Joyner IXGBE_WRITE_REG(&sc->hw, rxr->tail, pidx); 357c19c7afeSEric Joyner } /* ixgbe_isc_rxd_flush */ 3588eb6488eSEric Joyner 3598eb6488eSEric Joyner /************************************************************************ 360c19c7afeSEric Joyner * ixgbe_isc_rxd_available 3618eb6488eSEric Joyner ************************************************************************/ 3628eb6488eSEric Joyner static int 363c19c7afeSEric Joyner ixgbe_isc_rxd_available(void *arg, uint16_t qsidx, qidx_t pidx, qidx_t budget) 364758cc3dcSJack F Vogel { 365b1d5caf3SKevin Bowling struct ixgbe_softc *sc = arg; 366c19c7afeSEric Joyner struct ix_rx_queue *que = &sc->rx_queues[qsidx]; 367c19c7afeSEric Joyner struct rx_ring *rxr = &que->rxr; 368c19c7afeSEric Joyner union ixgbe_adv_rx_desc *rxd; 36951e46835SKevin Bowling uint32_t staterr; 370c19c7afeSEric Joyner int cnt, i, nrxd; 371758cc3dcSJack F Vogel 372c19c7afeSEric Joyner nrxd = sc->shared->isc_nrxd[0]; 373adf93b56SEric Joyner for (cnt = 0, i = pidx; cnt < nrxd && cnt <= budget;) { 374c19c7afeSEric Joyner rxd = &rxr->rx_base[i]; 375c19c7afeSEric Joyner staterr = le32toh(rxd->wb.upper.status_error); 376758cc3dcSJack F Vogel 377758cc3dcSJack F Vogel if ((staterr & IXGBE_RXD_STAT_DD) == 0) 378758cc3dcSJack F Vogel break; 379c19c7afeSEric Joyner if (++i == nrxd) 380c19c7afeSEric Joyner i = 0; 381c19c7afeSEric Joyner if (staterr & IXGBE_RXD_STAT_EOP) 382c19c7afeSEric Joyner cnt++; 383c19c7afeSEric Joyner } 384c19c7afeSEric Joyner return (cnt); 385c19c7afeSEric Joyner } /* ixgbe_isc_rxd_available */ 386758cc3dcSJack F Vogel 387c19c7afeSEric Joyner /************************************************************************ 388c19c7afeSEric Joyner * ixgbe_isc_rxd_pkt_get 389c19c7afeSEric Joyner * 390c19c7afeSEric Joyner * Routine sends data which has been dma'ed into host memory 391c19c7afeSEric Joyner * to upper layer. Initialize ri structure. 392c19c7afeSEric Joyner * 393c19c7afeSEric Joyner * Returns 0 upon success, errno on failure 394c19c7afeSEric Joyner ************************************************************************/ 395c19c7afeSEric Joyner 396c19c7afeSEric Joyner static int 397c19c7afeSEric Joyner ixgbe_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri) 398c19c7afeSEric Joyner { 399b1d5caf3SKevin Bowling struct ixgbe_softc *sc = arg; 40052f45d8aSVincenzo Maffione if_softc_ctx_t scctx = sc->shared; 401b1d5caf3SKevin Bowling struct ix_rx_queue *que = &sc->rx_queues[ri->iri_qsidx]; 402c19c7afeSEric Joyner struct rx_ring *rxr = &que->rxr; 403c19c7afeSEric Joyner union ixgbe_adv_rx_desc *rxd; 404c19c7afeSEric Joyner 40551e46835SKevin Bowling uint16_t pkt_info, len, cidx, i; 40651e46835SKevin Bowling uint32_t ptype; 40751e46835SKevin Bowling uint32_t staterr = 0; 408c19c7afeSEric Joyner bool eop; 409c19c7afeSEric Joyner 410c19c7afeSEric Joyner i = 0; 411c19c7afeSEric Joyner cidx = ri->iri_cidx; 412c19c7afeSEric Joyner do { 413c19c7afeSEric Joyner rxd = &rxr->rx_base[cidx]; 414c19c7afeSEric Joyner staterr = le32toh(rxd->wb.upper.status_error); 415c19c7afeSEric Joyner pkt_info = le16toh(rxd->wb.lower.lo_dword.hs_rss.pkt_info); 416c19c7afeSEric Joyner 417c19c7afeSEric Joyner /* Error Checking then decrement count */ 418c19c7afeSEric Joyner MPASS ((staterr & IXGBE_RXD_STAT_DD) != 0); 419c19c7afeSEric Joyner 420c19c7afeSEric Joyner len = le16toh(rxd->wb.upper.length); 421c19c7afeSEric Joyner ptype = le32toh(rxd->wb.lower.lo_dword.data) & 422758cc3dcSJack F Vogel IXGBE_RXDADV_PKTTYPE_MASK; 423c19c7afeSEric Joyner 424c19c7afeSEric Joyner ri->iri_len += len; 425c19c7afeSEric Joyner rxr->bytes += len; 426c19c7afeSEric Joyner 427c19c7afeSEric Joyner rxd->wb.upper.status_error = 0; 428758cc3dcSJack F Vogel eop = ((staterr & IXGBE_RXD_STAT_EOP) != 0); 429de35521aSEric Joyner 430758cc3dcSJack F Vogel /* Make sure bad packets are discarded */ 431758cc3dcSJack F Vogel if (eop && (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) != 0) { 432b1d5caf3SKevin Bowling if (sc->feat_en & IXGBE_FEATURE_VF) 433*c58d34ddSKevin Bowling if_inc_counter(ri->iri_ifp, IFCOUNTER_IERRORS, 434*c58d34ddSKevin Bowling 1); 435c19c7afeSEric Joyner 436758cc3dcSJack F Vogel rxr->rx_discarded++; 437c19c7afeSEric Joyner return (EBADMSG); 438758cc3dcSJack F Vogel } 439c19c7afeSEric Joyner ri->iri_frags[i].irf_flid = 0; 440c19c7afeSEric Joyner ri->iri_frags[i].irf_idx = cidx; 441c19c7afeSEric Joyner ri->iri_frags[i].irf_len = len; 442b1d5caf3SKevin Bowling if (++cidx == sc->shared->isc_nrxd[0]) 443c19c7afeSEric Joyner cidx = 0; 444c19c7afeSEric Joyner i++; 445c19c7afeSEric Joyner /* even a 16K packet shouldn't consume more than 8 clusters */ 446c19c7afeSEric Joyner MPASS(i < 9); 447c19c7afeSEric Joyner } while (!eop); 448758cc3dcSJack F Vogel 449758cc3dcSJack F Vogel rxr->rx_packets++; 450c19c7afeSEric Joyner rxr->packets++; 451c19c7afeSEric Joyner rxr->rx_bytes += ri->iri_len; 452c19c7afeSEric Joyner 45352f45d8aSVincenzo Maffione if ((scctx->isc_capenable & IFCAP_RXCSUM) != 0) 454c19c7afeSEric Joyner ixgbe_rx_checksum(staterr, ri, ptype); 455df7b11faSHiren Panchasara 456c19c7afeSEric Joyner ri->iri_flowid = le32toh(rxd->wb.lower.hi_dword.rss); 457c19c7afeSEric Joyner ri->iri_rsstype = ixgbe_determine_rsstype(pkt_info); 458b1d5caf3SKevin Bowling if ((sc->feat_en & IXGBE_FEATURE_RSS) == 0) { 459236204eeSAndriy Gapon if (ri->iri_rsstype == M_HASHTYPE_OPAQUE) 460236204eeSAndriy Gapon ri->iri_rsstype = M_HASHTYPE_NONE; 461236204eeSAndriy Gapon else 462236204eeSAndriy Gapon ri->iri_rsstype = M_HASHTYPE_OPAQUE_HASH; 463236204eeSAndriy Gapon } 464f7926a6dSVincenzo Maffione if ((rxr->vtag_strip) && (staterr & IXGBE_RXD_STAT_VP)) { 465f7926a6dSVincenzo Maffione ri->iri_vtag = le16toh(rxd->wb.upper.vlan); 466c19c7afeSEric Joyner ri->iri_flags |= M_VLANTAG; 467f7926a6dSVincenzo Maffione } 468f7926a6dSVincenzo Maffione 469f7926a6dSVincenzo Maffione ri->iri_nfrags = i; 470c19c7afeSEric Joyner return (0); 471c19c7afeSEric Joyner } /* ixgbe_isc_rxd_pkt_get */ 472758cc3dcSJack F Vogel 4738eb6488eSEric Joyner /************************************************************************ 4748eb6488eSEric Joyner * ixgbe_rx_checksum 475758cc3dcSJack F Vogel * 476758cc3dcSJack F Vogel * Verify that the hardware indicated that the checksum is valid. 477758cc3dcSJack F Vogel * Inform the stack about the status of checksum so that stack 478758cc3dcSJack F Vogel * doesn't spend time verifying the checksum. 4798eb6488eSEric Joyner ************************************************************************/ 480758cc3dcSJack F Vogel static void 48151e46835SKevin Bowling ixgbe_rx_checksum(uint32_t staterr, if_rxd_info_t ri, uint32_t ptype) 482758cc3dcSJack F Vogel { 48351e46835SKevin Bowling uint16_t status = (uint16_t)staterr; 48451e46835SKevin Bowling uint8_t errors = (uint8_t)(staterr >> 24); 485758cc3dcSJack F Vogel 48651e46835SKevin Bowling /* If there is a layer 3 or 4 error we are done */ 487*c58d34ddSKevin Bowling if (__predict_false(errors & 488*c58d34ddSKevin Bowling (IXGBE_RXD_ERR_IPE | IXGBE_RXD_ERR_TCPE))) 48951e46835SKevin Bowling return; 490758cc3dcSJack F Vogel 491758cc3dcSJack F Vogel /* IP Checksum Good */ 49251e46835SKevin Bowling if (status & IXGBE_RXD_STAT_IPCS) 49351e46835SKevin Bowling ri->iri_csum_flags = (CSUM_IP_CHECKED | CSUM_IP_VALID); 49451e46835SKevin Bowling 49551e46835SKevin Bowling /* Valid L4E checksum */ 49651e46835SKevin Bowling if (__predict_true(status & IXGBE_RXD_STAT_L4CS)) { 49751e46835SKevin Bowling /* SCTP header present. */ 49851e46835SKevin Bowling if (__predict_false((ptype & IXGBE_RXDADV_PKTTYPE_ETQF) == 0 && 49951e46835SKevin Bowling (ptype & IXGBE_RXDADV_PKTTYPE_SCTP) != 0)) { 50051e46835SKevin Bowling ri->iri_csum_flags |= CSUM_SCTP_VALID; 50151e46835SKevin Bowling } else { 502*c58d34ddSKevin Bowling ri->iri_csum_flags |= 503*c58d34ddSKevin Bowling CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 504c19c7afeSEric Joyner ri->iri_csum_data = htons(0xffff); 505758cc3dcSJack F Vogel } 506758cc3dcSJack F Vogel } 5078eb6488eSEric Joyner } /* ixgbe_rx_checksum */ 508758cc3dcSJack F Vogel 5098eb6488eSEric Joyner /************************************************************************ 510c19c7afeSEric Joyner * ixgbe_determine_rsstype 511c19c7afeSEric Joyner * 512c19c7afeSEric Joyner * Parse the packet type to determine the appropriate hash 5138eb6488eSEric Joyner ************************************************************************/ 5148eb6488eSEric Joyner static int 51551e46835SKevin Bowling ixgbe_determine_rsstype(uint16_t pkt_info) 516758cc3dcSJack F Vogel { 517c19c7afeSEric Joyner switch (pkt_info & IXGBE_RXDADV_RSSTYPE_MASK) { 518c19c7afeSEric Joyner case IXGBE_RXDADV_RSSTYPE_IPV4_TCP: 519c19c7afeSEric Joyner return M_HASHTYPE_RSS_TCP_IPV4; 520c19c7afeSEric Joyner case IXGBE_RXDADV_RSSTYPE_IPV4: 521c19c7afeSEric Joyner return M_HASHTYPE_RSS_IPV4; 522c19c7afeSEric Joyner case IXGBE_RXDADV_RSSTYPE_IPV6_TCP: 523c19c7afeSEric Joyner return M_HASHTYPE_RSS_TCP_IPV6; 524c19c7afeSEric Joyner case IXGBE_RXDADV_RSSTYPE_IPV6_EX: 525c19c7afeSEric Joyner return M_HASHTYPE_RSS_IPV6_EX; 526c19c7afeSEric Joyner case IXGBE_RXDADV_RSSTYPE_IPV6: 527c19c7afeSEric Joyner return M_HASHTYPE_RSS_IPV6; 528c19c7afeSEric Joyner case IXGBE_RXDADV_RSSTYPE_IPV6_TCP_EX: 529c19c7afeSEric Joyner return M_HASHTYPE_RSS_TCP_IPV6_EX; 530c19c7afeSEric Joyner case IXGBE_RXDADV_RSSTYPE_IPV4_UDP: 531c19c7afeSEric Joyner return M_HASHTYPE_RSS_UDP_IPV4; 532c19c7afeSEric Joyner case IXGBE_RXDADV_RSSTYPE_IPV6_UDP: 533c19c7afeSEric Joyner return M_HASHTYPE_RSS_UDP_IPV6; 534c19c7afeSEric Joyner case IXGBE_RXDADV_RSSTYPE_IPV6_UDP_EX: 535c19c7afeSEric Joyner return M_HASHTYPE_RSS_UDP_IPV6_EX; 536c19c7afeSEric Joyner default: 537c19c7afeSEric Joyner return M_HASHTYPE_OPAQUE; 538758cc3dcSJack F Vogel } 539c19c7afeSEric Joyner } /* ixgbe_determine_rsstype */ 540