Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sfc: create inner-csum queues on EF10 if supported

If the MC reports the VXLAN_NVGRE datapath capability, then these queues
can be used for checksum offload of encapsulated packets.

Signed-off-by: Edward Cree <ecree@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Edward Cree and committed by
David S. Miller
85d43fdb 044588b9

+28 -11
+16 -7
drivers/net/ethernet/sfc/ef10.c
··· 601 601 efx_ef10_read_licensed_features(efx); 602 602 603 603 /* We can have one VI for each vi_stride-byte region. 604 - * However, until we use TX option descriptors we need two TX queues 605 - * per channel. 604 + * However, until we use TX option descriptors we need up to four 605 + * TX queues per channel for different checksumming combinations. 606 606 */ 607 - efx->tx_queues_per_channel = 2; 607 + if (nic_data->datapath_caps & 608 + (1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN)) 609 + efx->tx_queues_per_channel = 4; 610 + else 611 + efx->tx_queues_per_channel = 2; 608 612 efx->max_vis = efx_ef10_mem_map_size(efx) / efx->vi_stride; 609 613 if (!efx->max_vis) { 610 614 netif_err(efx, drv, efx->net_dev, "error determining max VIs\n"); ··· 2150 2146 2151 2147 static int efx_ef10_tx_probe(struct efx_tx_queue *tx_queue) 2152 2148 { 2153 - tx_queue->type = tx_queue->label & EFX_TXQ_TYPE_OUTER_CSUM; 2149 + /* low two bits of label are what we want for type */ 2150 + BUILD_BUG_ON((EFX_TXQ_TYPE_OUTER_CSUM | EFX_TXQ_TYPE_INNER_CSUM) != 3); 2151 + tx_queue->type = tx_queue->label & 3; 2154 2152 return efx_nic_alloc_buffer(tx_queue->efx, &tx_queue->txd.buf, 2155 2153 (tx_queue->ptr_mask + 1) * 2156 2154 sizeof(efx_qword_t), ··· 2262 2256 static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue) 2263 2257 { 2264 2258 bool csum_offload = tx_queue->type & EFX_TXQ_TYPE_OUTER_CSUM; 2259 + bool inner_csum = tx_queue->type & EFX_TXQ_TYPE_INNER_CSUM; 2265 2260 struct efx_channel *channel = tx_queue->channel; 2266 2261 struct efx_nic *efx = tx_queue->efx; 2267 2262 struct efx_ef10_nic_data *nic_data; ··· 2289 2282 * TSOv2 cannot be used with Hardware timestamping, and is never needed 2290 2283 * for XDP tx. 2291 2284 */ 2292 - if (csum_offload && (nic_data->datapath_caps2 & 2285 + if ((csum_offload || inner_csum) && (nic_data->datapath_caps2 & 2293 2286 (1 << MC_CMD_GET_CAPABILITIES_V2_OUT_TX_TSO_V2_LBN)) && 2294 2287 !tx_queue->timestamping && !tx_queue->xdp_tx) { 2295 2288 tso_v2 = true; ··· 2310 2303 tx_queue->buffer[0].flags = EFX_TX_BUF_OPTION; 2311 2304 tx_queue->insert_count = 1; 2312 2305 txd = efx_tx_desc(tx_queue, 0); 2313 - EFX_POPULATE_QWORD_5(*txd, 2306 + EFX_POPULATE_QWORD_7(*txd, 2314 2307 ESF_DZ_TX_DESC_IS_OPT, true, 2315 2308 ESF_DZ_TX_OPTION_TYPE, 2316 2309 ESE_DZ_TX_OPTION_DESC_CRC_CSUM, 2317 2310 ESF_DZ_TX_OPTION_UDP_TCP_CSUM, csum_offload, 2318 - ESF_DZ_TX_OPTION_IP_CSUM, csum_offload, 2311 + ESF_DZ_TX_OPTION_IP_CSUM, csum_offload && !tso_v2, 2312 + ESF_DZ_TX_OPTION_INNER_UDP_TCP_CSUM, inner_csum, 2313 + ESF_DZ_TX_OPTION_INNER_IP_CSUM, inner_csum && !tso_v2, 2319 2314 ESF_DZ_TX_TIMESTAMP, tx_queue->timestamping); 2320 2315 tx_queue->write_count = 1; 2321 2316
+12 -4
drivers/net/ethernet/sfc/mcdi_functions.c
··· 165 165 MCDI_DECLARE_BUF(inbuf, MC_CMD_INIT_TXQ_IN_LEN(EFX_MAX_DMAQ_SIZE * 8 / 166 166 EFX_BUF_SIZE)); 167 167 bool csum_offload = tx_queue->type & EFX_TXQ_TYPE_OUTER_CSUM; 168 + bool inner_csum = tx_queue->type & EFX_TXQ_TYPE_INNER_CSUM; 168 169 size_t entries = tx_queue->txd.buf.len / EFX_BUF_SIZE; 169 170 struct efx_channel *channel = tx_queue->channel; 170 171 struct efx_nic *efx = tx_queue->efx; ··· 195 194 inlen = MC_CMD_INIT_TXQ_IN_LEN(entries); 196 195 197 196 do { 198 - MCDI_POPULATE_DWORD_4(inbuf, INIT_TXQ_IN_FLAGS, 197 + /* TSOv2 implies IP header checksum offload for TSO frames, 198 + * so we can safely disable IP header checksum offload for 199 + * everything else. If we don't have TSOv2, then we have to 200 + * enable IP header checksum offload, which is strictly 201 + * incorrect but better than breaking TSO. 202 + */ 203 + MCDI_POPULATE_DWORD_6(inbuf, INIT_TXQ_IN_FLAGS, 199 204 /* This flag was removed from mcdi_pcol.h for 200 205 * the non-_EXT version of INIT_TXQ. However, 201 206 * firmware still honours it. 202 207 */ 203 208 INIT_TXQ_EXT_IN_FLAG_TSOV2_EN, tso_v2, 204 - INIT_TXQ_IN_FLAG_IP_CSUM_DIS, !csum_offload, 209 + INIT_TXQ_IN_FLAG_IP_CSUM_DIS, !(csum_offload && tso_v2), 205 210 INIT_TXQ_IN_FLAG_TCP_CSUM_DIS, !csum_offload, 206 - INIT_TXQ_EXT_IN_FLAG_TIMESTAMP, 207 - tx_queue->timestamping); 211 + INIT_TXQ_EXT_IN_FLAG_TIMESTAMP, tx_queue->timestamping, 212 + INIT_TXQ_IN_FLAG_INNER_IP_CSUM_EN, inner_csum && !tso_v2, 213 + INIT_TXQ_IN_FLAG_INNER_TCP_CSUM_EN, inner_csum); 208 214 209 215 rc = efx_mcdi_rpc_quiet(efx, MC_CMD_INIT_TXQ, inbuf, inlen, 210 216 NULL, 0, NULL);