Deleted Added
full compact
sfxge_tx.c (291924) sfxge_tx.c (294077)
1/*-
2 * Copyright (c) 2010-2015 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * This software was developed in part by Philip Paeps under contract for
6 * Solarflare Communications, Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 33 unchanged lines hidden (view full) ---

42 *
43 * So, event queue plus label mapping to Tx queue index is:
44 * if event queue index is 0, TxQ-index = TxQ-label * [0..SFXGE_TXQ_NTYPES)
45 * else TxQ-index = SFXGE_TXQ_NTYPES + EvQ-index - 1
46 * See sfxge_get_txq_by_label() sfxge_ev.c
47 */
48
49#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2010-2015 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * This software was developed in part by Philip Paeps under contract for
6 * Solarflare Communications, Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 33 unchanged lines hidden (view full) ---

42 *
43 * So, event queue plus label mapping to Tx queue index is:
44 * if event queue index is 0, TxQ-index = TxQ-label * [0..SFXGE_TXQ_NTYPES)
45 * else TxQ-index = SFXGE_TXQ_NTYPES + EvQ-index - 1
46 * See sfxge_get_txq_by_label() sfxge_ev.c
47 */
48
49#include <sys/cdefs.h>
50__FBSDID("$FreeBSD: head/sys/dev/sfxge/sfxge_tx.c 291924 2015-12-07 06:04:24Z arybchik $");
50__FBSDID("$FreeBSD: head/sys/dev/sfxge/sfxge_tx.c 294077 2016-01-15 06:25:26Z arybchik $");
51
52#include <sys/types.h>
53#include <sys/mbuf.h>
54#include <sys/smp.h>
55#include <sys/socket.h>
56#include <sys/sysctl.h>
57#include <sys/syslog.h>
51
52#include <sys/types.h>
53#include <sys/mbuf.h>
54#include <sys/smp.h>
55#include <sys/socket.h>
56#include <sys/sysctl.h>
57#include <sys/syslog.h>
58#include <sys/limits.h>
58
59#include <net/bpf.h>
60#include <net/ethernet.h>
61#include <net/if.h>
62#include <net/if_vlan_var.h>
63
64#include <netinet/in.h>
65#include <netinet/ip.h>

--- 25 unchanged lines hidden (view full) ---

91#define SFXGE_PARAM_TX_DPL_PUT_MAX SFXGE_PARAM(tx_dpl_put_max)
92static int sfxge_tx_dpl_put_max = SFXGE_TX_DPL_PUT_PKT_LIMIT_DEFAULT;
93TUNABLE_INT(SFXGE_PARAM_TX_DPL_PUT_MAX, &sfxge_tx_dpl_put_max);
94SYSCTL_INT(_hw_sfxge, OID_AUTO, tx_dpl_put_max, CTLFLAG_RDTUN,
95 &sfxge_tx_dpl_put_max, 0,
96 "Maximum number of any packets in deferred packet put-list");
97
98#define SFXGE_PARAM_TSO_FW_ASSISTED SFXGE_PARAM(tso_fw_assisted)
59
60#include <net/bpf.h>
61#include <net/ethernet.h>
62#include <net/if.h>
63#include <net/if_vlan_var.h>
64
65#include <netinet/in.h>
66#include <netinet/ip.h>

--- 25 unchanged lines hidden (view full) ---

