35#include "opt_kern_tls.h"
36#include "opt_ratelimit.h"
39#include <sys/eventhandler.h>
41#include <sys/socket.h>
42#include <sys/kernel.h>
44#include <sys/malloc.h>
48#include <sys/taskqueue.h>
50#include <sys/sglist.h>
51#include <sys/sysctl.h>
53#include <sys/socketvar.h>
54#include <sys/counter.h>
56#include <net/ethernet.h>
58#include <net/if_vlan_var.h>
59#include <net/if_vxlan.h>
60#include <netinet/in.h>
61#include <netinet/ip.h>
62#include <netinet/ip6.h>
63#include <netinet/tcp.h>
64#include <netinet/udp.h>
65#include <machine/in_cksum.h>
66#include <machine/md_var.h>
70#include <machine/bus.h>
71#include <sys/selinfo.h>
72#include <net/if_var.h>
73#include <net/netmap.h>
74#include <dev/netmap/netmap_kern.h>
84#ifdef T4_PKT_TIMESTAMP
85#define RX_COPY_THRESHOLD (MINCLSIZE - 8)
87#define RX_COPY_THRESHOLD MINCLSIZE
101 "payload DMA offset in rx buffer (bytes)");
111 "payload pad boundary (bytes)");
120 "status page size (bytes)");
130 "Congestion control for RX queues (0 = backpressure, 1 = drop");
140 0,
"Enable buffer packing");
150 "payload pack boundary (bytes)");
177static int tsclk = -1;
178SYSCTL_INT(_hw_cxgbe, OID_AUTO, tsclk, CTLFLAG_RDTUN, &tsclk, 0,
179 "Control TCP timestamp rewriting when using pacing");
181static int eo_max_backlog = 1024 * 1024;
182SYSCTL_INT(_hw_cxgbe, OID_AUTO, eo_max_backlog, CTLFLAG_RDTUN, &eo_max_backlog,
183 0,
"Maximum backlog of ratelimited data per flow");
192 "Interrupt holdoff timer scale on T6+");
199 "Number of LRO entries per RX queue");
206 "Enable presorting of LRO frames");
210 "Number of mbuf pullups performed");
214 "Number of mbuf defrags performed");
218 "tx coalescing allowed");
226SYSCTL_INT(_hw_cxgbe, OID_AUTO, tx_coalesce_pkts, CTLFLAG_RWTUN,
228 "# of consecutive packets (1 - 255) that will trigger tx coalescing");
230SYSCTL_INT(_hw_cxgbe, OID_AUTO, tx_coalesce_gap, CTLFLAG_RWTUN,
244 struct sysctl_ctx_list *,
struct sysctl_oid *);
246static void add_iq_sysctls(
struct sysctl_ctx_list *,
struct sysctl_oid *,
249 struct sysctl_oid *,
struct sge_fl *);
258static void add_rxq_sysctls(
struct sysctl_ctx_list *,
struct sysctl_oid *,
264static void add_ofld_rxq_sysctls(
struct sysctl_ctx_list *,
struct sysctl_oid *,
269#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
273 struct sysctl_oid *);
276 struct sysctl_oid *,
struct sge_eq *);
280 struct sysctl_ctx_list *,
struct sysctl_oid *);
282static void add_wrq_sysctls(
struct sysctl_ctx_list *,
struct sysctl_oid *,
287 struct sysctl_oid *,
struct sge_txq *);
288#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
291static void add_ofld_txq_sysctls(
struct sysctl_ctx_list *,
struct sysctl_oid *,
301static inline void get_pkt_gl(
struct mbuf *,
struct sglist *);
302static inline u_int
txpkt_len16(u_int,
const u_int);
337#if defined(INET) || defined(INET6)
338static inline u_int txpkt_eo_len16(u_int, u_int, u_int);
364 atomic_store_rel_ptr(loc, (uintptr_t)h);
383 atomic_store_rel_ptr(loc, (uintptr_t)h);
395 atomic_store_rel_ptr(loc, (uintptr_t)h);
471 const struct cpl_fw4_ack *cpl = (
const void *)(rss + 1);
525 MPASS(h == NULL || *loc == (uintptr_t)NULL);
526 atomic_store_rel_ptr(loc, (uintptr_t)h);
536 if (fl_pktshift < 0 || fl_pktshift > 7) {
537 printf(
"Invalid hw.cxgbe.fl_pktshift value (%d),"
545#if defined(__i386__) || defined(__amd64__)
546 len = cpu_clflush_line_size > 64 ? 128 : 64;
551 printf(
"Invalid hw.cxgbe.spg_len value (%d),"
552 " using %d instead.\n",
spg_len, len);
557 if (cong_drop < -1 || cong_drop > 1) {
558 printf(
"Invalid hw.cxgbe.cong_drop value (%d),"
563 if (
tscale != 1 && (tscale < 3 || tscale > 17)) {
564 printf(
"Invalid hw.cxgbe.tscale value (%d),"
565 " using 1 instead.\n",
tscale);
570#
if MJUMPAGESIZE != MCLBYTES
575 printf(
"Invalid hw.cxgbe.largest_rx_cluster value (%d),"
581#
if MJUMPAGESIZE != MCLBYTES
586 printf(
"Invalid hw.cxgbe.safest_rx_cluster value (%d),"
593 pullups = counter_u64_alloc(M_WAITOK);
594 defrags = counter_u64_alloc(M_WAITOK);
630 return (refs - rels);
634#define MAX_PACK_BOUNDARY 512
640 int pad, pack, pad_shift;
645 if (
fl_pad < (1 << pad_shift) ||
662 device_printf(sc->
dev,
"Invalid hw.cxgbe.fl_pad value"
663 " (%d), using %d instead.\n",
fl_pad, pad);
673 device_printf(sc->
dev,
"hw.cxgbe.fl_pack (%d) ignored,"
674 " using %d instead.\n",
fl_pack, pad);
680 if (fl_pack < 16 || fl_pack == 32 || fl_pack > 4096 ||
686 MPASS(powerof2(pack));
694 device_printf(sc->
dev,
"Invalid hw.cxgbe.fl_pack value"
695 " (%d), using %d instead.\n",
fl_pack, pack);
716 int intr_timer[
SGE_NTIMERS] = {1, 5, 10, 50, 100, 200};
720 static int sw_buf_sizes[] = {
722#if MJUMPAGESIZE != MCLBYTES
730 (
"%s: trying to change chip settings when not master.", __func__));
752 for (i = 0; i < nitems(sw_buf_sizes); i++) {
765 KASSERT(intr_timer[0] <= timer_max,
766 (
"%s: not a single usable timer (%d, %d)", __func__, intr_timer[0],
768 for (i = 1; i < nitems(intr_timer); i++) {
769 KASSERT(intr_timer[i] >= intr_timer[i - 1],
770 (
"%s: timers not listed in increasing order (%d)",
773 while (intr_timer[i] > timer_max) {
774 if (i == nitems(intr_timer) - 1) {
775 intr_timer[i] = timer_max;
778 intr_timer[i] += intr_timer[i - 1];
846 return (hwsz >= 64 && (hwsz & mask) == 0);
859 static int sw_buf_sizes[] = {
861#if MJUMPAGESIZE != MCLBYTES
872 rxb->
size1 = sw_buf_sizes[i];
898 if (n < sp->sge_fl_buffer_size[rxb->
hwidx2] -
931 device_printf(sc->
dev,
"invalid SGE_CONTROL(0x%x)\n",
r);
940 device_printf(sc->
dev,
"invalid SGE_HOST_PAGE_SIZE(0x%x)\n",
r);
950 device_printf(sc->
dev,
"invalid ULP_RX_TDDP_PSZ(0x%x)\n",
r);
958 device_printf(sc->
dev,
"invalid ULP_RX_CTL(0x%x)\n",
r);
968 device_printf(sc->
dev,
"invalid TP_PARA_REG5(0x%x)\n",
r);
981 rc = bus_dma_tag_create(bus_get_dma_tag(sc->
dev), 1, 0,
982 BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, BUS_SPACE_MAXSIZE,
983 BUS_SPACE_UNRESTRICTED, BUS_SPACE_MAXSIZE, BUS_DMA_ALLOCNOW, NULL,
986 device_printf(sc->
dev,
987 "failed to create main DMA tag: %d\n", rc);
995 struct sysctl_oid_list *children)
999 SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"buffer_sizes",
1000 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
1003 SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"fl_pktshift", CTLFLAG_RD,
1004 NULL, sp->
fl_pktshift,
"payload DMA offset in rx buffer (bytes)");
1006 SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"fl_pad", CTLFLAG_RD,
1007 NULL, sp->
pad_boundary,
"payload pad boundary (bytes)");
1009 SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"spg_len", CTLFLAG_RD,
1010 NULL, sp->
spg_len,
"status page size (bytes)");
1012 SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"cong_drop", CTLFLAG_RD,
1013 NULL,
cong_drop,
"congestion drop setting");
1015 SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"fl_pack", CTLFLAG_RD,
1023 bus_dma_tag_destroy(sc->
dmat);
1099 ETHER_VLAN_ENCAP_LEN +
ifp->if_mtu;
1101 maxp < sc->params.tp.max_rx_pdu)
1109 int rc = 0, i, intr_idx;
1115#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
1119 int saved_idx,
iqidx;
1124 struct ifnet *
ifp = vi->
ifp;
1131 saved_idx = intr_idx;
1132 if (
ifp->if_capabilities & IFCAP_NETMAP) {
1144 rc = alloc_nm_rxq(vi,
nm_rxq, intr_idx, i);
1152 rc = alloc_nm_txq(vi, nm_txq,
iqidx, i);
1159 intr_idx = saved_idx;
1175 if (
ifp->if_capabilities & IFCAP_NETMAP)
1176 intr_idx = saved_idx + max(vi->
nrxq, vi->
nnmrxq);
1181 rc = alloc_ofld_rxq(vi, ofld_rxq, i, intr_idx, maxp);
1197#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
1199 rc = alloc_ofld_txq(vi, ofld_txq, i);
1220#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
1232 if (vi->
ifp->if_capabilities & IFCAP_NETMAP) {
1234 free_nm_txq(vi, nm_txq);
1251#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
1253 free_ofld_txq(vi, ofld_txq);
1266 free_ofld_rxq(vi, ofld_rxq);
1354t4_nm_intr(
void *arg)
1368t4_vi_intr(
void *arg)
1370 struct irq *irq = arg;
1372 MPASS(irq->nm_rxq != NULL);
1373 t4_nm_intr(irq->nm_rxq);
1375 MPASS(irq->rxq != NULL);
1389 int ndescs = 0, limit;
1396 (
"%s: called for iq %p with fl (iq->flags 0x%x)", __func__,
iq,
1401 limit = budget ? budget :
iq->
qsize / 16;
1417 panic(
"%s: data for an iq (%p) with no freelist",
1424 (
"%s: bad opcode %02x.", __func__,
1436 if (__predict_true(lq >= 1024)) {
1446 (void) atomic_cmpset_int(&q->
state,
1449 STAILQ_INSERT_TAIL(&iql, q,
1457 (
"%s: illegal response type %d on iq %p",
1458 __func__, rsp_type,
iq));
1460 "%s: illegal response type %d on iq %p",
1461 device_get_nameunit(sc->
dev), rsp_type,
iq);
1471 if (__predict_false(++ndescs == limit)) {
1479 return (EINPROGRESS);
1484 if (STAILQ_EMPTY(&iql))
1491 q = STAILQ_FIRST(&iql);
1492 STAILQ_REMOVE_HEAD(&iql, link);
1496 STAILQ_INSERT_TAIL(&iql, q, link);
1505#if defined(INET) || defined(INET6)
1507sort_before_lro(
struct lro_ctrl *
lro)
1510 return (
lro->lro_mbuf_max != 0);
1514static inline uint64_t
1517 uint64_t n = be64toh(lf) & 0xfffffffffffffff;
1519 if (n > UINT64_MAX / 1000000)
1530 if (__predict_false((++
fl->
cidx & 7) == 0)) {
1550 int rsp_type, starved;
1552 uint16_t fl_hw_cidx;
1554#if defined(INET) || defined(INET6)
1555 const struct timeval lro_timeout = {0, sc->
lro_timeout};
1563#if defined(INET) || defined(INET6)
1565 MPASS(sort_before_lro(
lro));
1568 tcp_lro_flush_all(
lro);
1580 limit = budget ? budget :
iq->
qsize / 16;
1606 if (__predict_true(
eth_rx(sc,
rxq, d, lq) == 0))
1611 if (__predict_false(m0 == NULL))
1618 (
"%s: bad opcode %02x.", __func__, d->
rss.
opcode));
1631 if (__predict_false(lq < 1024)) {
1632 panic(
"%s: indirect interrupt on iq_fl %p "
1633 "with qid %u", __func__,
iq, lq);
1640 KASSERT(0, (
"%s: illegal response type %d on iq %p",
1641 __func__, rsp_type,
iq));
1642 log(LOG_ERR,
"%s: illegal response type %d on iq %p",
1643 device_get_nameunit(sc->
dev), rsp_type,
iq);
1653 if (__predict_false(++ndescs == limit)) {
1658#if defined(INET) || defined(INET6)
1660 !sort_before_lro(
lro) &&
1662 tcp_lro_flush_inactive(
lro, &lro_timeout);
1666 return (EINPROGRESS);
1671#if defined(INET) || defined(INET6)
1673 if (ndescs > 0 &&
lro->lro_mbuf_count > 8) {
1674 MPASS(sort_before_lro(
lro));
1679 tcp_lro_flush_all(
lro);
1690 if (__predict_false(starved != 0))
1700 return ((
void *)(sd->
cl + sd->
moff));
1708 uma_zfree(clm->
zone, clm->
cl);
1734 len = min(remaining, blen);
1737 l = fr_offset + len;
1745 len = min(remaining, blen);
1749 if (fr_offset == 0) {
1750 m = m_gethdr(M_NOWAIT, MT_DATA);
1751 if (__predict_false(m == NULL))
1753 m->m_pkthdr.len = remaining;
1755 m = m_get(M_NOWAIT, MT_DATA);
1756 if (__predict_false(m == NULL))
1760 kmsan_mark(payload, len, KMSAN_STATE_INITED);
1764 bcopy(payload, mtod(m, caddr_t), len);
1773 if (sd->
nmbuf++ == 0) {
1787 m_cljset(m, sd->
cl, rxb->
type);
1799 struct mbuf *m0, *m, **pnext;
1803 M_ASSERTPKTHDR(
fl->
m0);
1804 MPASS(
fl->
m0->m_pkthdr.len == plen);
1822 remaining = plen - m0->m_len;
1823 pnext = &m0->m_next;
1824 while (remaining > 0) {
1828 if (__predict_false(m == NULL)) {
1837 remaining -= m->m_len;
1857 len = min(remaining, blen);
1859 l = fr_offset + len;
1870 len = min(remaining, blen);
1879 int remaining, fr_offset, len;
1883 while (remaining > 0) {
1902 return (min(plen, len));
1914#if defined(INET) || defined(INET6)
1917 uint16_t err_vec, tnl_type, tnlhdr_len;
1918 static const int sw_hashtype[4][2] = {
1919 {M_HASHTYPE_NONE, M_HASHTYPE_NONE},
1920 {M_HASHTYPE_RSS_IPV4, M_HASHTYPE_RSS_IPV6},
1921 {M_HASHTYPE_RSS_TCP_IPV4, M_HASHTYPE_RSS_TCP_IPV6},
1922 {M_HASHTYPE_RSS_UDP_IPV4, M_HASHTYPE_RSS_UDP_IPV6},
1924 static const int sw_csum_flags[2][2] = {
1928 CSUM_L3_CALC | CSUM_L3_VALID |
1929 CSUM_L4_CALC | CSUM_L4_VALID |
1930 CSUM_INNER_L3_CALC | CSUM_INNER_L3_VALID |
1931 CSUM_INNER_L4_CALC | CSUM_INNER_L4_VALID,
1935 CSUM_L3_CALC | CSUM_L3_VALID |
1936 CSUM_L4_CALC | CSUM_L4_VALID |
1937 CSUM_INNER_L4_CALC | CSUM_INNER_L4_VALID,
1942 CSUM_L4_CALC | CSUM_L4_VALID |
1943 CSUM_INNER_L3_CALC | CSUM_INNER_L3_VALID |
1944 CSUM_INNER_L4_CALC | CSUM_INNER_L4_VALID,
1948 CSUM_L4_CALC | CSUM_L4_VALID |
1949 CSUM_INNER_L4_CALC | CSUM_INNER_L4_VALID,
1954 if (vi->
pfil != NULL && PFIL_HOOKED_IN(vi->
pfil) &&
1963 CURVNET_SET_QUIET(
ifp->if_vnet);
1964 rc = pfil_run_hooks(vi->
pfil, frame,
ifp,
1965 slen | PFIL_MEMPTR | PFIL_IN, NULL);
1967 if (rc == PFIL_DROPPED || rc == PFIL_CONSUMED) {
1971 if (rc == PFIL_REALLOCED) {
1973 m0 = pfil_mem2mbuf(frame);
1979 if (__predict_false(m0 == NULL))
1987 m0->m_pkthdr.rcvif =
ifp;
1991 cpl = (
const void *)(&d->
rss + 1);
1993 const uint16_t ev = be16toh(cpl->
err_vec);
1999 err_vec = be16toh(cpl->
err_vec);
2010 m0->m_pkthdr.csum_data = be16toh(cpl->
csum);
2011 if (tnl_type == 0) {
2012 if (!ipv6 &&
ifp->if_capenable & IFCAP_RXCSUM) {
2013 m0->m_pkthdr.csum_flags = CSUM_L3_CALC |
2014 CSUM_L3_VALID | CSUM_L4_CALC |
2016 }
else if (ipv6 &&
ifp->if_capenable & IFCAP_RXCSUM_IPV6) {
2017 m0->m_pkthdr.csum_flags = CSUM_L4_CALC |
2024 M_HASHTYPE_SETINNER(m0);
2025 if (__predict_false(cpl->
ip_frag)) {
2039 m0->m_pkthdr.csum_data = 0xffff;
2041 m0->m_pkthdr.csum_flags = CSUM_L4_CALC |
2044 m0->m_pkthdr.csum_flags = CSUM_L3_CALC |
2045 CSUM_L3_VALID | CSUM_L4_CALC |
2051 MPASS(m0->m_pkthdr.csum_data == 0xffff);
2053 outer_ipv6 = tnlhdr_len >=
2054 sizeof(
struct ether_header) +
2055 sizeof(struct ip6_hdr);
2056 m0->m_pkthdr.csum_flags =
2057 sw_csum_flags[outer_ipv6][ipv6];
2064 m0->m_pkthdr.ether_vtag = be16toh(cpl->
vlan);
2065 m0->m_flags |= M_VLANTAG;
2077 m0->m_pkthdr.rcv_tstmp =
2080 m0->m_flags |= M_TSTMP;
2085 m0->m_pkthdr.numa_domain =
ifp->if_numa_domain;
2087#if defined(INET) || defined(INET6)
2089 (M_HASHTYPE_GET(m0) == M_HASHTYPE_RSS_TCP_IPV4 ||
2090 M_HASHTYPE_GET(m0) == M_HASHTYPE_RSS_TCP_IPV6)) {
2091 if (sort_before_lro(
lro)) {
2092 tcp_lro_queue_mbuf(
lro, m0);
2095 if (tcp_lro_rx(
lro, m0, 0) == 0)
2114 if (TAILQ_EMPTY(&
wrq->incomplete_wrs) && !STAILQ_EMPTY(&
wrq->wr_list))
2123 u_int available, dbdiff;
2129 MPASS(TAILQ_EMPTY(&
wrq->incomplete_wrs));
2130 wr = STAILQ_FIRST(&
wrq->wr_list);
2138 available =
eq->
sidx - 1;
2150 bcopy(&wr->wr[0], dst, wr->
wr_len);
2155 bcopy(&wr->wr[0], dst, first_portion);
2156 if (wr->
wr_len > first_portion) {
2157 bcopy(&wr->wr[first_portion], &
eq->
desc[0],
2158 wr->
wr_len - first_portion);
2164 if (available < eq->
sidx / 4 &&
2165 atomic_cmpset_int(&
eq->
equiq, 0, 1)) {
2181 STAILQ_REMOVE_HEAD(&
wrq->wr_list, link);
2187 }
while ((wr = STAILQ_FIRST(&
wrq->wr_list)) != NULL);
2206 MPASS((wr->
wr_len & 0x7) == 0);
2208 STAILQ_INSERT_TAIL(&
wrq->wr_list, wr, link);
2212 if (!TAILQ_EMPTY(&
wrq->incomplete_wrs))
2260 KASSERT(m->m_pkthdr.inner_l5hlen > 0,
2261 (
"%s: mbuf %p missing information on # of segments.", __func__, m));
2263 return (m->m_pkthdr.inner_l5hlen);
2271 m->m_pkthdr.inner_l5hlen = nsegs;
2279 return (m->m_pkthdr.PH_loc.eight[4]);
2287 m->m_pkthdr.PH_loc.eight[4] =
flags;
2296 n = m->m_pkthdr.PH_loc.eight[0];
2310 m->m_pkthdr.PH_loc.eight[0] = len16;
2315mbuf_eo_nsegs(
struct mbuf *m)
2319 return (m->m_pkthdr.PH_loc.eight[1]);
2322#if defined(INET) || defined(INET6)
2324set_mbuf_eo_nsegs(
struct mbuf *m, uint8_t nsegs)
2328 m->m_pkthdr.PH_loc.eight[1] = nsegs;
2333mbuf_eo_len16(
struct mbuf *m)
2338 n = m->m_pkthdr.PH_loc.eight[2];
2344#if defined(INET) || defined(INET6)
2346set_mbuf_eo_len16(
struct mbuf *m, uint8_t len16)
2350 m->m_pkthdr.PH_loc.eight[2] = len16;
2355mbuf_eo_tsclk_tsoff(
struct mbuf *m)
2359 return (m->m_pkthdr.PH_loc.eight[3]);
2362#if defined(INET) || defined(INET6)
2364set_mbuf_eo_tsclk_tsoff(
struct mbuf *m, uint8_t tsclk_tsoff)
2368 m->m_pkthdr.PH_loc.eight[3] = tsclk_tsoff;
2373needs_eo(
struct m_snd_tag *mst)
2376 return (mst != NULL && mst->sw->type == IF_SND_TAG_TYPE_RATE_LIMIT);
2391 m = m_gethdr(how, MT_DATA);
2392 else if (len <= MCLBYTES)
2393 m = m_getcl(how, MT_DATA, M_PKTHDR);
2398 m->m_pkthdr.len = len;
2408 const uint32_t csum_flags = CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP |
2409 CSUM_IP_TSO | CSUM_INNER_IP | CSUM_INNER_IP_UDP |
2410 CSUM_INNER_IP_TCP | CSUM_INNER_IP_TSO | CSUM_IP6_UDP |
2411 CSUM_IP6_TCP | CSUM_IP6_TSO | CSUM_INNER_IP6_UDP |
2412 CSUM_INNER_IP6_TCP | CSUM_INNER_IP6_TSO;
2416 return (m->m_pkthdr.csum_flags & csum_flags);
2422 const uint32_t csum_flags = CSUM_IP_TSO | CSUM_IP6_TSO |
2423 CSUM_INNER_IP_TSO | CSUM_INNER_IP6_TSO;
2427 return (m->m_pkthdr.csum_flags & csum_flags);
2436 return (m->m_pkthdr.csum_flags & CSUM_ENCAP_VXLAN);
2442 const uint32_t csum_flags = CSUM_ENCAP_VXLAN | CSUM_INNER_IP_TSO |
2447 return ((m->m_pkthdr.csum_flags & csum_flags) != 0 &&
2448 (m->m_pkthdr.csum_flags & csum_flags) != CSUM_ENCAP_VXLAN);
2451#if defined(INET) || defined(INET6)
2453needs_inner_tcp_csum(
struct mbuf *m)
2455 const uint32_t csum_flags = CSUM_INNER_IP_TSO | CSUM_INNER_IP6_TSO;
2459 return (m->m_pkthdr.csum_flags & csum_flags);
2466 const uint32_t csum_flags = CSUM_IP | CSUM_IP_TSO | CSUM_INNER_IP |
2471 return (m->m_pkthdr.csum_flags & csum_flags);
2477 const uint32_t csum_flags = CSUM_IP_TCP | CSUM_IP_TSO | CSUM_IP6_TCP |
2482 return (m->m_pkthdr.csum_flags & csum_flags);
2487needs_outer_l4_csum(
struct mbuf *m)
2489 const uint32_t csum_flags = CSUM_IP_UDP | CSUM_IP_TCP | CSUM_IP_TSO |
2490 CSUM_IP6_UDP | CSUM_IP6_TCP | CSUM_IP6_TSO;
2494 return (m->m_pkthdr.csum_flags & csum_flags);
2498needs_outer_udp_csum(
struct mbuf *m)
2500 const uint32_t csum_flags = CSUM_IP_UDP | CSUM_IP6_UDP;
2504 return (m->m_pkthdr.csum_flags & csum_flags);
2514 return (m->m_flags & M_VLANTAG);
2517#if defined(INET) || defined(INET6)
2519m_advance(
struct mbuf **pm,
int *poffset,
int len)
2521 struct mbuf *m = *pm;
2522 int offset = *poffset;
2528 if (offset + len < m->m_len) {
2530 p = mtod(m, uintptr_t) + offset;
2533 len -= m->m_len - offset;
2548 int i, len, off, pglen, pgoff, seglen, segoff;
2552 off = mtod(m, vm_offset_t);
2557 if (m->m_epg_hdrlen != 0) {
2558 if (off >= m->m_epg_hdrlen) {
2559 off -= m->m_epg_hdrlen;
2561 seglen = m->m_epg_hdrlen - off;
2563 seglen = min(seglen, len);
2566 paddr = pmap_kextract(
2567 (vm_offset_t)&m->m_epg_hdr[segoff]);
2568 if (*nextaddr != paddr)
2570 *nextaddr = paddr + seglen;
2573 pgoff = m->m_epg_1st_off;
2574 for (i = 0; i < m->m_epg_npgs && len > 0; i++) {
2575 pglen = m_epg_pagelen(m, i, pgoff);
2581 seglen = pglen - off;
2582 segoff = pgoff + off;
2584 seglen = min(seglen, len);
2586 paddr = m->m_epg_pa[i] + segoff;
2587 if (*nextaddr != paddr)
2589 *nextaddr = paddr + seglen;
2593 seglen = min(len, m->m_epg_trllen - off);
2595 paddr = pmap_kextract((vm_offset_t)&m->m_epg_trail[off]);
2596 if (*nextaddr != paddr)
2598 *nextaddr = paddr + seglen;
2613 vm_paddr_t nextaddr, paddr;
2618 MPASS(m->m_pkthdr.len > 0);
2619 MPASS(m->m_pkthdr.len >= skip);
2623 for (; m; m = m->m_next) {
2625 if (__predict_false(len == 0))
2631 if ((m->m_flags & M_EXTPG) != 0) {
2637 va = mtod(m, vm_offset_t) + skip;
2640 paddr = pmap_kextract(va);
2641 nsegs += sglist_count((
void *)(uintptr_t)va, len);
2642 if (paddr == nextaddr)
2644 nextaddr = pmap_kextract(va + len - 1) + 1;
2684 struct mbuf *m0 = *mp, *m;
2685 int rc, nsegs, defragged = 0;
2686 struct ether_header *eh;
2690#if defined(INET) || defined(INET6)
2694#if defined(KERN_TLS) || defined(RATELIMIT)
2695 struct m_snd_tag *mst;
2702 if (__predict_false(m0->m_pkthdr.len < ETHER_HDR_LEN)) {
2715 MPASS(m0->m_pkthdr.len > 0);
2717#if defined(KERN_TLS) || defined(RATELIMIT)
2718 if (m0->m_pkthdr.csum_flags & CSUM_SND_TAG)
2719 mst = m0->m_pkthdr.snd_tag;
2724 if (mst != NULL && mst->sw->type == IF_SND_TAG_TYPE_TLS) {
2738 if (defragged++ > 0) {
2743 if ((m = m_defrag(m0, M_NOWAIT)) == NULL) {
2751 if (__predict_false(nsegs > 2 && m0->m_pkthdr.len <= MHLEN &&
2754 m0 = m_pullup(m0, m0->m_pkthdr.len);
2773 if (__predict_false(needs_eo(mst) && !needs_outer_l4_csum(m0))) {
2774 m_snd_tag_rele(m0->m_pkthdr.snd_tag);
2775 m0->m_pkthdr.snd_tag = NULL;
2776 m0->m_pkthdr.csum_flags &= ~CSUM_SND_TAG;
2789 eh = mtod(m,
struct ether_header *);
2790 eh_type = ntohs(eh->ether_type);
2791 if (eh_type == ETHERTYPE_VLAN) {
2792 struct ether_vlan_header *evh = (
void *)eh;
2794 eh_type = ntohs(evh->evl_proto);
2795 m0->m_pkthdr.l2hlen =
sizeof(*evh);
2797 m0->m_pkthdr.l2hlen =
sizeof(*eh);
2799#if defined(INET) || defined(INET6)
2802 l3hdr = m_advance(&m, &offset, m0->m_pkthdr.l2hlen);
2804 m_advance(&m, &offset, m0->m_pkthdr.l2hlen);
2810 case ETHERTYPE_IPV6:
2811 m0->m_pkthdr.l3hlen =
sizeof(
struct ip6_hdr);
2817 struct ip *ip = l3hdr;
2823 const uint16_t ipl = ip->ip_len;
2826 ip->ip_sum = ~in_cksum_hdr(ip);
2829 ip->ip_sum = in_cksum_hdr(ip);
2831 m0->m_pkthdr.l3hlen = ip->ip_hl << 2;
2837 log(LOG_ERR,
"%s: ethertype 0x%04x unknown. "
2838 "if_cxgbe must be compiled with the same "
2839 "INET/INET6 options as the kernel.\n", __func__,
2846#if defined(INET) || defined(INET6)
2848 m0->m_pkthdr.l4hlen =
sizeof(
struct udphdr);
2849 m0->m_pkthdr.l5hlen =
sizeof(
struct vxlan_header);
2852 eh = m_advance(&m, &offset, m0->m_pkthdr.l3hlen +
2853 sizeof(
struct udphdr) +
sizeof(
struct vxlan_header));
2854 eh_type = ntohs(eh->ether_type);
2855 if (eh_type == ETHERTYPE_VLAN) {
2856 struct ether_vlan_header *evh = (
void *)eh;
2858 eh_type = ntohs(evh->evl_proto);
2859 m0->m_pkthdr.inner_l2hlen =
sizeof(*evh);
2861 m0->m_pkthdr.inner_l2hlen =
sizeof(*eh);
2863 l3hdr = m_advance(&m, &offset, m0->m_pkthdr.inner_l2hlen);
2865 m_advance(&m, &offset, m0->m_pkthdr.inner_l2hlen);
2870 case ETHERTYPE_IPV6:
2871 m0->m_pkthdr.inner_l3hlen =
sizeof(
struct ip6_hdr);
2877 struct ip *ip = l3hdr;
2879 m0->m_pkthdr.inner_l3hlen = ip->ip_hl << 2;
2885 log(LOG_ERR,
"%s: VXLAN hw offload requested"
2886 "with unknown ethertype 0x%04x. if_cxgbe "
2887 "must be compiled with the same INET/INET6 "
2888 "options as the kernel.\n", __func__,
2894 if (needs_inner_tcp_csum(m0)) {
2895 tcp = m_advance(&m, &offset, m0->m_pkthdr.inner_l3hlen);
2896 m0->m_pkthdr.inner_l4hlen = tcp->th_off * 4;
2898 MPASS((m0->m_pkthdr.csum_flags & CSUM_SND_TAG) == 0);
2899 m0->m_pkthdr.csum_flags &= CSUM_INNER_IP6_UDP |
2900 CSUM_INNER_IP6_TCP | CSUM_INNER_IP6_TSO | CSUM_INNER_IP |
2901 CSUM_INNER_IP_UDP | CSUM_INNER_IP_TCP | CSUM_INNER_IP_TSO |
2906 tcp = m_advance(&m, &offset, m0->m_pkthdr.l3hlen);
2907 m0->m_pkthdr.l4hlen = tcp->th_off * 4;
2909 if (tsclk >= 0 && *(uint32_t *)(tcp + 1) == ntohl(0x0101080a)) {
2910 set_mbuf_eo_tsclk_tsoff(m0,
2914 set_mbuf_eo_tsclk_tsoff(m0, 0);
2915 }
else if (needs_outer_udp_csum(m0)) {
2916 m0->m_pkthdr.l4hlen =
sizeof(
struct udphdr);
2920 if (needs_eo(mst)) {
2924 immhdrs = m0->m_pkthdr.l2hlen + m0->m_pkthdr.l3hlen +
2925 m0->m_pkthdr.l4hlen;
2929 set_mbuf_eo_nsegs(m0, nsegs);
2930 set_mbuf_eo_len16(m0,
2931 txpkt_eo_len16(nsegs, immhdrs,
needs_tso(m0)));
2944 int ndesc, available;
2954 if (TAILQ_EMPTY(&
wrq->incomplete_wrs) && !STAILQ_EMPTY(&
wrq->wr_list))
2957 if (!STAILQ_EMPTY(&
wrq->wr_list)) {
2961 if (__predict_false(wr == NULL))
2964 cookie->
ndesc = ndesc;
2970 available =
eq->
sidx - 1;
2973 if (available < ndesc)
2977 cookie->
ndesc = ndesc;
2978 TAILQ_INSERT_TAIL(&
wrq->incomplete_wrs, cookie, link);
2982 if (__predict_false(cookie->
pidx + ndesc >
eq->
sidx)) {
3001 if (cookie->
pidx == -1) {
3002 struct wrqe *wr = __containerof(w,
struct wrqe, wr);
3008 if (__predict_false(w == &
wrq->
ss[0])) {
3019 ndesc = cookie->
ndesc;
3021 MPASS(
pidx >= 0 && pidx < eq->
sidx);
3022 prev = TAILQ_PREV(cookie, wrq_incomplete_wrs, link);
3023 next = TAILQ_NEXT(cookie, link);
3026 if (next == NULL || ndesc >= 16) {
3037 if (available < eq->
sidx / 4 &&
3038 atomic_cmpset_int(&
eq->
equiq, 0, 1)) {
3052 next->
ndesc += ndesc;
3056 prev->
ndesc += ndesc;
3058 TAILQ_REMOVE(&
wrq->incomplete_wrs, cookie, link);
3060 if (TAILQ_EMPTY(&
wrq->incomplete_wrs) && !STAILQ_EMPTY(&
wrq->wr_list))
3064 if (TAILQ_EMPTY(&
wrq->incomplete_wrs)) {
3121 atomic_cmpset_int(&
eq->
equiq, 0, 1)) {
3130#if defined(__i386__) || defined(__amd64__)
3131extern uint64_t tsc_freq;
3137 const uint64_t cycles = get_cyclecount();
3139#if defined(__i386__) || defined(__amd64__)
3142 const uint64_t itg = 0;
3147 return (cycles -
last_tx < itg);
3158 struct ifnet *
ifp = txq->
ifp;
3163 u_int total, remaining;
3164 u_int n, avail, dbdiff;
3167 bool snd, recent_tx;
3175 for (i = 0; i <
txp->
npkt; i++)
3176 m_freem(
txp->
mb[i]);
3179 m0 =
r->items[
cidx];
3181 if (++
cidx ==
r->size)
3185 *coalescing =
false;
3196 if (remaining == 0) {
3203 MPASS(remaining > 0);
3204 while (remaining > 0) {
3205 m0 =
r->items[
cidx];
3207 MPASS(m0->m_nextpkt == NULL);
3213 goto skip_coalescing;
3216 else if (recent_tx) {
3221 if (
txp->
npkt > 0 || remaining > 1 ||
3223 atomic_load_int(&txq->
eq.
equiq) != 0) {
3234 for (i = 0; i <
txp->
npkt; i++)
3274 MPASS(rc != 0 && rc != EAGAIN);
3278 if (__predict_false(avail < n)) {
3289 ETHER_BPF_MTAP(
ifp, m0);
3294 ETHER_BPF_MTAP(
ifp, m0);
3300 MPASS(n >= 1 && n <= avail);
3318 if (__predict_false(++
cidx ==
r->size))
3327 atomic_load_int(&txq->
eq.
equiq) == 0) {
3335 for (i = 0; i <
txp->
npkt; i++)
3368 int qsize,
int intr_idx,
int cong)
3372 (
"%s: bad tmr_idx %d", __func__, tmr_idx));
3374 (
"%s: bad pktc_idx %d", __func__, pktc_idx));
3375 KASSERT(intr_idx >= -1 && intr_idx < sc->intr_count,
3376 (
"%s: bad intr_idx %d", __func__, intr_idx));
3383 if (pktc_idx >= 0) {
3387 iq->
qsize = roundup2(qsize, 16);
3421 uint8_t tx_chan,
struct sge_iq *
iq,
char *name)
3424 (
"%s: bad qtype %d", __func__, eqtype));
3436 bus_dmamap_t *map, bus_addr_t *pa,
void **va)
3440 rc = bus_dma_tag_create(sc->
dmat, 512, 0, BUS_SPACE_MAXADDR,
3441 BUS_SPACE_MAXADDR, NULL, NULL, len, 1, len, 0, NULL, NULL,
tag);
3443 CH_ERR(sc,
"cannot allocate DMA tag: %d\n", rc);
3447 rc = bus_dmamem_alloc(*
tag, va,
3448 BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, map);
3450 CH_ERR(sc,
"cannot allocate DMA memory: %d\n", rc);
3456 CH_ERR(sc,
"cannot load DMA map: %d\n", rc);
3468 bus_addr_t pa,
void *va)
3471 bus_dmamap_unload(
tag, map);
3473 bus_dmamem_free(
tag, va, map);
3475 bus_dma_tag_destroy(
tag);
3488 struct sysctl_ctx_list *ctx,
struct sysctl_oid *oid)
3514 M_CXGBE, M_ZERO | M_WAITOK);
3540 bzero(
fl,
sizeof(*
fl));
3543 bzero(
iq,
sizeof(*
iq));
3563 bzero(&c,
sizeof(c));
3581 (
"%s: invalid direct intr_idx %d", __func__,
iq->
intr_idx));
3624 CH_ERR(sc,
"failed to create hw ingress queue: %d\n", rc);
3635 panic (
"%s: iq->cntxt_id (%d) more than the max (%d)", __func__,
3644 for (i = 0; i <
fl->
sidx * 8; i++)
3654 panic(
"%s: fl->cntxt_id (%d) more than the max (%d)",
3662 uint32_t mask = (1 << s_qpp) - 1;
3663 volatile uint8_t *
udb;
3666 udb += (qid >> s_qpp) << PAGE_SHIFT;
3683 uint32_t param, val;
3692 for (i = 0; i < 4; i++) {
3694 val |= 1 << (i << 2);
3701 CH_ERR(sc,
"failed to set congestion manager context "
3702 "for ingress queue %d: %d\n",
iq->
cntxt_id, rc);
3725 CH_ERR(sc,
"failed to free iq %p: %d\n",
iq, rc);
3728 iq->
flags &= ~IQ_HW_ALLOCATED;
3737 struct sysctl_oid_list *children;
3739 if (ctx == NULL || oid == NULL)
3742 children = SYSCTL_CHILDREN(oid);
3743 SYSCTL_ADD_UAUTO(ctx, children, OID_AUTO,
"ba", CTLFLAG_RD, &
iq->
ba,
3744 "bus address of descriptor ring");
3745 SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"dmalen", CTLFLAG_RD, NULL,
3747 SYSCTL_ADD_U16(ctx, children, OID_AUTO,
"abs_id", CTLFLAG_RD,
3748 &
iq->
abs_id, 0,
"absolute id of the queue");
3749 SYSCTL_ADD_U16(ctx, children, OID_AUTO,
"cntxt_id", CTLFLAG_RD,
3750 &
iq->
cntxt_id, 0,
"SGE context id of the queue");
3751 SYSCTL_ADD_U16(ctx, children, OID_AUTO,
"cidx", CTLFLAG_RD, &
iq->
cidx,
3752 0,
"consumer index");
3757 struct sysctl_oid *oid,
struct sge_fl *
fl)
3759 struct sysctl_oid_list *children;
3761 if (ctx == NULL || oid == NULL)
3764 children = SYSCTL_CHILDREN(oid);
3765 oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO,
"fl",
3766 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
"freelist");
3767 children = SYSCTL_CHILDREN(oid);
3769 SYSCTL_ADD_UAUTO(ctx, children, OID_AUTO,
"ba", CTLFLAG_RD,
3770 &
fl->
ba,
"bus address of descriptor ring");
3771 SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"dmalen", CTLFLAG_RD, NULL,
3773 "desc ring size in bytes");
3774 SYSCTL_ADD_U16(ctx, children, OID_AUTO,
"cntxt_id", CTLFLAG_RD,
3775 &
fl->
cntxt_id, 0,
"SGE context id of the freelist");
3776 SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
"padding", CTLFLAG_RD, NULL,
3777 fl_pad ? 1 : 0,
"padding enabled");
3778 SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
"packing", CTLFLAG_RD, NULL,
3780 SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
"cidx", CTLFLAG_RD, &
fl->
cidx,
3781 0,
"consumer index");
3783 SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
"rx_offset",
3784 CTLFLAG_RD, &
fl->
rx_offset, 0,
"packing rx offset");
3786 SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
"pidx", CTLFLAG_RD, &
fl->
pidx,
3787 0,
"producer index");
3816 CH_ERR(sc,
"failed to allocate fwq: %d\n", rc);
3827 CH_ERR(sc,
"failed to create hw fwq: %d\n", rc);
3865 struct sysctl_oid *oid;
3868 MPASS(idx < sc->params.nports);
3873 snprintf(name,
sizeof(name),
"%d", idx);
3874 oid = SYSCTL_ADD_NODE(&sc->
ctx, SYSCTL_CHILDREN(sc->
ctrlq_oid),
3875 OID_AUTO, name, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
3878 snprintf(name,
sizeof(name),
"%s ctrlq%d",
3879 device_get_nameunit(sc->
dev), idx);
3884 CH_ERR(sc,
"failed to allocate ctrlq%d: %d\n", idx, rc);
3885 sysctl_remove_oid(oid, 1, 1);
3896 CH_ERR(sc,
"failed to create hw ctrlq%d: %d\n", idx, rc);
3947 struct ifnet *
ifp = vi->
ifp;
3948 struct sysctl_oid *oid;
3953#if defined(INET) || defined(INET6)
3961 snprintf(name,
sizeof(name),
"%d", idx);
3962 oid = SYSCTL_ADD_NODE(&vi->
ctx, SYSCTL_CHILDREN(vi->
rxq_oid),
3963 OID_AUTO, name, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
3968#if defined(INET) || defined(INET6)
3969 if (
ifp->if_capenable & IFCAP_LRO)
3972 if (
ifp->if_capenable & IFCAP_HWRXTSTMP)
3974 snprintf(name,
sizeof(name),
"%s rxq%d-fl",
3975 device_get_nameunit(vi->
dev), idx);
3979 CH_ERR(vi,
"failed to allocate rxq%d: %d\n", idx, rc);
3980 sysctl_remove_oid(oid, 1, 1);
3981#if defined(INET) || defined(INET6)
3995 CH_ERR(vi,
"failed to create hw rxq%d: %d\n", idx, rc);
4004 (
"iq_base mismatch"));
4006 (
"PF with non-zero iq_base"));
4034#if defined(INET) || defined(INET6)
4039 bzero(
rxq,
sizeof(*
rxq));
4047 struct sysctl_oid_list *children;
4049 if (ctx == NULL || oid == NULL)
4052 children = SYSCTL_CHILDREN(oid);
4053#if defined(INET) || defined(INET6)
4054 SYSCTL_ADD_U64(ctx, children, OID_AUTO,
"lro_queued", CTLFLAG_RD,
4055 &
rxq->
lro.lro_queued, 0, NULL);
4056 SYSCTL_ADD_U64(ctx, children, OID_AUTO,
"lro_flushed", CTLFLAG_RD,
4057 &
rxq->
lro.lro_flushed, 0, NULL);
4060 &
rxq->
rxcsum,
"# of times hardware assisted with checksum");
4065 "# of times hardware assisted with inner checksum (VXLAN)");
4074 int intr_idx,
int maxp)
4078 struct sysctl_oid *oid;
4084 snprintf(name,
sizeof(name),
"%d", idx);
4085 oid = SYSCTL_ADD_NODE(&vi->
ctx,
4087 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
"offload rx queue");
4091 snprintf(name,
sizeof(name),
"%s ofld_rxq%d-fl",
4092 device_get_nameunit(vi->
dev), idx);
4097 CH_ERR(vi,
"failed to allocate ofld_rxq%d: %d\n", idx,
4099 sysctl_remove_oid(oid, 1, 1);
4105 counter_u64_alloc(M_WAITOK);
4106 add_ofld_rxq_sysctls(&vi->
ctx, oid, ofld_rxq);
4113 CH_ERR(vi,
"failed to create hw ofld_rxq%d: %d\n", idx,
4140 bzero(ofld_rxq,
sizeof(*ofld_rxq));
4145add_ofld_rxq_sysctls(
struct sysctl_ctx_list *ctx,
struct sysctl_oid *oid,
4148 struct sysctl_oid_list *children;
4150 if (ctx == NULL || oid == NULL)
4153 children = SYSCTL_CHILDREN(oid);
4154 SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
4156 "# of TOE TLS records received");
4157 SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
4159 "# of payload octets in received TOE TLS records");
4161 oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO,
"iscsi",
4162 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
"TOE iSCSI statistics");
4163 children = SYSCTL_CHILDREN(oid);
4165 SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO,
"ddp_setup_ok",
4167 "# of times DDP buffer was setup successfully.");
4168 SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO,
"ddp_setup_error",
4170 "# of times DDP buffer setup failed.");
4171 SYSCTL_ADD_U64(ctx, children, OID_AUTO,
"ddp_octets",
4173 "# of octets placed directly");
4174 SYSCTL_ADD_U64(ctx, children, OID_AUTO,
"ddp_pdus",
4176 "# of PDUs with data placed directly.");
4177 SYSCTL_ADD_U64(ctx, children, OID_AUTO,
"fl_octets",
4179 "# of data octets delivered in freelist");
4180 SYSCTL_ADD_U64(ctx, children, OID_AUTO,
"fl_pdus",
4182 "# of PDUs with data delivered in freelist");
4183 SYSCTL_ADD_U64(ctx, children, OID_AUTO,
"padding_errors",
4185 "# of PDUs with invalid padding");
4186 SYSCTL_ADD_U64(ctx, children, OID_AUTO,
"header_digest_errors",
4188 "# of PDUs with invalid header digests");
4189 SYSCTL_ADD_U64(ctx, children, OID_AUTO,
"data_digest_errors",
4191 "# of PDUs with invalid data digests");
4203 while (!powerof2(qsize))
4205 fthresh =
ilog2(qsize);
4219 bzero(&c,
sizeof(c));
4242 CH_ERR(sc,
"failed to create hw ctrlq for tx_chan %d: %d\n",
4251 panic(
"%s: eq->cntxt_id (%d) more than the max (%d)", __func__,
4265 bzero(&c,
sizeof(c));
4287 device_printf(vi->
dev,
4288 "failed to create Ethernet egress queue: %d\n", rc);
4296 panic(
"%s: eq->cntxt_id (%d) more than the max (%d)", __func__,
4303#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
4311 bzero(&c,
sizeof(c));
4318 c.fetchszm_to_iqid =
4328 c.eqaddr = htobe64(
eq->
ba);
4332 device_printf(vi->
dev,
4333 "failed to create egress queue for TCP offload: %d\n", rc);
4341 panic(
"%s: eq->cntxt_id (%d) more than the max (%d)", __func__,
4352 struct sysctl_oid *oid)
4365 if (ctx != NULL && oid != NULL)
4382 bzero(
eq,
sizeof(*
eq));
4387 struct sysctl_oid *oid,
struct sge_eq *
eq)
4389 struct sysctl_oid_list *children = SYSCTL_CHILDREN(oid);
4391 SYSCTL_ADD_UAUTO(ctx, children, OID_AUTO,
"ba", CTLFLAG_RD, &
eq->
ba,
4392 "bus address of descriptor ring");
4393 SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"dmalen", CTLFLAG_RD, NULL,
4395 "desc ring size in bytes");
4396 SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
"abs_id", CTLFLAG_RD,
4397 &
eq->
abs_id, 0,
"absolute id of the queue");
4398 SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
"cntxt_id", CTLFLAG_RD,
4399 &
eq->
cntxt_id, 0,
"SGE context id of the queue");
4400 SYSCTL_ADD_U16(ctx, children, OID_AUTO,
"cidx", CTLFLAG_RD, &
eq->
cidx,
4401 0,
"consumer index");
4402 SYSCTL_ADD_U16(ctx, children, OID_AUTO,
"pidx", CTLFLAG_RD, &
eq->
pidx,
4403 0,
"producer index");
4404 SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"sidx", CTLFLAG_RD, NULL,
4405 eq->
sidx,
"status page index");
4431#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
4433 rc = ofld_eq_alloc(sc, vi,
eq);
4438 panic(
"%s: invalid eq type %d.", __func__,
eq->
type);
4441 CH_ERR(sc,
"failed to allocate egress queue(%d): %d\n",
4450 uint32_t mask = (1 << s_qpp) - 1;
4451 volatile uint8_t *
udb;
4483#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
4489 panic(
"%s: invalid eq type %d.", __func__,
eq->
type);
4492 CH_ERR(sc,
"failed to free eq (type %d): %d\n",
eq->
type, rc);
4495 eq->
flags &= ~EQ_HW_ALLOCATED;
4502 struct sysctl_ctx_list *ctx,
struct sysctl_oid *oid)
4517 TAILQ_INIT(&
wrq->incomplete_wrs);
4518 STAILQ_INIT(&
wrq->wr_list);
4531 MPASS(TAILQ_EMPTY(&
wrq->incomplete_wrs));
4532 MPASS(STAILQ_EMPTY(&
wrq->wr_list));
4533 bzero(
wrq,
sizeof(*
wrq));
4540 struct sysctl_oid_list *children;
4542 if (ctx == NULL || oid == NULL)
4545 children = SYSCTL_CHILDREN(oid);
4551 &
wrq->
tx_wrs_ss,
"# of work requests (copied from scratch space)");
4566 struct sysctl_oid *oid;
4571 snprintf(name,
sizeof(name),
"%d", idx);
4572 oid = SYSCTL_ADD_NODE(&vi->
ctx, SYSCTL_CHILDREN(vi->
txq_oid),
4573 OID_AUTO, name, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
4577 snprintf(name,
sizeof(name),
"%s txq%d",
4578 device_get_nameunit(vi->
dev), idx);
4585 CH_ERR(vi,
"failed to allocate mp_ring for txq%d: %d\n",
4588 sysctl_remove_oid(oid, 1, 1);
4594 CH_ERR(vi,
"failed to allocate txq%d: %d\n", idx, rc);
4614 CH_ERR(vi,
"failed to create hw txq%d: %d\n", idx, rc);
4624 (
"eq_base mismatch"));
4626 (
"PF with non-zero eq_base"));
4666 sglist_free(txq->
gl);
4667 free(txq->
sdesc, M_CXGBE);
4671 bzero(txq,
sizeof(*txq));
4677 struct sysctl_oid *oid,
struct sge_txq *txq)
4680 struct sysctl_oid_list *children;
4682 if (ctx == NULL || oid == NULL)
4686 children = SYSCTL_CHILDREN(oid);
4690 SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"tc",
4691 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, vi, txq - sc->
sge.
txq,
4692 sysctl_tc,
"I",
"traffic class (-1 means none)");
4695 &txq->
txcsum,
"# of times hardware assisted with checksum");
4697 &txq->
vlan_insertion,
"# of times hardware inserted 802.1Q tag");
4699 &txq->
tso_wrs,
"# of TSO work requests");
4701 &txq->
imm_wrs,
"# of work requests with immediate data");
4703 &txq->
sgl_wrs,
"# of work requests with direct SGL");
4705 &txq->
txpkt_wrs,
"# of txpkt work requests (one pkt/WR)");
4707 &txq->
txpkts0_wrs,
"# of txpkts (type 0) work requests");
4709 &txq->
txpkts1_wrs,
"# of txpkts (type 1) work requests");
4712 "# of frames tx'd using type0 txpkts work requests");
4715 "# of frames tx'd using type1 txpkts work requests");
4718 "# of times txpkts had to be flushed out by an egress-update");
4720 &txq->
raw_wrs,
"# of raw work requests (non-packets)");
4725 "# of times hardware assisted with inner checksums (VXLAN)");
4731 "# of NIC TLS records transmitted");
4734 "# of short NIC TLS records transmitted");
4737 "# of partial NIC TLS records transmitted");
4740 "# of full NIC TLS records transmitted");
4743 "# of payload octets in transmitted NIC TLS records");
4746 "# of octets DMAd but not transmitted in NIC TLS records");
4749 "# of NIC TLS options-only packets transmitted");
4752 "# of NIC TLS header-only packets transmitted");
4755 "# of NIC TLS FIN-only packets transmitted");
4758 "# of NIC TLS padded FIN packets on short TLS records");
4761 "# of NIC TLS sessions using AES-CBC");
4764 "# of NIC TLS sessions using AES-GCM");
4769#if defined(TCP_OFFLOAD) || defined(RATELIMIT)
4776 struct sysctl_oid *oid;
4784 MPASS(idx < vi->nofldtxq);
4787 snprintf(name,
sizeof(name),
"%d", idx);
4788 oid = SYSCTL_ADD_NODE(&vi->
ctx,
4790 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
"offload tx queue");
4792 snprintf(name,
sizeof(name),
"%s ofld_txq%d",
4793 device_get_nameunit(vi->
dev), idx);
4806 CH_ERR(vi,
"failed to allocate ofld_txq%d: %d\n", idx,
4808 sysctl_remove_oid(oid, 1, 1);
4819 add_ofld_txq_sysctls(&vi->
ctx, oid, ofld_txq);
4825 CH_ERR(vi,
"failed to create hw ofld_txq%d: %d\n", idx,
4859 bzero(ofld_txq,
sizeof(*ofld_txq));
4864add_ofld_txq_sysctls(
struct sysctl_ctx_list *ctx,
struct sysctl_oid *oid,
4867 struct sysctl_oid_list *children;
4869 if (ctx == NULL || oid == NULL)
4872 children = SYSCTL_CHILDREN(oid);
4873 SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO,
"tx_iscsi_pdus",
4875 "# of iSCSI PDUs transmitted");
4876 SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO,
"tx_iscsi_octets",
4878 "# of payload octets in transmitted iSCSI PDUs");
4879 SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO,
"tx_iscsi_iso_wrs",
4881 "# of iSCSI segmentation offload work requests");
4882 SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO,
"tx_toe_tls_records",
4884 "# of TOE TLS records transmitted");
4885 SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO,
"tx_toe_tls_octets",
4887 "# of payload octets in transmitted TOE TLS records");
4894 bus_addr_t *
ba = arg;
4897 (
"%s meant for single segment mappings only.", __func__));
4899 *
ba = error ? 0 : segs->ds_addr;
4913 *
fl->
udb = htole32(v);
4935 uint16_t max_pidx, zidx =
fl->
zidx;
4945 max_pidx = __predict_false(hw_cidx == 0) ?
fl->
sidx - 1 : hw_cidx - 1;
4946 if (
fl->
pidx == max_pidx * 8)
4955 if (sd->
cl != NULL) {
4957 if (sd->
nmbuf == 0) {
4977 if (atomic_fetchadd_int(&clm->
refcount, -1) == 1) {
4984 MPASS(sd->
cl == NULL);
4985 cl = uma_zalloc(rxb->
zone, M_NOWAIT);
4986 if (__predict_false(
cl == NULL)) {
4990 cl = uma_zalloc(rxb->
zone, M_NOWAIT);
4998 pa = pmap_kextract((vm_offset_t)
cl);
5003 *d = htobe64(pa | rxb->
hwidx2);
5006 *d = htobe64(pa | rxb->
hwidx1);
5013 if (__predict_false((++
fl->
pidx & 7) == 0)) {
5022 if (n < 8 ||
pidx == max_pidx)
5045 mtx_assert(&sc->
sfl_lock, MA_OWNED);
5046 TAILQ_FOREACH_SAFE(
fl, &sc->sfl, link, fl_temp) {
5050 TAILQ_REMOVE(&sc->sfl,
fl, link);
5056 if (!TAILQ_EMPTY(&sc->sfl))
5073 for (i = 0; i <
fl->
sidx * 8; i++, sd++) {
5081 if (atomic_fetchadd_int(&clm->
refcount, -1) == 1) {
5104 rc = sglist_append_mbuf(
gl, m);
5105 if (__predict_false(rc != 0)) {
5106 panic(
"%s: mbuf %p (%d segs) was vetted earlier but now fails "
5111 (
"%s: nsegs changed for mbuf %p from %d to %d", __func__, m,
5115 (
"%s: %d segments, should have been 1 <= nsegs <= %d", __func__,
5133 sizeof(struct
ulptx_sgl) + 8 * ((3 * nsegs) / 2 + (nsegs & 1));
5135 return (howmany(n, 16));
5152 sizeof(struct
ulptx_sgl) + 8 * ((3 * nsegs) / 2 + (nsegs & 1));
5154 return (howmany(n, 16));
5194 8 * ((3 * nsegs) / 2 + (nsegs & 1));
5196 return (howmany(n, 16));
5210 return (howmany(n, 16));
5224static inline uint64_t
5228 int csum_type, l2hlen, l3hlen;
5230 static const int csum_types[3][2] = {
5241 MPASS(m->m_pkthdr.l2hlen >= ETHER_HDR_LEN);
5242 MPASS(m->m_pkthdr.l3hlen >=
sizeof(
struct ip));
5245 MPASS(m->m_pkthdr.l4hlen > 0);
5246 MPASS(m->m_pkthdr.l5hlen > 0);
5247 MPASS(m->m_pkthdr.inner_l2hlen >= ETHER_HDR_LEN);
5248 MPASS(m->m_pkthdr.inner_l3hlen >=
sizeof(
struct ip));
5250 l2hlen = m->m_pkthdr.l2hlen + m->m_pkthdr.l3hlen +
5251 m->m_pkthdr.l4hlen + m->m_pkthdr.l5hlen +
5252 m->m_pkthdr.inner_l2hlen - ETHER_HDR_LEN;
5253 l3hlen = m->m_pkthdr.inner_l3hlen;
5255 l2hlen = m->m_pkthdr.l2hlen - ETHER_HDR_LEN;
5256 l3hlen = m->m_pkthdr.l3hlen;
5263 if (m->m_pkthdr.csum_flags & (CSUM_IP_TCP | CSUM_INNER_IP_TCP |
5264 CSUM_IP6_TCP | CSUM_INNER_IP6_TCP))
5266 else if (m->m_pkthdr.csum_flags & (CSUM_IP_UDP | CSUM_INNER_IP_UDP |
5267 CSUM_IP6_UDP | CSUM_INNER_IP6_UDP))
5272 if (m->m_pkthdr.csum_flags & (CSUM_IP | CSUM_IP_TCP | CSUM_IP_UDP |
5273 CSUM_INNER_IP | CSUM_INNER_IP_TCP | CSUM_INNER_IP_UDP))
5276 MPASS(m->m_pkthdr.csum_flags & (CSUM_IP6_TCP | CSUM_IP6_UDP |
5277 CSUM_INNER_IP6_TCP | CSUM_INNER_IP6_UDP));
5284 csum_type = csum_types[x][y];
5285 MPASS(csum_type != 0);
5303 KASSERT(m0->m_pkthdr.l2hlen > 0 && m0->m_pkthdr.l3hlen > 0 &&
5304 m0->m_pkthdr.l4hlen > 0,
5305 (
"%s: mbuf %p needs TSO but missing header lengths",
5313 if (m0->m_pkthdr.l3hlen ==
sizeof(
struct ip6_hdr))
5319 lso->
mss = htobe16(m0->m_pkthdr.tso_segsz);
5321 lso->
len = htobe32(m0->m_pkthdr.len);
5332 KASSERT(m0->m_pkthdr.inner_l2hlen > 0 &&
5333 m0->m_pkthdr.inner_l3hlen > 0 && m0->m_pkthdr.inner_l4hlen > 0 &&
5334 m0->m_pkthdr.inner_l5hlen > 0,
5335 (
"%s: mbuf %p needs VXLAN_TSO but missing inner header lengths",
5337 KASSERT(m0->m_pkthdr.l2hlen > 0 && m0->m_pkthdr.l3hlen > 0 &&
5338 m0->m_pkthdr.l4hlen > 0 && m0->m_pkthdr.l5hlen > 0,
5339 (
"%s: mbuf %p needs VXLAN_TSO but missing outer header lengths",
5346 (m0->m_pkthdr.l2hlen - ETHER_HDR_LEN) >> 2) |
5349 if (m0->m_pkthdr.l3hlen ==
sizeof(
struct ip6_hdr))
5361 m0->m_pkthdr.l3hlen + m0->m_pkthdr.l4hlen +
5362 m0->m_pkthdr.l5hlen) |
5368 (m0->m_pkthdr.inner_l2hlen - ETHER_HDR_LEN) >> 2) |
5371 if (m0->m_pkthdr.inner_l3hlen ==
sizeof(
struct ip6_hdr))
5381 return (tnl_lso + 1);
5384#define VM_TX_L2HDR_LEN 16
5402 int len16, ndesc, pktlen;
5409 pktlen = m0->m_pkthdr.len;
5439 cpl = (
void *)(wr + 1);
5456 cpl->
len = htobe16(pktlen);
5457 cpl->
ctrl1 = htobe64(ctrl1);
5460 dst = (
void *)(cpl + 1);
5470 dst = (
void *)&
eq->
desc[0];
5502 MPASS(ndesc <= available);
5505 for (m = m0; m != NULL; m = m->m_next)
5534 int len16, ndesc, pktlen, nsegs;
5542 pktlen = m0->m_pkthdr.len;
5558 MPASS(ndesc <= available);
5579 cpl = (
void *)(wr + 1);
5601 cpl->
len = htobe16(pktlen);
5602 cpl->
ctrl1 = htobe64(ctrl1);
5605 dst = (
void *)(cpl + 1);
5606 if (__predict_false((uintptr_t)dst == (uintptr_t)&
eq->
desc[
eq->
sidx]))
5607 dst = (caddr_t)&
eq->
desc[0];
5615 for (m = m0; m != NULL; m = m->m_next) {
5622 KASSERT(pktlen == 0, (
"%s: %d bytes left.", __func__, pktlen));
5647 len =
sizeof(
struct ether_header);
5649 return (memcmp(m->m_data, &
txp->
ethmacdst[0], len) != 0);
5662 int avail,
bool *send)
5675 goto cannot_coalesce;
5688 if (m->m_pkthdr.len +
txp->
plen > 65535)
5689 goto retry_after_send;
5691 goto retry_after_send;
5702 goto cannot_coalesce;
5714 int avail,
bool *send)
5731 if (m->m_pkthdr.len > 65535)
5732 goto cannot_coalesce;
5745 goto cannot_coalesce;
5753 if (m->m_pkthdr.len +
txp->
plen > 65535) {
5763 goto retry_after_send;
5767 goto retry_after_send;
5770 goto retry_after_send;
5798 int ndesc, i, checkwrap;
5799 struct mbuf *m, *last;
5823 for (i = 0; i <
txp->
npkt; i++) {
5836 ulpsc = (
void *)(ulpmc + 1);
5841 cpl = (
void *)(ulpsc + 1);
5844 cpl = (
void *)&
eq->
desc[0];
5869 cpl->
len = htobe16(m->m_pkthdr.len);
5870 cpl->
ctrl1 = htobe64(ctrl1);
5875 flitp = (
void *)&
eq->
desc[0];
5880 last->m_nextpkt = m;
5910 struct mbuf *m, *last;
5916 MPASS(
txp->
mb[0] != NULL);
5936 for (i = 0; i <
txp->
npkt; i++) {
5938 if (i & 1 && (uintptr_t)flitp == (uintptr_t)&
eq->
desc[
eq->
sidx])
5957 cpl->
len = htobe16(m->m_pkthdr.len);
5958 cpl->
ctrl1 = htobe64(ctrl1);
5965 last->m_nextpkt = m;
5988 struct sglist *
gl = txq->
gl;
5989 struct sglist_seg *seg;
5992 int i, nflits, nsegs;
5994 KASSERT(((uintptr_t)(*to) & 0xf) == 0,
5995 (
"%s: SGL must start at a 16 byte boundary: %p", __func__, *to));
5996 MPASS((uintptr_t)(*to) >= (uintptr_t)&
eq->
desc[0]);
5997 MPASS((uintptr_t)(*to) < (uintptr_t)&
eq->
desc[
eq->
sidx]);
6000 nsegs =
gl->sg_nseg;
6003 nflits = (3 * (nsegs - 1)) / 2 + ((nsegs - 1) & 1) + 2;
6006 seg = &
gl->sg_segs[0];
6007 usgl = (
void *)flitp;
6017 usgl->
len0 = htobe32(seg->ss_len);
6018 usgl->
addr0 = htobe64(seg->ss_paddr);
6021 if (checkwrap == 0 || (uintptr_t)(flitp + nflits) <= (uintptr_t)wrap) {
6025 for (i = 0; i < nsegs - 1; i++, seg++) {
6026 usgl->
sge[i / 2].
len[i & 1] = htobe32(seg->ss_len);
6027 usgl->
sge[i / 2].
addr[i & 1] = htobe64(seg->ss_paddr);
6030 usgl->
sge[i / 2].
len[1] = htobe32(0);
6037 flitp = (
void *)(usgl + 1);
6038 for (i = 0; i < nflits - 2; i++) {
6040 flitp = (
void *)
eq->
desc;
6041 *flitp++ =
get_flit(seg, nsegs - 1, i);
6046 MPASS(((uintptr_t)flitp) & 0xf);
6050 MPASS((((uintptr_t)flitp) & 0xf) == 0);
6051 if (__predict_false(flitp == wrap))
6054 *to = (
void *)flitp;
6061 MPASS((uintptr_t)(*to) >= (uintptr_t)&
eq->
desc[0]);
6062 MPASS((uintptr_t)(*to) < (uintptr_t)&
eq->
desc[
eq->
sidx]);
6064 if (__predict_true((uintptr_t)(*to) + len <=
6066 bcopy(from, *to, len);
6069 int portion = (uintptr_t)&
eq->
desc[
eq->
sidx] - (uintptr_t)(*to);
6071 bcopy(from, *to, portion);
6073 portion = len - portion;
6074 bcopy(from, (
void *)
eq->
desc, portion);
6075 (*to) = (caddr_t)
eq->
desc + portion;
6091 switch (ffs(db) - 1) {
6097 volatile uint64_t *dst, *src;
6106 (
"%s: inappropriate doorbell (0x%x, %d, %d) for eq %p",
6112 src = (
void *)&
eq->
desc[i];
6113 while (src != (
void *)&
eq->
desc[i + 1])
6145 uint16_t hw_cidx,
pidx;
6150 if (
pidx == hw_cidx)
6156static inline uint16_t
6162 return (be16toh(
cidx));
6173 u_int can_reclaim, reclaimed;
6180 while (can_reclaim && reclaimed < n) {
6182 struct mbuf *m, *nextpkt;
6188 KASSERT(can_reclaim >= ndesc,
6189 (
"%s: unexpected number of credits: %d, %d",
6190 __func__, can_reclaim, ndesc));
6192 (
"%s: descriptor with no credits: cidx %d",
6195 for (m = txsd->
m; m != NULL; m = nextpkt) {
6196 nextpkt = m->m_nextpkt;
6197 m->m_nextpkt = NULL;
6201 can_reclaim -= ndesc;
6227 int i = (idx / 3) * 2;
6233 rc = (uint64_t)segs[i].
ss_len << 32;
6235 rc |= (uint64_t)(segs[i + 1].
ss_len);
6237 return (htobe64(rc));
6240 return (htobe64(segs[i].ss_paddr));
6242 return (htobe64(segs[i + 1].ss_paddr));
6258 if (rxb->
size1 < PAGE_SIZE &&
6264 if (rxb->
size2 >= maxp)
6274 if (rxb->
size1 >= maxp)
6290 TAILQ_INSERT_TAIL(&sc->sfl,
fl, link);
6302 atomic_readandclear_int(&
eq->
equiq);
6313 atomic_readandclear_int(&
eq->
equiq);
6327 struct sge *s = &sc->
sge;
6329 static void (*h[])(
struct adapter *,
struct sge_eq *) = {NULL,
6333 KASSERT(m == NULL, (
"%s: payload with opcode %02x", __func__,
6350 const struct cpl_fw6_msg *cpl = (
const void *)(rss + 1);
6352 KASSERT(m == NULL, (
"%s: payload with opcode %02x", __func__,
6379 "%s: Received WRERR_RPL message with opcode %#x\n",
6380 device_get_nameunit(adap->
dev), opcode);
6383 log(LOG_ERR,
"%s: FW_ERROR (%s) ", device_get_nameunit(adap->
dev),
6388 log(LOG_ERR,
"exception info:\n");
6390 log(LOG_ERR,
"%s%08x", i == 0 ?
"\t" :
" ",
6395 log(LOG_ERR,
"HW module regaddr %08x regval %08x\n",
6400 log(LOG_ERR,
"WR cidx %d PF %d VF %d eqid %d hdr:\n",
6405 for (i = 0; i < nitems(e->
u.
wr.
wrhdr); i++)
6406 log(LOG_ERR,
"%s%02x", i == 0 ?
"\t" :
" ",
6411 log(LOG_ERR,
"ACL cidx %d PF %d VF %d eqid %d %s",
6418 for (i = 0; i < nitems(e->
u.
acl.
val); i++)
6419 log(LOG_ERR,
" %02x", e->
u.
acl.
val[i]);
6423 log(LOG_ERR,
"type %#x\n",
6455 sbuf_new(&sb, NULL, 128, SBUF_AUTOEXTEND);
6466 rc = sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req);
6472#if defined(INET) || defined(INET6)
6477txpkt_eo_len16(u_int nsegs, u_int immhdrs, u_int tso)
6485 if (__predict_false(nsegs == 0))
6489 n +=
sizeof(
struct ulptx_sgl) + 8 * ((3 * nsegs) / 2 + (nsegs & 1));
6494 return (howmany(n, 16));
6498#define ETID_FLOWC_NPARAMS 6
6499#define ETID_FLOWC_LEN (roundup2((sizeof(struct fw_flowc_wr) + \
6500 ETID_FLOWC_NPARAMS * sizeof(struct fw_flowc_mnemval)), 16))
6501#define ETID_FLOWC_LEN16 (howmany(ETID_FLOWC_LEN, 16))
6511 mtx_assert(&cst->
lock, MA_OWNED);
6516 if (__predict_false(flowc == NULL))
6519 bzero(flowc, ETID_FLOWC_LEN);
6539 cst->
flags &= ~EO_FLOWC_PENDING;
6547#define ETID_FLUSH_LEN16 (howmany(sizeof (struct fw_flowc_wr), 16))
6555 mtx_assert(&cst->
lock, MA_OWNED);
6558 if (__predict_false(flowc == NULL))
6561 bzero(flowc, ETID_FLUSH_LEN16 * 16);
6577 struct mbuf *m0,
int compl)
6582 int len16, pktlen, nsegs, immhdrs;
6586 struct sglist_seg segs[38];
6588 mtx_assert(&cst->
lock, MA_OWNED);
6590 KASSERT(m0->m_pkthdr.l2hlen > 0 && m0->m_pkthdr.l3hlen > 0 &&
6591 m0->m_pkthdr.l4hlen > 0,
6592 (
"%s: ethofld mbuf %p is missing header lengths", __func__, m0));
6594 len16 = mbuf_eo_len16(m0);
6595 nsegs = mbuf_eo_nsegs(m0);
6596 pktlen = m0->m_pkthdr.len;
6600 immhdrs = m0->m_pkthdr.l2hlen + m0->m_pkthdr.l3hlen + m0->m_pkthdr.l4hlen;
6608 if (needs_outer_udp_csum(m0)) {
6615 wr->
u.
udpseg.
mss = htobe16(pktlen - immhdrs);
6618 cpl = (
void *)(wr + 1);
6633 wr->
u.
tcpseg.
mss = htobe16(m0->m_pkthdr.tso_segsz);
6638 ETHER_HDR_LEN) >> 2) |
6641 if (m0->m_pkthdr.l3hlen ==
sizeof(
struct ip6_hdr))
6645 lso->
mss = htobe16(m0->m_pkthdr.tso_segsz);
6647 lso->
len = htobe32(pktlen);
6649 cpl = (
void *)(lso + 1);
6652 cpl = (
void *)(wr + 1);
6657 MPASS(needs_outer_l4_csum(m0));
6669 cpl->
len = htobe16(pktlen);
6670 cpl->
ctrl1 = htobe64(ctrl1);
6673 p = (uintptr_t)(cpl + 1);
6674 m_copydata(m0, 0, immhdrs, (
void *)p);
6682 pad = 16 - (immhdrs & 0xf);
6683 bzero((
void *)p, pad);
6685 usgl = (
void *)(p + pad);
6689 sglist_init(&sg, nitems(segs), segs);
6690 for (; m0 != NULL; m0 = m0->m_next) {
6691 if (__predict_false(m0->m_len == 0))
6693 if (immhdrs >= m0->m_len) {
6694 immhdrs -= m0->m_len;
6697 if (m0->m_flags & M_EXTPG)
6698 sglist_append_mbuf_epg(&sg, m0,
6699 mtod(m0, vm_offset_t), m0->m_len);
6701 sglist_append(&sg, mtod(m0,
char *) + immhdrs,
6702 m0->m_len - immhdrs);
6705 MPASS(sg.sg_nseg == nsegs);
6711 *(uint64_t *)((
char *)wr + len16 * 16 - 8) = 0;
6714 usgl->
addr0 = htobe64(segs[0].ss_paddr);
6715 for (i = 0; i < nsegs - 1; i++) {
6716 usgl->
sge[i / 2].
len[i & 1] = htobe32(segs[i + 1].
ss_len);
6717 usgl->
sge[i / 2].
addr[i & 1] = htobe64(segs[i + 1].ss_paddr);
6720 usgl->
sge[i / 2].
len[1] = htobe32(0);
6730 int next_credits, compl;
6733 mtx_assert(&cst->
lock, MA_OWNED);
6735 while ((m = mbufq_first(&cst->pending_tx)) != NULL) {
6739 next_credits = mbuf_eo_len16(m);
6740 MPASS(next_credits > 0);
6751 if (__predict_false(wr == NULL)) {
6759 ETHER_BPF_MTAP(cst->
com.ifp, m);
6760 write_ethofld_wr(cst, wr, m, compl);
6766 (void) mbufq_dequeue(&cst->pending_tx);
6778 m->m_pkthdr.snd_tag = NULL;
6779 m->m_pkthdr.csum_flags &= ~CSUM_SND_TAG;
6780 m_snd_tag_rele(&cst->
com);
6787ethofld_transmit(
struct ifnet *
ifp,
struct mbuf *m0)
6792 MPASS(m0->m_nextpkt == NULL);
6793 MPASS(m0->m_pkthdr.csum_flags & CSUM_SND_TAG);
6794 MPASS(m0->m_pkthdr.snd_tag != NULL);
6797 mtx_lock(&cst->
lock);
6804 const uint32_t rss_mask = vi->
rss_size - 1;
6808 if (M_HASHTYPE_ISHASH(m0))
6809 rss_hash = m0->m_pkthdr.flowid;
6811 rss_hash = arc4random();
6813 cst->
iqid = vi->
rss[rss_hash & rss_mask];
6815 rc = send_etid_flowc_wr(cst, pi, vi);
6820 if (__predict_false(cst->
plen + m0->m_pkthdr.len > eo_max_backlog)) {
6825 mbufq_enqueue(&cst->pending_tx, m0);
6826 cst->
plen += m0->m_pkthdr.len;
6834 m_snd_tag_ref(&cst->
com);
6836 mtx_unlock(&cst->
lock);
6837 m_snd_tag_rele(&cst->
com);
6841 mtx_unlock(&cst->
lock);
6842 if (__predict_false(rc != 0))
6851 const struct cpl_fw4_ack *cpl = (
const void *)(rss + 1);
6855 uint8_t credits = cpl->
credits;
6857 cst = lookup_etid(sc,
etid);
6858 mtx_lock(&cst->
lock);
6860 MPASS(credits >= ETID_FLOWC_LEN16);
6861 credits -= ETID_FLOWC_LEN16;
6862 cst->
flags &= ~EO_FLOWC_RPL_PENDING;
6866 (
"%s: etid %u (%p) wasn't expecting completion.",
6867 __func__,
etid, cst));
6870 while (credits > 0) {
6872 if (__predict_false(m == NULL)) {
6880 MPASS(credits == ETID_FLUSH_LEN16);
6884 cst->
flags &= ~EO_FLUSH_RPL_PENDING;
6886 cxgbe_rate_tag_free_locked(cst);
6890 (
"%s: too many credits (%u, %u)", __func__, cpl->
credits,
6892 KASSERT(credits >= mbuf_eo_len16(m),
6893 (
"%s: too few credits (%u, %u, %u)", __func__,
6894 cpl->
credits, credits, mbuf_eo_len16(m)));
6895 credits -= mbuf_eo_len16(m);
6896 cst->
plen -= m->m_pkthdr.len;
6908 m_snd_tag_ref(&cst->
com);
6909 m = mbufq_first(&cst->pending_tx);
6910 if (m != NULL && cst->
tx_credits >= mbuf_eo_len16(m))
6912 mtx_unlock(&cst->
lock);
6913 m_snd_tag_rele(&cst->
com);
6920 MPASS(mbufq_first(&cst->pending_tx) == NULL);
6921 mtx_unlock(&cst->
lock);
int(* an_handler_t)(struct sge_iq *, const struct rsp_ctrl *)
static struct wrqe * alloc_wrqe(int wr_len, struct sge_wrq *wrq)
static uint32_t t4_read_reg(struct adapter *sc, uint32_t reg)
#define FL_NOT_RUNNING_LOW(fl)
int(* fw_msg_handler_t)(struct adapter *, const __be64 *)
static void t4_write_reg(struct adapter *sc, uint32_t reg, uint32_t val)
#define IDXDIFF(head, tail, wrap)
STAILQ_HEAD(, wrqe) wr_list
struct sge_nm_rxq * nm_rxq
#define TXQ_LOCK_ASSERT_OWNED(txq)
static void t4_wrq_tx(struct adapter *sc, struct wrqe *wr)
#define EQ_LOCK_ASSERT_OWNED(eq)
#define for_each_rxq(vi, iter, q)
static int forwarding_intr_to_fwq(struct adapter *sc)
#define FL_LOCK_ASSERT_OWNED(fl)
#define for_each_nm_rxq(vi, iter, q)
#define for_each_ofld_rxq(vi, iter, q)
#define IDXINCR(idx, incr, wrap)
int sysctl_tc(SYSCTL_HANDLER_ARGS)
static struct sge_rxq * iq_to_rxq(struct sge_iq *iq)
#define for_each_ofld_txq(vi, iter, q)
static void free_wrqe(struct wrqe *wr)
#define for_each_txq(vi, iter, q)
#define for_each_nm_txq(vi, iter, q)
int(* cpl_handler_t)(struct sge_iq *, const struct rss_header *, struct mbuf *)
#define FL_RUNNING_LOW(fl)
#define ADAPTER_LOCK_ASSERT_NOTOWNED(sc)
#define CXGBE_UNIMPLEMENTED(s)
static int tx_len16_to_desc(int len16)
bool t4_slow_intr_handler(struct adapter *adapter, bool verbose)
static int is_ftid(const struct adapter *sc, u_int tid)
int t4_iq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int iqtype, unsigned int iqid, unsigned int fl0id, unsigned int fl1id)
static int is_hashfilter(const struct adapter *adap)
static int t4_wr_mbox(struct adapter *adap, int mbox, const void *cmd, int size, void *rpl)
void t4_set_reg_field(struct adapter *adap, unsigned int addr, u32 mask, u32 val)
int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int eqid)
static int is_etid(const struct adapter *sc, u_int tid)
int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
void t4_fatal_err(struct adapter *adapter, bool fw_error)
static int chip_id(struct adapter *adap)
#define for_each_port(adapter, iter)
int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int nparams, const u32 *params, const u32 *val)
void t4_tp_pio_write(struct adapter *adap, const u32 *buff, u32 nregs, u32 start_index, bool sleep_ok)
static int is_t4(struct adapter *adap)
static int is_hpftid(const struct adapter *sc, u_int tid)
int t4_eth_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int eqid)
static int is_ktls(const struct adapter *adap)
void t4_tp_pio_read(struct adapter *adap, u32 *buff, u32 nregs, u32 start_index, bool sleep_ok)
static unsigned int us_to_core_ticks(const struct adapter *adap, unsigned int us)
int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int eqid)
static struct cxgbe_rate_tag * mst_to_crt(struct m_snd_tag *t)
#define CH_ERR(adap, fmt,...)
unsigned int max_pkts_per_eth_tx_pkts_wr
struct sysctl_oid * fwq_oid
volatile uint8_t * udbs_base
const struct chip_params * chip_params
struct sysctl_ctx_list ctx
struct adapter_params params
struct port_info * port[MAX_NPORTS]
struct sysctl_oid * ctrlq_oid
struct callout sfl_callout
struct taskqueue * tq[MAX_NCHAN]
RSS_HDR __be32 opcode_qid
__be32 op_to_IpIdSplitOut
__be16 UdpLenSetOut_to_TnlHdrLen
struct sge_ofld_txq * eo_txq
struct mbufq pending_tx pending_fwack
__be32 autoequiqe_to_viid
union fw_error_cmd::fw_error u
union fw_eth_tx_eo_wr::fw_eth_tx_eo u
struct fw_flowc_mnemval mnemval[0]
__be16 iqdroprss_to_iqesize
__be16 fl0dcaen_to_fl0cidxfthresh
__be32 type_to_iqandstindex
volatile uint16_t hw_cidx
uint64_t cl_fast_recycled
counter_u64_t rx_iscsi_ddp_setup_error
uint64_t rx_iscsi_fl_pdus
uint64_t rx_iscsi_ddp_pdus
u_long rx_toe_tls_records
uint64_t rx_iscsi_fl_octets
uint64_t rx_iscsi_data_digest_errors
uint64_t rx_iscsi_ddp_octets
uint64_t rx_iscsi_header_digest_errors
uint64_t rx_iscsi_padding_errors
counter_u64_t rx_iscsi_ddp_setup_ok
counter_u64_t tx_iscsi_octets
counter_u64_t tx_iscsi_iso_wrs
counter_u64_t tx_toe_tls_octets
counter_u64_t tx_toe_tls_records
counter_u64_t tx_iscsi_pdus
u32 sge_fl_buffer_size[SGE_FLBUF_SIZES]
uint64_t kern_tls_options
struct task tx_reclaim_task
uint64_t kern_tls_partial
uint64_t kern_tls_records
uint64_t kern_tls_fin_short
uint8_t ss[SGE_MAX_WR_LEN]
struct rx_buf_info rx_buf_info[SW_ZONE_SIZES]
struct sge_ofld_rxq * ofld_rxq
struct sge_ofld_txq * ofld_txq
struct ulptx_sge_pair sge[]
struct sysctl_ctx_list ctx
struct sysctl_oid * ofld_rxq_oid
struct sysctl_oid * rxq_oid
struct sysctl_oid * txq_oid
struct sysctl_oid * ofld_txq_oid
#define V_QINTR_TIMER_IDX(x)
int t6_ktls_write_wr(struct sge_txq *txq, void *dst, struct mbuf *m, u_int nsegs, u_int available)
int t6_ktls_parse_pkt(struct mbuf *m, int *nsegsp, int *len16p)
int mp_ring_alloc(struct mp_ring **pr, int size, void *cookie, ring_drain_t drain, ring_can_drain_t can_drain, struct malloc_type *mt, struct mtx *lck, int flags)
void mp_ring_check_drainage(struct mp_ring *r, int budget)
void mp_ring_sysctls(struct mp_ring *r, struct sysctl_ctx_list *ctx, struct sysctl_oid_list *children)
bool mp_ring_is_idle(struct mp_ring *r)
void mp_ring_free(struct mp_ring *r)
#define F_CPL_TX_TNL_LSO_FIRST
#define V_ULP_TXPKT_FID(x)
#define F_CPL_TX_TNL_LSO_IPV6OUT
#define G_T6_RX_TNL_TYPE(x)
#define V_CPL_TX_TNL_LSO_IPHDRLEN(x)
#define F_CPL_TX_TNL_LSO_IPHDRCHKOUT
#define F_CPL_TX_TNL_LSO_LAST
#define V_TXPKT_CSUM_TYPE(x)
#define F_TXPKT_L4CSUM_DIS
#define V_TXPKT_ETHHDR_LEN(x)
#define V_CPL_TX_TNL_LSO_SIZE(x)
#define V_CPL_TX_TNL_LSO_TNLHDRLEN(x)
#define F_CPL_TX_TNL_LSO_IPLENSETOUT
#define V_CPL_TX_TNL_LSO_ETHHDRLEN(x)
#define V_ULP_TXPKT_DEST(x)
#define RX_PKT_TNL_TYPE_VXLAN
#define F_CPL_TX_TNL_LSO_UDPCHKCLROUT
#define V_LSO_TCPHDR_LEN(x)
#define G_T6_RX_TNLHDR_LEN(x)
#define V_CPL_TX_TNL_LSO_TNLTYPE(x)
#define V_LSO_ETHHDR_LEN(x)
#define V_CPL_TX_TNL_LSO_MSS(x)
#define F_LSO_FIRST_SLICE
#define G_CPL_FW4_ACK_FLOWID(x)
#define V_TXPKT_VF_VLD(x)
#define F_CPL_TX_TNL_LSO_IPV6
#define V_TXPKT_OPCODE(x)
#define V_CPL_TX_TNL_LSO_ETHHDRLENOUT(x)
#define V_CPL_TX_TNL_LSO_IPHDRLENOUT(x)
#define V_TXPKT_IPHDR_LEN(x)
#define V_CPL_TX_TNL_LSO_TCPHDRLEN(x)
#define F_CPL_TX_TNL_LSO_UDPLENSETOUT
#define V_LSO_IPHDR_LEN(x)
#define V_T6_TXPKT_ETHHDR_LEN(x)
#define G_T6_COMPR_RXERR_VEC(x)
#define V_CPL_TX_TNL_LSO_OPCODE(x)
#define F_TXPKT_IPCSUM_DIS
#define F_CPL_TX_TNL_LSO_IPIDINCOUT
#define A_SGE_ITP_CONTROL
#define V_HOSTPAGESIZEPF3(x)
#define A_PL_PF_INT_CAUSE
#define V_HOSTPAGESIZEPF5(x)
#define V_HOSTPAGESIZEPF1(x)
#define V_EGRSTATUSPAGESIZE(x)
#define A_SGE_FL_BUFFER_SIZE2
#define A_SGE_INGRESS_RX_THRESHOLD
#define A_SGE_TIMER_VALUE_4_AND_5
#define A_SGE_FL_BUFFER_SIZE0
#define V_INGPADBOUNDARY(x)
#define MYPF_REG(reg_addr)
#define A_SGE_TIMER_VALUE_0_AND_1
#define A_ULP_RX_ISCSI_PSZ
#define A_SGE_HOST_PAGE_SIZE
#define V_HOSTPAGESIZEPF0(x)
#define V_INDICATESIZE(x)
#define F_EGRSTATUSPAGESIZE
#define A_ULP_RX_TDDP_PSZ
#define V_HOSTPAGESIZEPF7(x)
#define A_SGE_FL_BUFFER_SIZE15
#define V_HOSTPAGESIZEPF4(x)
#define V_HOSTPAGESIZEPF6(x)
#define V_INGPACKBOUNDARY(x)
#define A_SGE_FL_BUFFER_SIZE1
#define V_HOSTPAGESIZEPF2(x)
#define M_INGPACKBOUNDARY
#define A_SGE_TIMER_VALUE_2_AND_3
#define X_FETCHBURSTMIN_64B_T6
#define X_FETCHBURSTMIN_64B
#define X_INGPADBOUNDARY_SHIFT
#define X_RSPD_TYPE_FLBUF
#define X_HOSTFCMODE_NONE
#define X_HOSTFCMODE_STATUS_PAGE
#define X_CIDXFLUSHTHRESH_128
#define X_FETCHBURSTMIN_128B
#define X_FETCHBURSTMAX_256B
#define X_UPDATEDELIVERY_INTERRUPT
#define X_TIMERREG_UPDATE_CIDX
#define X_FETCHBURSTMAX_512B
#define X_T6_INGPADBOUNDARY_SHIFT
static void add_fl_to_sfl(struct adapter *, struct sge_fl *)
void t4_register_an_handler(an_handler_t h)
static void init_iq(struct sge_iq *, struct adapter *, int, int, int, int, int)
static counter_u64_t pullups
static int set_tcb_rpl_handler(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
static int alloc_txq(struct vi_info *, struct sge_txq *, int)
void t4_register_shared_cpl_handler(int opcode, cpl_handler_t h, int cookie)
static void add_eq_sysctls(struct adapter *, struct sysctl_ctx_list *, struct sysctl_oid *, struct sge_eq *)
static bool needs_vxlan_tso(struct mbuf *m)
static int skip_scatter_segment(struct adapter *sc, struct sge_fl *fl, int fr_offset, int remaining)
cpl_handler_t abort_rpl_rss_handlers[NUM_CPL_COOKIES]
static u_int write_txpkts_vm_wr(struct adapter *, struct sge_txq *)
SYSCTL_INT(_hw_cxgbe, OID_AUTO, fl_pktshift, CTLFLAG_RDTUN, &fl_pktshift, 0, "payload DMA offset in rx buffer (bytes)")
static void add_rxq_sysctls(struct sysctl_ctx_list *, struct sysctl_oid *, struct sge_rxq *)
static u_int reclaim_tx_descs(struct sge_txq *, u_int)
static u_int eth_tx(struct mp_ring *r, u_int cidx, u_int pidx, bool *coalescing)
an_handler_t t4_an_handler
static u_int txpkts1_len16(void)
static int handle_sge_egr_update(struct sge_iq *, const struct rss_header *, struct mbuf *)
static void handle_wrq_egr_update(struct adapter *sc, struct sge_eq *eq)
static bool record_eth_tx_time(struct sge_txq *txq)
void t4_sge_modload(void)
static int alloc_rxq(struct vi_info *, struct sge_rxq *, int, int, int)
static void * write_lso_cpl(void *cpl, struct mbuf *m0)
static struct mbuf * get_scatter_segment(struct adapter *sc, struct sge_fl *fl, int fr_offset, int remaining)
static u_int qsize_to_fthresh(int qsize)
static int t4_tx_coalesce
static void init_fl(struct adapter *, struct sge_fl *, int, int, char *)
cpl_handler_t act_open_rpl_handlers[NUM_CPL_COOKIES]
static int count_mbuf_nsegs(struct mbuf *m, int skip, uint8_t *cflags)
static int free_iq_fl_hwq(struct adapter *, struct sge_iq *, struct sge_fl *)
static void ring_fl_db(struct adapter *, struct sge_fl *)
static int alloc_iq_fl(struct vi_info *, struct sge_iq *, struct sge_fl *, struct sysctl_ctx_list *, struct sysctl_oid *)
static int add_to_txpkts_pf(struct adapter *, struct sge_txq *, struct mbuf *, int, bool *)
int t4_create_dma_tag(struct adapter *sc)
static int buffer_packing
static bool bufidx_used(struct adapter *sc, int idx)
struct mbuf * alloc_wr_mbuf(int len, int how)
static int handle_fw_msg(struct sge_iq *, const struct rss_header *, struct mbuf *)
static int max_nsegs_allowed(struct mbuf *m, bool vm_wr)
void t4_tweak_chip_settings(struct adapter *sc)
static void free_wrq(struct adapter *, struct sge_wrq *)
static void add_fl_sysctls(struct adapter *, struct sysctl_ctx_list *, struct sysctl_oid *, struct sge_fl *)
void commit_wrq_wr(struct sge_wrq *wrq, void *w, struct wrq_cookie *cookie)
void free_fl_buffers(struct adapter *sc, struct sge_fl *fl)
static uint16_t read_hw_cidx(struct sge_eq *)
static void move_to_next_rxbuf(struct sge_fl *fl)
static int discard_tx(struct sge_eq *eq)
static void free_eq(struct adapter *, struct sge_eq *)
static void calculate_mbuf_len16(struct mbuf *, bool)
static int wr_can_update_eq(void *p)
static int service_iq_fl(struct sge_iq *, int)
static int mbuf_nsegs(struct mbuf *m)
static int mbuf_len16(struct mbuf *m)
int t4_setup_vi_queues(struct vi_info *vi)
static int add_to_txpkts_vf(struct adapter *, struct sge_txq *, struct mbuf *, int, bool *)
static void tx_reclaim(void *, int)
static int eth_rx(struct adapter *, struct sge_rxq *, const struct iq_desc *, u_int)
int parse_pkt(struct mbuf **mp, bool vm_wr)
static bool needs_hwcsum(struct mbuf *m)
static u_int can_resume_eth_tx(struct mp_ring *r)
static void free_iq_fl(struct adapter *, struct sge_iq *, struct sge_fl *)
cpl_handler_t l2t_write_rpl_handlers[NUM_CPL_COOKIES]
static int free_eq_hwq(struct adapter *, struct vi_info *, struct sge_eq *)
static bool needs_vxlan_csum(struct mbuf *m)
static void set_txupdate_flags(struct sge_txq *txq, u_int avail, struct fw_eth_tx_pkt_wr *wr)
int t4_verify_chip_settings(struct adapter *sc)
void t4_sge_modunload(void)
static void init_eq(struct adapter *, struct sge_eq *, int, int, uint8_t, struct sge_iq *, char *)
static int get_segment_len(struct adapter *sc, struct sge_fl *fl, int plen)
void t4_register_fw_msg_handler(int type, fw_msg_handler_t h)
void t4_sge_sysctls(struct adapter *sc, struct sysctl_ctx_list *ctx, struct sysctl_oid_list *children)
cpl_handler_t t4_cpl_handler[NUM_CPL_CMDS]
static int service_iq(struct sge_iq *, int)
static void refill_sfl(void *)
static void t4_init_shared_cpl_handlers(void)
static void free_rxq(struct vi_info *, struct sge_rxq *)
static u_int reclaimable_tx_desc(struct sge_eq *)
void t4_intr_evt(void *arg)
static bool needs_outer_tcp_csum(struct mbuf *m)
static void ring_eq_db(struct adapter *, struct sge_eq *, u_int)
static int t4_tx_coalesce_gap
static void save_l2hdr(struct txpkts *txp, struct mbuf *m)
static u_int write_txpkt_wr(struct adapter *, struct sge_txq *, struct mbuf *, u_int)
static struct cluster_metadata * cl_metadata(struct fl_sdesc *sd)
int free_ring(struct adapter *sc, bus_dma_tag_t tag, bus_dmamap_t map, bus_addr_t pa, void *va)
static u_int total_available_tx_desc(struct sge_eq *)
static bool needs_vlan_insertion(struct mbuf *m)
int t4_teardown_vi_queues(struct vi_info *vi)
static int count_mbuf_ext_pgs(struct mbuf *m, int skip, vm_paddr_t *nextaddr)
static int alloc_ctrlq(struct adapter *, int)
static void get_pkt_gl(struct mbuf *, struct sglist *)
static void free_ctrlq(struct adapter *, int)
static u_int txpkt_len16(u_int, const u_int)
static u_int write_raw_wr(struct sge_txq *, void *, struct mbuf *, u_int)
static void set_mbuf_len16(struct mbuf *m, uint8_t len16)
static int t4_handle_wrerr_rpl(struct adapter *, const __be64 *)
static int sysctl_bufsizes(SYSCTL_HANDLER_ARGS)
static void add_txq_sysctls(struct vi_info *, struct sysctl_ctx_list *, struct sysctl_oid *, struct sge_txq *)
static int alloc_eq(struct adapter *, struct sge_eq *, struct sysctl_ctx_list *, struct sysctl_oid *)
static int fw4_ack_handler(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
static bool needs_l3_csum(struct mbuf *m)
static struct mbuf * get_fl_payload(struct adapter *, struct sge_fl *, uint32_t)
static void free_txq(struct vi_info *, struct sge_txq *)
static int safest_rx_cluster
CTASSERT(offsetof(struct cpl_fw4_msg, data)==offsetof(struct cpl_fw6_msg, data))
static void wrq_tx_drain(void *, int)
static int eth_eq_alloc(struct adapter *, struct vi_info *, struct sge_eq *)
static u_int imm_payload(u_int ndesc)
int t4_setup_adapter_queues(struct adapter *sc)
static u_int txpkts0_len16(u_int)
#define RX_COPY_THRESHOLD
static void write_gl_to_txd(struct sge_txq *, struct mbuf *, caddr_t *, int)
static void skip_fl_payload(struct adapter *sc, struct sge_fl *fl, int plen)
int tnl_cong(struct port_info *pi, int drop)
static void add_wrq_sysctls(struct sysctl_ctx_list *, struct sysctl_oid *, struct sge_wrq *)
int t4_destroy_dma_tag(struct adapter *sc)
static counter_u64_t defrags
static int abort_rpl_rss_handler(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
static uint64_t csum_to_ctrl(struct adapter *sc, struct mbuf *m)
static struct timeval txerr_ratecheck
static u_int write_txpkt_vm_wr(struct adapter *, struct sge_txq *, struct mbuf *)
fw_msg_handler_t t4_fw_msg_handler[NUM_FW6_TYPES]
static int refill_fl(struct adapter *, struct sge_fl *, int)
static void * write_tnl_lso_cpl(void *cpl, struct mbuf *m0)
SYSCTL_COUNTER_U64(_hw_cxgbe, OID_AUTO, pullups, CTLFLAG_RD, &pullups, "Number of mbuf pullups performed")
static const struct timeval txerr_interval
static u_int write_txpkts_wr(struct adapter *, struct sge_txq *)
static int hwsz_ok(struct adapter *sc, int hwsz)
static int ctrl_eq_alloc(struct adapter *, struct sge_eq *)
cpl_handler_t fw4_ack_handlers[NUM_CPL_COOKIES]
static int t4_tx_coalesce_pkts
static void copy_to_txd(struct sge_eq *, caddr_t, caddr_t *, int)
static int alloc_fwq(struct adapter *)
void t4_init_rx_buf_info(struct adapter *sc)
uint64_t t4_sge_extfree_refs(void)
static bool cmp_l2hdr(struct txpkts *txp, struct mbuf *m)
static int alloc_iq_fl_hwq(struct vi_info *, struct sge_iq *, struct sge_fl *)
static int alloc_wrq(struct adapter *, struct vi_info *, struct sge_wrq *, struct sysctl_ctx_list *, struct sysctl_oid *)
static counter_u64_t extfree_refs
static void rxb_free(struct mbuf *m)
static bool cannot_use_txpkts(struct mbuf *m)
void t4_intr_err(void *arg)
static void free_fwq(struct adapter *)
static int find_refill_source(struct adapter *, int, bool)
void t4_intr_all(void *arg)
void * start_wrq_wr(struct sge_wrq *wrq, int len16, struct wrq_cookie *cookie)
static int max_rx_payload(struct adapter *sc, struct ifnet *ifp, const bool ofld)
static uint64_t last_flit_to_ns(struct adapter *sc, uint64_t lf)
cpl_handler_t set_tcb_rpl_handlers[NUM_CPL_COOKIES]
static int l2t_write_rpl_handler(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
static __be64 get_flit(struct sglist_seg *, int, int)
static counter_u64_t extfree_rels
static void setup_pad_and_pack_boundaries(struct adapter *sc)
static bool needs_tso(struct mbuf *m)
static int mbuf_cflags(struct mbuf *m)
int alloc_ring(struct adapter *sc, size_t len, bus_dma_tag_t *tag, bus_dmamap_t *map, bus_addr_t *pa, void **va)
#define MAX_PACK_BOUNDARY
static void set_mbuf_cflags(struct mbuf *m, uint8_t flags)
static void set_mbuf_nsegs(struct mbuf *m, uint8_t nsegs)
void t4_update_fl_bufsize(struct ifnet *ifp)
void t4_register_cpl_handler(int opcode, cpl_handler_t h)
static u_int txpkt_vm_len16(u_int, const u_int)
static void oneseg_dma_callback(void *, bus_dma_segment_t *, int, int)
static int act_open_rpl_handler(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
static void drain_wrq_wr_list(struct adapter *, struct sge_wrq *)
static int alloc_eq_hwq(struct adapter *, struct vi_info *, struct sge_eq *)
int t4_teardown_adapter_queues(struct adapter *sc)
void t4_wrq_tx_locked(struct adapter *sc, struct sge_wrq *wrq, struct wrqe *wr)
static int largest_rx_cluster
static void add_iq_sysctls(struct sysctl_ctx_list *, struct sysctl_oid *, struct sge_iq *)
static void handle_eth_egr_update(struct adapter *sc, struct sge_eq *eq)
#define V_FW_EQ_CTRL_CMD_CMPLIQID(x)
#define V_FW_ETH_TX_EO_WR_TSOFF(x)
#define V_FW_EQ_CTRL_CMD_FBMIN(x)
@ FW_ETH_TX_EO_TYPE_TCPSEG
@ FW_ETH_TX_EO_TYPE_UDPSEG
#define G_FW_ERROR_CMD_MV(x)
#define V_FW_EQ_ETH_CMD_PFN(x)
#define G_FW_EQ_OFLD_CMD_EQID(x)
#define V_FW_EQ_ETH_CMD_FBMIN(x)
#define V_FW_EQ_OFLD_CMD_HOSTFCMODE(x)
#define F_FW_IQ_CMD_IQSTART
#define V_FW_ETH_TX_PKT_WR_IMMDLEN(x)
#define V_FW_EQ_ETH_CMD_PCIECHN(x)
#define V_FW_EQ_CTRL_CMD_PCIECHN(x)
#define F_FW_IQ_CMD_FL0FETCHRO
#define F_FW_EQ_ETH_CMD_AUTOEQUIQE
#define F_FW_IQ_CMD_FL0DATARO
#define V_FW_EQ_ETH_CMD_VFN(x)
#define F_FW_EQ_OFLD_CMD_ALLOC
#define V_FW_IQ_CMD_IQPCIECH(x)
#define G_FW_ERROR_CMD_FATAL(x)
#define V_FW_EQ_OFLD_CMD_EQSIZE(x)
#define V_FW_EQ_CTRL_CMD_HOSTFCMODE(x)
#define F_FW_IQ_CMD_FL0CONGEN
#define V_FW_EQ_OFLD_CMD_VFN(x)
#define F_FW_EQ_CTRL_CMD_ALLOC
#define F_FW_EQ_CTRL_CMD_EQSTART
#define V_FW_IQ_CMD_IQINTCNTTHRESH(x)
#define F_FW_IQ_CMD_ALLOC
#define V_FW_FLOWC_WR_NPARAMS(x)
#define V_FW_IQ_CMD_VIID(x)
#define V_FW_IQ_CMD_FL0HOSTFCMODE(x)
@ FW_ERROR_TYPE_EXCEPTION
#define V_FW_EQ_OFLD_CMD_PCIECHN(x)
#define V_FW_PARAMS_PARAM_YZ(x)
#define G_FW_ERROR_CMD_TYPE(x)
#define F_FW_EQ_ETH_CMD_AUTOEQUEQE
#define G_FW_ERROR_CMD_PFN(x)
#define G_FW_ERROR_CMD_VFN(x)
#define V_FW_IQ_CMD_FL0CNGCHMAP(x)
#define V_FW_EQ_CTRL_CMD_FBMAX(x)
#define F_FW_IQ_CMD_FL0CONGCIF
#define F_FW_IQ_CMD_FL0PADEN
#define F_FW_IQ_CMD_IQASYNCH
#define F_FW_EQ_ETH_CMD_EQSTART
#define V_FW_EQ_ETH_CMD_HOSTFCMODE(x)
#define V_FW_IQ_CMD_IQANDSTINDEX(x)
#define V_FW_IQ_CMD_PFN(x)
#define V_FW_EQ_ETH_CMD_EQSIZE(x)
#define V_FW_EQ_OFLD_CMD_CIDXFTHRESH(x)
#define V_FW_EQ_CTRL_CMD_EQSIZE(x)
#define F_FW_IQ_CMD_FL0PACKEN
@ FW_FLOWC_MNEM_SCHEDCLASS
#define V_FW_IQ_CMD_TYPE(x)
#define F_FW_EQ_CTRL_CMD_FETCHRO
#define V_FW_ETH_TX_EO_WR_IMMDLEN(x)
#define V_FW_PARAMS_MNEM(x)
#define F_FW_IQ_CMD_IQANDST
#define G_FW_EQ_CTRL_CMD_EQID(x)
#define V_FW_EQ_CTRL_CMD_IQID(x)
#define V_FW_ETH_TX_EO_WR_TSCLK(x)
#define V_FW_WR_FLOWID(x)
#define V_FW_EQ_ETH_CMD_FBMAX(x)
#define V_FW_IQ_CMD_IQESIZE(x)
#define V_FW_EQ_OFLD_CMD_FBMIN(x)
@ FW_FLOWC_MNEM_EOSTATE_ESTABLISHED
#define V_FW_EQ_ETH_CMD_VIID(x)
#define F_FW_IQ_CMD_IQGTSMODE
#define F_FW_IQ_CMD_IQFLINTCONGEN
#define F_FW_EQ_OFLD_CMD_EQSTART
#define V_FW_EQ_OFLD_CMD_FBMAX(x)
#define F_FW_EQ_ETH_CMD_FETCHRO
#define V_FW_EQ_CTRL_CMD_VFN(x)
#define V_FW_EQ_CTRL_CMD_CIDXFTHRESH(x)
#define V_FW_PARAMS_PARAM_X(x)
@ FW_PARAMS_PARAM_DMAQ_CONM_CTXT
#define F_FW_EQ_OFLD_CMD_FETCHRO
#define F_FW_EQ_ETH_CMD_ALLOC
#define G_FW_EQ_ETH_CMD_EQID(x)
#define G_FW_EQ_OFLD_CMD_PHYSEQID(x)
#define G_FW_EQ_ETH_CMD_PHYSEQID(x)
#define V_FW_EQ_OFLD_CMD_IQID(x)
#define V_FW_EQ_ETH_CMD_IQID(x)
#define V_FW_IQ_CMD_VFN(x)
#define V_FW_EQ_CTRL_CMD_PFN(x)
#define V_FW_IQ_CMD_FL0FBMAX(x)
#define V_FW_IQ_CMD_FL0FBMIN(x)
#define G_FW_EQ_CTRL_CMD_PHYSEQID(x)
#define V_FW_IQ_CMD_IQANUD(x)
#define FW_LEN16(fw_struct)
#define V_FW_EQ_OFLD_CMD_PFN(x)
struct fw_error_cmd::fw_error::fw_error_exception exception
struct fw_error_cmd::fw_error::fw_error_wr wr
struct fw_error_cmd::fw_error::fw_error_hwmodule hwmodule
struct fw_error_cmd::fw_error::fw_error_acl acl
struct fw_eth_tx_eo_wr::fw_eth_tx_eo::fw_eth_tx_eo_udpseg udpseg
struct fw_eth_tx_eo_wr::fw_eth_tx_eo::fw_eth_tx_eo_tcpseg tcpseg