92#define SFXGE_PARAM_TX_DPL_PUT_MAX SFXGE_PARAM(tx_dpl_put_max)
93static int sfxge_tx_dpl_put_max = SFXGE_TX_DPL_PUT_PKT_LIMIT_DEFAULT;
94TUNABLE_INT(SFXGE_PARAM_TX_DPL_PUT_MAX, &sfxge_tx_dpl_put_max);
95SYSCTL_INT(_hw_sfxge, OID_AUTO, tx_dpl_put_max, CTLFLAG_RDTUN,
96 &sfxge_tx_dpl_put_max, 0,
97 "Maximum number of any packets in deferred packet put-list");
98
99#define SFXGE_PARAM_TSO_FW_ASSISTED SFXGE_PARAM(tso_fw_assisted)
99static int sfxge_tso_fw_assisted = 1;
100static int sfxge_tso_fw_assisted = (SFXGE_FATSOV1 | SFXGE_FATSOV2);
100TUNABLE_INT(SFXGE_PARAM_TSO_FW_ASSISTED, &sfxge_tso_fw_assisted);
101SYSCTL_INT(_hw_sfxge, OID_AUTO, tso_fw_assisted, CTLFLAG_RDTUN,
102 &sfxge_tso_fw_assisted, 0,
101TUNABLE_INT(SFXGE_PARAM_TSO_FW_ASSISTED, &sfxge_tso_fw_assisted);
102SYSCTL_INT(_hw_sfxge, OID_AUTO, tso_fw_assisted, CTLFLAG_RDTUN,
103 &sfxge_tso_fw_assisted, 0,
103 "Use FW-assisted TSO if supported by NIC firmware");
104 "Bitmask of FW-assisted TSO allowed to use if supported by NIC firmware");
104
105
106static const struct {
107 const char *name;
108 size_t offset;
109} sfxge_tx_stats[] = {
110#define SFXGE_TX_STAT(name, member) \
111 { #name, offsetof(struct sfxge_txq, member) }

--- 733 unchanged lines hidden (view full) ---

845 * still faster than segmenting in the stack.
846 */
847
848struct sfxge_tso_state {
849 /* Output position */
850 unsigned out_len; /* Remaining length in current segment */
851 unsigned seqnum; /* Current sequence number */
852 unsigned packet_space; /* Remaining space in current packet */
105
106
107static const struct {
108 const char *name;
109 size_t offset;
110} sfxge_tx_stats[] = {
111#define SFXGE_TX_STAT(name, member) \
112 { #name, offsetof(struct sfxge_txq, member) }

--- 733 unchanged lines hidden (view full) ---

846 * still faster than segmenting in the stack.
847 */
848
849struct sfxge_tso_state {
850 /* Output position */
851 unsigned out_len; /* Remaining length in current segment */
852 unsigned seqnum; /* Current sequence number */
853 unsigned packet_space; /* Remaining space in current packet */
854 unsigned segs_space; /* Remaining number of DMA segments
855 for the packet (FATSOv2 only) */
853
854 /* Input position */
855 uint64_t dma_addr; /* DMA address of current position */
856 unsigned in_len; /* Remaining length in current mbuf */
857
858 const struct mbuf *mbuf; /* Input mbuf (head of chain) */
859 u_short protocol; /* Network protocol (after VLAN decap) */
860 ssize_t nh_off; /* Offset of network header */

--- 86 unchanged lines hidden (view full) ---

947{
948 const efx_nic_cfg_t *encp = efx_nic_cfg_get(txq->sc->enp);
949#if !SFXGE_TX_PARSE_EARLY
950 struct ether_header *eh = mtod(mbuf, struct ether_header *);
951 const struct tcphdr *th;
952 struct tcphdr th_copy;
953#endif
954
856
857 /* Input position */
858 uint64_t dma_addr; /* DMA address of current position */
859 unsigned in_len; /* Remaining length in current mbuf */
860
861 const struct mbuf *mbuf; /* Input mbuf (head of chain) */
862 u_short protocol; /* Network protocol (after VLAN decap) */
863 ssize_t nh_off; /* Offset of network header */

--- 86 unchanged lines hidden (view full) ---

950{
951 const efx_nic_cfg_t *encp = efx_nic_cfg_get(txq->sc->enp);
952#if !SFXGE_TX_PARSE_EARLY
953 struct ether_header *eh = mtod(mbuf, struct ether_header *);
954 const struct tcphdr *th;
955 struct tcphdr th_copy;
956#endif
957
955 tso->fw_assisted = txq->sc->tso_fw_assisted;
958 tso->fw_assisted = txq->tso_fw_assisted;
956 tso->mbuf = mbuf;
957
958 /* Find network protocol and header */
959#if !SFXGE_TX_PARSE_EARLY
960 tso->protocol = eh->ether_type;
961 if (tso->protocol == htons(ETHERTYPE_VLAN)) {
962 struct ether_vlan_header *veh =
963 mtod(mbuf, struct ether_vlan_header *);

--- 90 unchanged lines hidden (view full) ---

1054 * of fragment or end-of-packet. Return 0 on success, 1 if not enough
1055 * space.
1056 */
1057static void tso_fill_packet_with_fragment(struct sfxge_txq *txq,
1058 struct sfxge_tso_state *tso)
1059{
1060 efx_desc_t *desc;
1061 int n;
959 tso->mbuf = mbuf;
960
961 /* Find network protocol and header */
962#if !SFXGE_TX_PARSE_EARLY
963 tso->protocol = eh->ether_type;
964 if (tso->protocol == htons(ETHERTYPE_VLAN)) {
965 struct ether_vlan_header *veh =
966 mtod(mbuf, struct ether_vlan_header *);

--- 90 unchanged lines hidden (view full) ---

1057 * of fragment or end-of-packet. Return 0 on success, 1 if not enough
1058 * space.
1059 */
1060static void tso_fill_packet_with_fragment(struct sfxge_txq *txq,
1061 struct sfxge_tso_state *tso)
1062{
1063 efx_desc_t *desc;
1064 int n;
1065 uint64_t dma_addr = tso->dma_addr;
1066 boolean_t eop;
1062
1063 if (tso->in_len == 0 || tso->packet_space == 0)
1064 return;
1065
1066 KASSERT(tso->in_len > 0, ("TSO input length went negative"));
1067 KASSERT(tso->packet_space > 0, ("TSO packet space went negative"));
1068
1067
1068 if (tso->in_len == 0 || tso->packet_space == 0)
1069 return;
1070
1071 KASSERT(tso->in_len > 0, ("TSO input length went negative"));
1072 KASSERT(tso->packet_space > 0, ("TSO packet space went negative"));
1073
1069 n = min(tso->in_len, tso->packet_space);
1074 if (tso->fw_assisted & SFXGE_FATSOV2) {
1075 n = tso->in_len;
1076 tso->out_len -= n;
1077 tso->seqnum += n;
1078 tso->in_len = 0;
1079 if (n < tso->packet_space) {
1080 tso->packet_space -= n;
1081 tso->segs_space--;
1082 } else {
1083 tso->packet_space = tso->seg_size -
1084 (n - tso->packet_space) % tso->seg_size;
1085 tso->segs_space =
1086 EFX_TX_FATSOV2_DMA_SEGS_PER_PKT_MAX - 1 -
1087 (tso->packet_space != tso->seg_size);
1088 }
1089 } else {
1090 n = min(tso->in_len, tso->packet_space);
1091 tso->packet_space -= n;
1092 tso->out_len -= n;
1093 tso->dma_addr += n;
1094 tso->in_len -= n;
1095 }
1070
1096
1071 tso->packet_space -= n;
1072 tso->out_len -= n;
1073 tso->in_len -= n;
1097 /*
1098 * It is OK to use binary OR below to avoid extra branching
1099 * since all conditions may always be checked.
1100 */
1101 eop = (tso->out_len == 0) | (tso->packet_space == 0) |
1102 (tso->segs_space == 0);
1074
1075 desc = &txq->pend_desc[txq->n_pend_desc++];
1103
1104 desc = &txq->pend_desc[txq->n_pend_desc++];
1076 efx_tx_qdesc_dma_create(txq->common,
1077 tso->dma_addr,
1078 n,
1079 tso->out_len == 0 || tso->packet_space == 0,
1080 desc);
1081
1082 tso->dma_addr += n;
1105 efx_tx_qdesc_dma_create(txq->common, dma_addr, n, eop, desc);
1083}
1084
1085/* Callback from bus_dmamap_load() for long TSO headers. */
1086static void tso_map_long_header(void *dma_addr_ret,
1087 bus_dma_segment_t *segs, int nseg,
1088 int error)
1089{
1090 *(uint64_t *)dma_addr_ret = ((__predict_true(error == 0) &&

--- 16 unchanged lines hidden (view full) ---

1107 unsigned ip_length;
1108 caddr_t header;
1109 uint64_t dma_addr;
1110 bus_dmamap_t map;
1111 efx_desc_t *desc;
1112 int rc;
1113
1114 if (tso->fw_assisted) {
1106}
1107
1108/* Callback from bus_dmamap_load() for long TSO headers. */
1109static void tso_map_long_header(void *dma_addr_ret,
1110 bus_dma_segment_t *segs, int nseg,
1111 int error)
1112{
1113 *(uint64_t *)dma_addr_ret = ((__predict_true(error == 0) &&

--- 16 unchanged lines hidden (view full) ---

1130 unsigned ip_length;
1131 caddr_t header;
1132 uint64_t dma_addr;
1133 bus_dmamap_t map;
1134 efx_desc_t *desc;
1135 int rc;
1136
1137 if (tso->fw_assisted) {
1115 uint8_t tcp_flags = tso->tcp_flags;
1138 if (tso->fw_assisted & SFXGE_FATSOV2) {
1139 /* Add 2 FATSOv2 option descriptors */
1140 desc = &txq->pend_desc[txq->n_pend_desc];
1141 efx_tx_qdesc_tso2_create(txq->common,
1142 tso->packet_id,
1143 tso->seqnum,
1144 tso->seg_size,
1145 desc,
1146 EFX_TX_FATSOV2_OPT_NDESCS);
1147 desc += EFX_TX_FATSOV2_OPT_NDESCS;
1148 txq->n_pend_desc += EFX_TX_FATSOV2_OPT_NDESCS;
1149 KASSERT(txq->stmp[id].flags == 0, ("stmp flags are not 0"));
1150 id = (id + EFX_TX_FATSOV2_OPT_NDESCS) & txq->ptr_mask;
1116
1151
1117 if (tso->out_len > tso->seg_size)
1118 tcp_flags &= ~(TH_FIN | TH_PUSH);
1152 tso->segs_space =
1153 EFX_TX_FATSOV2_DMA_SEGS_PER_PKT_MAX - 1;
1154 } else {
1155 uint8_t tcp_flags = tso->tcp_flags;
1119
1156
1120 /* TSO option descriptor */
1121 desc = &txq->pend_desc[txq->n_pend_desc++];
1122 efx_tx_qdesc_tso_create(txq->common,
1123 tso->packet_id,
1124 tso->seqnum,
1125 tcp_flags,
1126 desc++);
1127 KASSERT(txq->stmp[id].flags == 0, ("stmp flags are not 0"));
1128 id = (id + 1) & txq->ptr_mask;
1157 if (tso->out_len > tso->seg_size)
1158 tcp_flags &= ~(TH_FIN | TH_PUSH);
1129
1159
1160 /* Add FATSOv1 option descriptor */
1161 desc = &txq->pend_desc[txq->n_pend_desc++];
1162 efx_tx_qdesc_tso_create(txq->common,
1163 tso->packet_id,
1164 tso->seqnum,
1165 tcp_flags,
1166 desc++);
1167 KASSERT(txq->stmp[id].flags == 0, ("stmp flags are not 0"));
1168 id = (id + 1) & txq->ptr_mask;
1169
1170 tso->seqnum += tso->seg_size;
1171 tso->segs_space = UINT_MAX;
1172 }
1173
1130 /* Header DMA descriptor */
1131 *desc = tso->header_desc;
1132 txq->n_pend_desc++;
1133 KASSERT(txq->stmp[id].flags == 0, ("stmp flags are not 0"));
1134 id = (id + 1) & txq->ptr_mask;
1174 /* Header DMA descriptor */
1175 *desc = tso->header_desc;
1176 txq->n_pend_desc++;
1177 KASSERT(txq->stmp[id].flags == 0, ("stmp flags are not 0"));
1178 id = (id + 1) & txq->ptr_mask;
1135
1136 tso->seqnum += tso->seg_size;
1137 } else {
1138 /* Allocate a DMA-mapped header buffer. */
1139 if (__predict_true(tso->header_len <= TSOH_STD_SIZE)) {
1140 unsigned int page_index = (id / 2) / TSOH_PER_PAGE;
1141 unsigned int buf_index = (id / 2) % TSOH_PER_PAGE;
1142
1143 header = (txq->tsoh_buffer[page_index].esm_base +
1144 buf_index * TSOH_STD_SIZE);

--- 65 unchanged lines hidden (view full) ---

1210 /* Form a descriptor for this header. */
1211 desc = &txq->pend_desc[txq->n_pend_desc++];
1212 efx_tx_qdesc_dma_create(txq->common,
1213 dma_addr,
1214 tso->header_len,
1215 0,
1216 desc);
1217 id = (id + 1) & txq->ptr_mask;
1179 } else {
1180 /* Allocate a DMA-mapped header buffer. */
1181 if (__predict_true(tso->header_len <= TSOH_STD_SIZE)) {
1182 unsigned int page_index = (id / 2) / TSOH_PER_PAGE;
1183 unsigned int buf_index = (id / 2) % TSOH_PER_PAGE;
1184
1185 header = (txq->tsoh_buffer[page_index].esm_base +
1186 buf_index * TSOH_STD_SIZE);

--- 65 unchanged lines hidden (view full) ---

1252 /* Form a descriptor for this header. */
1253 desc = &txq->pend_desc[txq->n_pend_desc++];
1254 efx_tx_qdesc_dma_create(txq->common,
1255 dma_addr,
1256 tso->header_len,
1257 0,
1258 desc);
1259 id = (id + 1) & txq->ptr_mask;
1260
1261 tso->segs_space = UINT_MAX;
1218 }
1219 tso->packet_space = tso->seg_size;
1220 txq->tso_packets++;
1221 *idp = id;
1222
1223 return (0);
1224}
1225

--- 33 unchanged lines hidden (view full) ---

1259 if (n_dma_seg == 0)
1260 break;
1261 ++dma_seg;
1262 tso.in_len = dma_seg->ds_len;
1263 tso.dma_addr = dma_seg->ds_addr;
1264 }
1265
1266 /* End of packet? */
1262 }
1263 tso->packet_space = tso->seg_size;
1264 txq->tso_packets++;
1265 *idp = id;
1266
1267 return (0);
1268}
1269

--- 33 unchanged lines hidden (view full) ---

1303 if (n_dma_seg == 0)
1304 break;
1305 ++dma_seg;
1306 tso.in_len = dma_seg->ds_len;
1307 tso.dma_addr = dma_seg->ds_addr;
1308 }
1309
1310 /* End of packet? */
1267 if (tso.packet_space == 0) {
1311 if ((tso.packet_space == 0) | (tso.segs_space == 0)) {
1312 unsigned int n_fatso_opt_desc =
1313 (tso.fw_assisted & SFXGE_FATSOV2) ?
1314 EFX_TX_FATSOV2_OPT_NDESCS :
1315 (tso.fw_assisted & SFXGE_FATSOV1) ? 1 : 0;
1316
1268 /* If the queue is now full due to tiny MSS,
1269 * or we can't create another header, discard
1270 * the remainder of the input mbuf but do not
1271 * roll back the work we have done.
1272 */
1317 /* If the queue is now full due to tiny MSS,
1318 * or we can't create another header, discard
1319 * the remainder of the input mbuf but do not
1320 * roll back the work we have done.
1321 */
1273 if (txq->n_pend_desc + tso.fw_assisted +
1274 1 /* header */ + n_dma_seg >
1275 txq->max_pkt_desc) {
1322 if (txq->n_pend_desc + n_fatso_opt_desc +
1323 1 /* header */ + n_dma_seg > txq->max_pkt_desc) {
1276 txq->tso_pdrop_too_many++;
1277 break;
1278 }
1279 if (__predict_false(tso_start_new_packet(txq, &tso,
1280 &id))) {
1281 txq->tso_pdrop_no_rsrc++;
1282 break;
1283 }

--- 118 unchanged lines hidden (view full) ---

1402
1403 efx_sram_buf_tbl_clear(sc->enp, txq->buf_base_id,
1404 EFX_TXQ_NBUFS(sc->txq_entries));
1405
1406 SFXGE_EVQ_UNLOCK(evq);
1407 SFXGE_TXQ_UNLOCK(txq);
1408}
1409
1324 txq->tso_pdrop_too_many++;
1325 break;
1326 }
1327 if (__predict_false(tso_start_new_packet(txq, &tso,
1328 &id))) {
1329 txq->tso_pdrop_no_rsrc++;
1330 break;
1331 }

--- 118 unchanged lines hidden (view full) ---

1450
1451 efx_sram_buf_tbl_clear(sc->enp, txq->buf_base_id,
1452 EFX_TXQ_NBUFS(sc->txq_entries));
1453
1454 SFXGE_EVQ_UNLOCK(evq);
1455 SFXGE_TXQ_UNLOCK(txq);
1456}
1457
1458/*
1459 * Estimate maximum number of Tx descriptors required for TSO packet.
1460 * With minimum MSS and maximum mbuf length we might need more (even
1461 * than a ring-ful of descriptors), but this should not happen in
1462 * practice except due to deliberate attack. In that case we will
1463 * truncate the output at a packet boundary.
1464 */
1465static unsigned int
1466sfxge_tx_max_pkt_desc(const struct sfxge_softc *sc, enum sfxge_txq_type type,
1467 unsigned int tso_fw_assisted)
1468{
1469 /* One descriptor for every input fragment */
1470 unsigned int max_descs = SFXGE_TX_MAPPING_MAX_SEG;
1471 unsigned int sw_tso_max_descs;
1472 unsigned int fa_tso_v1_max_descs = 0;
1473 unsigned int fa_tso_v2_max_descs = 0;
1474
1475 /* VLAN tagging Tx option descriptor may be required */
1476 if (efx_nic_cfg_get(sc->enp)->enc_hw_tx_insert_vlan_enabled)
1477 max_descs++;
1478
1479 if (type == SFXGE_TXQ_IP_TCP_UDP_CKSUM) {
1480 /*
1481 * Plus header and payload descriptor for each output segment.
1482 * Minus one since header fragment is already counted.
1483 * Even if FATSO is used, we should be ready to fallback
1484 * to do it in the driver.
1485 */
1486 sw_tso_max_descs = SFXGE_TSO_MAX_SEGS * 2 - 1;
1487
1488 /* FW assisted TSOv1 requires one more descriptor per segment
1489 * in comparison to SW TSO */
1490 if (tso_fw_assisted & SFXGE_FATSOV1)
1491 fa_tso_v1_max_descs =
1492 sw_tso_max_descs + SFXGE_TSO_MAX_SEGS;
1493
1494 /* FW assisted TSOv2 requires 3 (2 FATSO plus header) extra
1495 * descriptors per superframe limited by number of DMA fetches
1496 * per packet. The first packet header is already counted.
1497 */
1498 if (tso_fw_assisted & SFXGE_FATSOV2) {
1499 fa_tso_v2_max_descs =
1500 howmany(SFXGE_TX_MAPPING_MAX_SEG,
1501 EFX_TX_FATSOV2_DMA_SEGS_PER_PKT_MAX - 1) *
1502 (EFX_TX_FATSOV2_OPT_NDESCS + 1) - 1;
1503 }
1504
1505 max_descs += MAX(sw_tso_max_descs,
1506 MAX(fa_tso_v1_max_descs, fa_tso_v2_max_descs));
1507 }
1508
1509 return (max_descs);
1510}
1511
1410static int
1411sfxge_tx_qstart(struct sfxge_softc *sc, unsigned int index)
1412{
1413 struct sfxge_txq *txq;
1414 efsys_mem_t *esmp;
1415 uint16_t flags;
1512static int
1513sfxge_tx_qstart(struct sfxge_softc *sc, unsigned int index)
1514{
1515 struct sfxge_txq *txq;
1516 efsys_mem_t *esmp;
1517 uint16_t flags;
1518 unsigned int tso_fw_assisted;
1416 struct sfxge_evq *evq;
1417 unsigned int desc_index;
1418 int rc;
1419
1420 SFXGE_ADAPTER_LOCK_ASSERT_OWNED(sc);
1421
1422 txq = sc->txq[index];
1423 esmp = &txq->mem;

--- 5 unchanged lines hidden (view full) ---

1429 ("evq->init_state != SFXGE_EVQ_STARTED"));
1430
1431 /* Program the buffer table. */
1432 if ((rc = efx_sram_buf_tbl_set(sc->enp, txq->buf_base_id, esmp,
1433 EFX_TXQ_NBUFS(sc->txq_entries))) != 0)
1434 return (rc);
1435
1436 /* Determine the kind of queue we are creating. */
1519 struct sfxge_evq *evq;
1520 unsigned int desc_index;
1521 int rc;
1522
1523 SFXGE_ADAPTER_LOCK_ASSERT_OWNED(sc);
1524
1525 txq = sc->txq[index];
1526 esmp = &txq->mem;

--- 5 unchanged lines hidden (view full) ---

1532 ("evq->init_state != SFXGE_EVQ_STARTED"));
1533
1534 /* Program the buffer table. */
1535 if ((rc = efx_sram_buf_tbl_set(sc->enp, txq->buf_base_id, esmp,
1536 EFX_TXQ_NBUFS(sc->txq_entries))) != 0)
1537 return (rc);
1538
1539 /* Determine the kind of queue we are creating. */
1540 tso_fw_assisted = 0;
1437 switch (txq->type) {
1438 case SFXGE_TXQ_NON_CKSUM:
1439 flags = 0;
1440 break;
1441 case SFXGE_TXQ_IP_CKSUM:
1442 flags = EFX_TXQ_CKSUM_IPV4;
1443 break;
1444 case SFXGE_TXQ_IP_TCP_UDP_CKSUM:
1445 flags = EFX_TXQ_CKSUM_IPV4 | EFX_TXQ_CKSUM_TCPUDP;
1541 switch (txq->type) {
1542 case SFXGE_TXQ_NON_CKSUM:
1543 flags = 0;
1544 break;
1545 case SFXGE_TXQ_IP_CKSUM:
1546 flags = EFX_TXQ_CKSUM_IPV4;
1547 break;
1548 case SFXGE_TXQ_IP_TCP_UDP_CKSUM:
1549 flags = EFX_TXQ_CKSUM_IPV4 | EFX_TXQ_CKSUM_TCPUDP;
1550 tso_fw_assisted = sc->tso_fw_assisted;
1551 if (tso_fw_assisted & SFXGE_FATSOV2)
1552 flags |= EFX_TXQ_FATSOV2;
1446 break;
1447 default:
1448 KASSERT(0, ("Impossible TX queue"));
1449 flags = 0;
1450 break;
1451 }
1452
1453 /* Create the common code transmit queue. */
1454 if ((rc = efx_tx_qcreate(sc->enp, index, txq->type, esmp,
1455 sc->txq_entries, txq->buf_base_id, flags, evq->common,
1553 break;
1554 default:
1555 KASSERT(0, ("Impossible TX queue"));
1556 flags = 0;
1557 break;
1558 }
1559
1560 /* Create the common code transmit queue. */
1561 if ((rc = efx_tx_qcreate(sc->enp, index, txq->type, esmp,
1562 sc->txq_entries, txq->buf_base_id, flags, evq->common,
1456 &txq->common, &desc_index)) != 0)
1457 goto fail;
1563 &txq->common, &desc_index)) != 0) {
1564 /* Retry if no FATSOv2 resources, otherwise fail */
1565 if ((rc != ENOSPC) || (~flags & EFX_TXQ_FATSOV2))
1566 goto fail;
1458
1567
1568 /* Looks like all FATSOv2 contexts are used */
1569 flags &= ~EFX_TXQ_FATSOV2;
1570 tso_fw_assisted &= ~SFXGE_FATSOV2;
1571 if ((rc = efx_tx_qcreate(sc->enp, index, txq->type, esmp,
1572 sc->txq_entries, txq->buf_base_id, flags, evq->common,
1573 &txq->common, &desc_index)) != 0)
1574 goto fail;
1575 }
1576
1459 /* Initialise queue descriptor indexes */
1460 txq->added = txq->pending = txq->completed = txq->reaped = desc_index;
1461
1462 SFXGE_TXQ_LOCK(txq);
1463
1464 /* Enable the transmit queue. */
1465 efx_tx_qenable(txq->common);
1466
1467 txq->init_state = SFXGE_TXQ_STARTED;
1468 txq->flush_state = SFXGE_FLUSH_REQUIRED;
1577 /* Initialise queue descriptor indexes */
1578 txq->added = txq->pending = txq->completed = txq->reaped = desc_index;
1579
1580 SFXGE_TXQ_LOCK(txq);
1581
1582 /* Enable the transmit queue. */
1583 efx_tx_qenable(txq->common);
1584
1585 txq->init_state = SFXGE_TXQ_STARTED;
1586 txq->flush_state = SFXGE_FLUSH_REQUIRED;
1587 txq->tso_fw_assisted = tso_fw_assisted;
1469
1588
1589 txq->max_pkt_desc = sfxge_tx_max_pkt_desc(sc, txq->type,
1590 tso_fw_assisted);
1591
1470 SFXGE_TXQ_UNLOCK(txq);
1471
1472 return (0);
1473
1474fail:
1475 efx_sram_buf_tbl_clear(sc->enp, txq->buf_base_id,
1476 EFX_TXQ_NBUFS(sc->txq_entries));
1477 return (rc);

--- 91 unchanged lines hidden (view full) ---

1569
1570 sc->txq[index] = NULL;
1571
1572 SFXGE_TXQ_LOCK_DESTROY(txq);
1573
1574 free(txq, M_SFXGE);
1575}
1576
1592 SFXGE_TXQ_UNLOCK(txq);
1593
1594 return (0);
1595
1596fail:
1597 efx_sram_buf_tbl_clear(sc->enp, txq->buf_base_id,
1598 EFX_TXQ_NBUFS(sc->txq_entries));
1599 return (rc);

--- 91 unchanged lines hidden (view full) ---

1691
1692 sc->txq[index] = NULL;
1693
1694 SFXGE_TXQ_LOCK_DESTROY(txq);
1695
1696 free(txq, M_SFXGE);
1697}
1698
1577/*
1578 * Estimate maximum number of Tx descriptors required for TSO packet.
1579 * With minimum MSS and maximum mbuf length we might need more (even
1580 * than a ring-ful of descriptors), but this should not happen in
1581 * practice except due to deliberate attack. In that case we will
1582 * truncate the output at a packet boundary.
1583 */
1584static unsigned int
1585sfxge_tx_max_pkt_desc(const struct sfxge_softc *sc, enum sfxge_txq_type type)
1586{
1587 /* One descriptor for every input fragment */
1588 unsigned int max_descs = SFXGE_TX_MAPPING_MAX_SEG;
1589
1590 /* VLAN tagging Tx option descriptor may be required */
1591 if (efx_nic_cfg_get(sc->enp)->enc_hw_tx_insert_vlan_enabled)
1592 max_descs++;
1593
1594 if (type == SFXGE_TXQ_IP_TCP_UDP_CKSUM) {
1595 /*
1596 * Plus header and payload descriptor for each output segment.
1597 * Minus one since header fragment is already counted.
1598 */
1599 max_descs += SFXGE_TSO_MAX_SEGS * 2 - 1;
1600
1601 /* FW assisted TSO requires one more descriptor per segment */
1602 if (sc->tso_fw_assisted)
1603 max_descs += SFXGE_TSO_MAX_SEGS;
1604 }
1605
1606 return (max_descs);
1607}
1608
1609static int
1610sfxge_tx_qinit(struct sfxge_softc *sc, unsigned int txq_index,
1611 enum sfxge_txq_type type, unsigned int evq_index)
1612{
1613 char name[16];
1614 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
1615 struct sysctl_oid *txq_node;
1616 struct sfxge_txq *txq;

--- 113 unchanged lines hidden (view full) ---

1730 goto fail_txq_stat_init;
1731
1732 txq->type = type;
1733 txq->evq_index = evq_index;
1734 txq->txq_index = txq_index;
1735 txq->init_state = SFXGE_TXQ_INITIALIZED;
1736 txq->hw_vlan_tci = 0;
1737
1699static int
1700sfxge_tx_qinit(struct sfxge_softc *sc, unsigned int txq_index,
1701 enum sfxge_txq_type type, unsigned int evq_index)
1702{
1703 char name[16];
1704 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
1705 struct sysctl_oid *txq_node;
1706 struct sfxge_txq *txq;

--- 113 unchanged lines hidden (view full) ---

1820 goto fail_txq_stat_init;
1821
1822 txq->type = type;
1823 txq->evq_index = evq_index;
1824 txq->txq_index = txq_index;
1825 txq->init_state = SFXGE_TXQ_INITIALIZED;
1826 txq->hw_vlan_tci = 0;
1827
1738 txq->max_pkt_desc = sfxge_tx_max_pkt_desc(sc, type);
1739
1740 return (0);
1741
1742fail_txq_stat_init:
1743fail_dpl_node:
1744fail_tx_dpl_put_max:
1745fail_tx_dpl_get_max:
1746fail3:
1747fail_txq_node:

--- 93 unchanged lines hidden (view full) ---

1841 intr = &sc->intr;
1842
1843 KASSERT(intr->state == SFXGE_INTR_INITIALIZED,
1844 ("intr->state != SFXGE_INTR_INITIALIZED"));
1845
1846 sc->txq_count = SFXGE_TXQ_NTYPES - 1 + sc->intr.n_alloc;
1847
1848 sc->tso_fw_assisted = sfxge_tso_fw_assisted;
1828 return (0);
1829
1830fail_txq_stat_init:
1831fail_dpl_node:
1832fail_tx_dpl_put_max:
1833fail_tx_dpl_get_max:
1834fail3:
1835fail_txq_node:

--- 93 unchanged lines hidden (view full) ---

1929 intr = &sc->intr;
1930
1931 KASSERT(intr->state == SFXGE_INTR_INITIALIZED,
1932 ("intr->state != SFXGE_INTR_INITIALIZED"));
1933
1934 sc->txq_count = SFXGE_TXQ_NTYPES - 1 + sc->intr.n_alloc;
1935
1936 sc->tso_fw_assisted = sfxge_tso_fw_assisted;
1849 if (sc->tso_fw_assisted)
1850 sc->tso_fw_assisted =
1851 (encp->enc_features & EFX_FEATURE_FW_ASSISTED_TSO) &&
1852 (encp->enc_fw_assisted_tso_enabled);
1937 if ((~encp->enc_features & EFX_FEATURE_FW_ASSISTED_TSO) ||
1938 (!encp->enc_fw_assisted_tso_enabled))
1939 sc->tso_fw_assisted &= ~SFXGE_FATSOV1;
1940 if ((~encp->enc_features & EFX_FEATURE_FW_ASSISTED_TSO_V2) ||
1941 (!encp->enc_fw_assisted_tso_v2_enabled))
1942 sc->tso_fw_assisted &= ~SFXGE_FATSOV2;
1853
1854 sc->txqs_node = SYSCTL_ADD_NODE(
1855 device_get_sysctl_ctx(sc->dev),
1856 SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)),
1857 OID_AUTO, "txq", CTLFLAG_RD, NULL, "Tx queues");
1858 if (sc->txqs_node == NULL) {
1859 rc = ENOMEM;
1860 goto fail_txq_node;

--- 37 unchanged lines hidden ---
1943
1944 sc->txqs_node = SYSCTL_ADD_NODE(
1945 device_get_sysctl_ctx(sc->dev),
1946 SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)),
1947 OID_AUTO, "txq", CTLFLAG_RD, NULL, "Tx queues");
1948 if (sc->txqs_node == NULL) {
1949 rc = ENOMEM;
1950 goto fail_txq_node;

--- 37 unchanged lines hidden ---