18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/****************************************************************************
38c2ecf20Sopenharmony_ci * Driver for Solarflare network controllers and boards
48c2ecf20Sopenharmony_ci * Copyright 2018 Solarflare Communications Inc.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify it
78c2ecf20Sopenharmony_ci * under the terms of the GNU General Public License version 2 as published
88c2ecf20Sopenharmony_ci * by the Free Software Foundation, incorporated herein by reference.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include "net_driver.h"
128c2ecf20Sopenharmony_ci#include "efx.h"
138c2ecf20Sopenharmony_ci#include "nic_common.h"
148c2ecf20Sopenharmony_ci#include "tx_common.h"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistatic unsigned int efx_tx_cb_page_count(struct efx_tx_queue *tx_queue)
178c2ecf20Sopenharmony_ci{
188c2ecf20Sopenharmony_ci	return DIV_ROUND_UP(tx_queue->ptr_mask + 1,
198c2ecf20Sopenharmony_ci			    PAGE_SIZE >> EFX_TX_CB_ORDER);
208c2ecf20Sopenharmony_ci}
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ciint efx_probe_tx_queue(struct efx_tx_queue *tx_queue)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	struct efx_nic *efx = tx_queue->efx;
258c2ecf20Sopenharmony_ci	unsigned int entries;
268c2ecf20Sopenharmony_ci	int rc;
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	/* Create the smallest power-of-two aligned ring */
298c2ecf20Sopenharmony_ci	entries = max(roundup_pow_of_two(efx->txq_entries), EFX_MIN_DMAQ_SIZE);
308c2ecf20Sopenharmony_ci	EFX_WARN_ON_PARANOID(entries > EFX_MAX_DMAQ_SIZE);
318c2ecf20Sopenharmony_ci	tx_queue->ptr_mask = entries - 1;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	netif_dbg(efx, probe, efx->net_dev,
348c2ecf20Sopenharmony_ci		  "creating TX queue %d size %#x mask %#x\n",
358c2ecf20Sopenharmony_ci		  tx_queue->queue, efx->txq_entries, tx_queue->ptr_mask);
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	/* Allocate software ring */
388c2ecf20Sopenharmony_ci	tx_queue->buffer = kcalloc(entries, sizeof(*tx_queue->buffer),
398c2ecf20Sopenharmony_ci				   GFP_KERNEL);
408c2ecf20Sopenharmony_ci	if (!tx_queue->buffer)
418c2ecf20Sopenharmony_ci		return -ENOMEM;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	tx_queue->cb_page = kcalloc(efx_tx_cb_page_count(tx_queue),
448c2ecf20Sopenharmony_ci				    sizeof(tx_queue->cb_page[0]), GFP_KERNEL);
458c2ecf20Sopenharmony_ci	if (!tx_queue->cb_page) {
468c2ecf20Sopenharmony_ci		rc = -ENOMEM;
478c2ecf20Sopenharmony_ci		goto fail1;
488c2ecf20Sopenharmony_ci	}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	/* Allocate hardware ring, determine TXQ type */
518c2ecf20Sopenharmony_ci	rc = efx_nic_probe_tx(tx_queue);
528c2ecf20Sopenharmony_ci	if (rc)
538c2ecf20Sopenharmony_ci		goto fail2;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	tx_queue->channel->tx_queue_by_type[tx_queue->type] = tx_queue;
568c2ecf20Sopenharmony_ci	return 0;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cifail2:
598c2ecf20Sopenharmony_ci	kfree(tx_queue->cb_page);
608c2ecf20Sopenharmony_ci	tx_queue->cb_page = NULL;
618c2ecf20Sopenharmony_cifail1:
628c2ecf20Sopenharmony_ci	kfree(tx_queue->buffer);
638c2ecf20Sopenharmony_ci	tx_queue->buffer = NULL;
648c2ecf20Sopenharmony_ci	return rc;
658c2ecf20Sopenharmony_ci}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_civoid efx_init_tx_queue(struct efx_tx_queue *tx_queue)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	struct efx_nic *efx = tx_queue->efx;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	netif_dbg(efx, drv, efx->net_dev,
728c2ecf20Sopenharmony_ci		  "initialising TX queue %d\n", tx_queue->queue);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	tx_queue->insert_count = 0;
758c2ecf20Sopenharmony_ci	tx_queue->notify_count = 0;
768c2ecf20Sopenharmony_ci	tx_queue->write_count = 0;
778c2ecf20Sopenharmony_ci	tx_queue->packet_write_count = 0;
788c2ecf20Sopenharmony_ci	tx_queue->old_write_count = 0;
798c2ecf20Sopenharmony_ci	tx_queue->read_count = 0;
808c2ecf20Sopenharmony_ci	tx_queue->old_read_count = 0;
818c2ecf20Sopenharmony_ci	tx_queue->empty_read_count = 0 | EFX_EMPTY_COUNT_VALID;
828c2ecf20Sopenharmony_ci	tx_queue->xmit_pending = false;
838c2ecf20Sopenharmony_ci	tx_queue->timestamping = (efx_ptp_use_mac_tx_timestamps(efx) &&
848c2ecf20Sopenharmony_ci				  tx_queue->channel == efx_ptp_channel(efx));
858c2ecf20Sopenharmony_ci	tx_queue->completed_timestamp_major = 0;
868c2ecf20Sopenharmony_ci	tx_queue->completed_timestamp_minor = 0;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	tx_queue->xdp_tx = efx_channel_is_xdp_tx(tx_queue->channel);
898c2ecf20Sopenharmony_ci	tx_queue->tso_version = 0;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	/* Set up TX descriptor ring */
928c2ecf20Sopenharmony_ci	efx_nic_init_tx(tx_queue);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	tx_queue->initialised = true;
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_civoid efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	struct efx_tx_buffer *buffer;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
1028c2ecf20Sopenharmony_ci		  "shutting down TX queue %d\n", tx_queue->queue);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	if (!tx_queue->buffer)
1058c2ecf20Sopenharmony_ci		return;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	/* Free any buffers left in the ring */
1088c2ecf20Sopenharmony_ci	while (tx_queue->read_count != tx_queue->write_count) {
1098c2ecf20Sopenharmony_ci		unsigned int pkts_compl = 0, bytes_compl = 0;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci		buffer = &tx_queue->buffer[tx_queue->read_count & tx_queue->ptr_mask];
1128c2ecf20Sopenharmony_ci		efx_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl);
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci		++tx_queue->read_count;
1158c2ecf20Sopenharmony_ci	}
1168c2ecf20Sopenharmony_ci	tx_queue->xmit_pending = false;
1178c2ecf20Sopenharmony_ci	netdev_tx_reset_queue(tx_queue->core_txq);
1188c2ecf20Sopenharmony_ci}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_civoid efx_remove_tx_queue(struct efx_tx_queue *tx_queue)
1218c2ecf20Sopenharmony_ci{
1228c2ecf20Sopenharmony_ci	int i;
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	if (!tx_queue->buffer)
1258c2ecf20Sopenharmony_ci		return;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
1288c2ecf20Sopenharmony_ci		  "destroying TX queue %d\n", tx_queue->queue);
1298c2ecf20Sopenharmony_ci	efx_nic_remove_tx(tx_queue);
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	if (tx_queue->cb_page) {
1328c2ecf20Sopenharmony_ci		for (i = 0; i < efx_tx_cb_page_count(tx_queue); i++)
1338c2ecf20Sopenharmony_ci			efx_nic_free_buffer(tx_queue->efx,
1348c2ecf20Sopenharmony_ci					    &tx_queue->cb_page[i]);
1358c2ecf20Sopenharmony_ci		kfree(tx_queue->cb_page);
1368c2ecf20Sopenharmony_ci		tx_queue->cb_page = NULL;
1378c2ecf20Sopenharmony_ci	}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	kfree(tx_queue->buffer);
1408c2ecf20Sopenharmony_ci	tx_queue->buffer = NULL;
1418c2ecf20Sopenharmony_ci	tx_queue->channel->tx_queue_by_type[tx_queue->type] = NULL;
1428c2ecf20Sopenharmony_ci}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_civoid efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
1458c2ecf20Sopenharmony_ci			struct efx_tx_buffer *buffer,
1468c2ecf20Sopenharmony_ci			unsigned int *pkts_compl,
1478c2ecf20Sopenharmony_ci			unsigned int *bytes_compl)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	if (buffer->unmap_len) {
1508c2ecf20Sopenharmony_ci		struct device *dma_dev = &tx_queue->efx->pci_dev->dev;
1518c2ecf20Sopenharmony_ci		dma_addr_t unmap_addr = buffer->dma_addr - buffer->dma_offset;
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci		if (buffer->flags & EFX_TX_BUF_MAP_SINGLE)
1548c2ecf20Sopenharmony_ci			dma_unmap_single(dma_dev, unmap_addr, buffer->unmap_len,
1558c2ecf20Sopenharmony_ci					 DMA_TO_DEVICE);
1568c2ecf20Sopenharmony_ci		else
1578c2ecf20Sopenharmony_ci			dma_unmap_page(dma_dev, unmap_addr, buffer->unmap_len,
1588c2ecf20Sopenharmony_ci				       DMA_TO_DEVICE);
1598c2ecf20Sopenharmony_ci		buffer->unmap_len = 0;
1608c2ecf20Sopenharmony_ci	}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	if (buffer->flags & EFX_TX_BUF_SKB) {
1638c2ecf20Sopenharmony_ci		struct sk_buff *skb = (struct sk_buff *)buffer->skb;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci		EFX_WARN_ON_PARANOID(!pkts_compl || !bytes_compl);
1668c2ecf20Sopenharmony_ci		(*pkts_compl)++;
1678c2ecf20Sopenharmony_ci		(*bytes_compl) += skb->len;
1688c2ecf20Sopenharmony_ci		if (tx_queue->timestamping &&
1698c2ecf20Sopenharmony_ci		    (tx_queue->completed_timestamp_major ||
1708c2ecf20Sopenharmony_ci		     tx_queue->completed_timestamp_minor)) {
1718c2ecf20Sopenharmony_ci			struct skb_shared_hwtstamps hwtstamp;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci			hwtstamp.hwtstamp =
1748c2ecf20Sopenharmony_ci				efx_ptp_nic_to_kernel_time(tx_queue);
1758c2ecf20Sopenharmony_ci			skb_tstamp_tx(skb, &hwtstamp);
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci			tx_queue->completed_timestamp_major = 0;
1788c2ecf20Sopenharmony_ci			tx_queue->completed_timestamp_minor = 0;
1798c2ecf20Sopenharmony_ci		}
1808c2ecf20Sopenharmony_ci		dev_consume_skb_any((struct sk_buff *)buffer->skb);
1818c2ecf20Sopenharmony_ci		netif_vdbg(tx_queue->efx, tx_done, tx_queue->efx->net_dev,
1828c2ecf20Sopenharmony_ci			   "TX queue %d transmission id %x complete\n",
1838c2ecf20Sopenharmony_ci			   tx_queue->queue, tx_queue->read_count);
1848c2ecf20Sopenharmony_ci	} else if (buffer->flags & EFX_TX_BUF_XDP) {
1858c2ecf20Sopenharmony_ci		xdp_return_frame_rx_napi(buffer->xdpf);
1868c2ecf20Sopenharmony_ci	}
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	buffer->len = 0;
1898c2ecf20Sopenharmony_ci	buffer->flags = 0;
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci/* Remove packets from the TX queue
1938c2ecf20Sopenharmony_ci *
1948c2ecf20Sopenharmony_ci * This removes packets from the TX queue, up to and including the
1958c2ecf20Sopenharmony_ci * specified index.
1968c2ecf20Sopenharmony_ci */
1978c2ecf20Sopenharmony_cistatic void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
1988c2ecf20Sopenharmony_ci				unsigned int index,
1998c2ecf20Sopenharmony_ci				unsigned int *pkts_compl,
2008c2ecf20Sopenharmony_ci				unsigned int *bytes_compl)
2018c2ecf20Sopenharmony_ci{
2028c2ecf20Sopenharmony_ci	struct efx_nic *efx = tx_queue->efx;
2038c2ecf20Sopenharmony_ci	unsigned int stop_index, read_ptr;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	stop_index = (index + 1) & tx_queue->ptr_mask;
2068c2ecf20Sopenharmony_ci	read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	while (read_ptr != stop_index) {
2098c2ecf20Sopenharmony_ci		struct efx_tx_buffer *buffer = &tx_queue->buffer[read_ptr];
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci		if (!efx_tx_buffer_in_use(buffer)) {
2128c2ecf20Sopenharmony_ci			netif_err(efx, tx_err, efx->net_dev,
2138c2ecf20Sopenharmony_ci				  "TX queue %d spurious TX completion id %d\n",
2148c2ecf20Sopenharmony_ci				  tx_queue->queue, read_ptr);
2158c2ecf20Sopenharmony_ci			efx_schedule_reset(efx, RESET_TYPE_TX_SKIP);
2168c2ecf20Sopenharmony_ci			return;
2178c2ecf20Sopenharmony_ci		}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci		efx_dequeue_buffer(tx_queue, buffer, pkts_compl, bytes_compl);
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci		++tx_queue->read_count;
2228c2ecf20Sopenharmony_ci		read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
2238c2ecf20Sopenharmony_ci	}
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_civoid efx_xmit_done_check_empty(struct efx_tx_queue *tx_queue)
2278c2ecf20Sopenharmony_ci{
2288c2ecf20Sopenharmony_ci	if ((int)(tx_queue->read_count - tx_queue->old_write_count) >= 0) {
2298c2ecf20Sopenharmony_ci		tx_queue->old_write_count = READ_ONCE(tx_queue->write_count);
2308c2ecf20Sopenharmony_ci		if (tx_queue->read_count == tx_queue->old_write_count) {
2318c2ecf20Sopenharmony_ci			/* Ensure that read_count is flushed. */
2328c2ecf20Sopenharmony_ci			smp_mb();
2338c2ecf20Sopenharmony_ci			tx_queue->empty_read_count =
2348c2ecf20Sopenharmony_ci				tx_queue->read_count | EFX_EMPTY_COUNT_VALID;
2358c2ecf20Sopenharmony_ci		}
2368c2ecf20Sopenharmony_ci	}
2378c2ecf20Sopenharmony_ci}
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_civoid efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
2408c2ecf20Sopenharmony_ci{
2418c2ecf20Sopenharmony_ci	unsigned int fill_level, pkts_compl = 0, bytes_compl = 0;
2428c2ecf20Sopenharmony_ci	struct efx_nic *efx = tx_queue->efx;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	EFX_WARN_ON_ONCE_PARANOID(index > tx_queue->ptr_mask);
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	efx_dequeue_buffers(tx_queue, index, &pkts_compl, &bytes_compl);
2478c2ecf20Sopenharmony_ci	tx_queue->pkts_compl += pkts_compl;
2488c2ecf20Sopenharmony_ci	tx_queue->bytes_compl += bytes_compl;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	if (pkts_compl > 1)
2518c2ecf20Sopenharmony_ci		++tx_queue->merge_events;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	/* See if we need to restart the netif queue.  This memory
2548c2ecf20Sopenharmony_ci	 * barrier ensures that we write read_count (inside
2558c2ecf20Sopenharmony_ci	 * efx_dequeue_buffers()) before reading the queue status.
2568c2ecf20Sopenharmony_ci	 */
2578c2ecf20Sopenharmony_ci	smp_mb();
2588c2ecf20Sopenharmony_ci	if (unlikely(netif_tx_queue_stopped(tx_queue->core_txq)) &&
2598c2ecf20Sopenharmony_ci	    likely(efx->port_enabled) &&
2608c2ecf20Sopenharmony_ci	    likely(netif_device_present(efx->net_dev))) {
2618c2ecf20Sopenharmony_ci		fill_level = efx_channel_tx_fill_level(tx_queue->channel);
2628c2ecf20Sopenharmony_ci		if (fill_level <= efx->txq_wake_thresh)
2638c2ecf20Sopenharmony_ci			netif_tx_wake_queue(tx_queue->core_txq);
2648c2ecf20Sopenharmony_ci	}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	efx_xmit_done_check_empty(tx_queue);
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci/* Remove buffers put into a tx_queue for the current packet.
2708c2ecf20Sopenharmony_ci * None of the buffers must have an skb attached.
2718c2ecf20Sopenharmony_ci */
2728c2ecf20Sopenharmony_civoid efx_enqueue_unwind(struct efx_tx_queue *tx_queue,
2738c2ecf20Sopenharmony_ci			unsigned int insert_count)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	struct efx_tx_buffer *buffer;
2768c2ecf20Sopenharmony_ci	unsigned int bytes_compl = 0;
2778c2ecf20Sopenharmony_ci	unsigned int pkts_compl = 0;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	/* Work backwards until we hit the original insert pointer value */
2808c2ecf20Sopenharmony_ci	while (tx_queue->insert_count != insert_count) {
2818c2ecf20Sopenharmony_ci		--tx_queue->insert_count;
2828c2ecf20Sopenharmony_ci		buffer = __efx_tx_queue_get_insert_buffer(tx_queue);
2838c2ecf20Sopenharmony_ci		efx_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl);
2848c2ecf20Sopenharmony_ci	}
2858c2ecf20Sopenharmony_ci}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_cistruct efx_tx_buffer *efx_tx_map_chunk(struct efx_tx_queue *tx_queue,
2888c2ecf20Sopenharmony_ci				       dma_addr_t dma_addr, size_t len)
2898c2ecf20Sopenharmony_ci{
2908c2ecf20Sopenharmony_ci	const struct efx_nic_type *nic_type = tx_queue->efx->type;
2918c2ecf20Sopenharmony_ci	struct efx_tx_buffer *buffer;
2928c2ecf20Sopenharmony_ci	unsigned int dma_len;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	/* Map the fragment taking account of NIC-dependent DMA limits. */
2958c2ecf20Sopenharmony_ci	do {
2968c2ecf20Sopenharmony_ci		buffer = efx_tx_queue_get_insert_buffer(tx_queue);
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci		if (nic_type->tx_limit_len)
2998c2ecf20Sopenharmony_ci			dma_len = nic_type->tx_limit_len(tx_queue, dma_addr, len);
3008c2ecf20Sopenharmony_ci		else
3018c2ecf20Sopenharmony_ci			dma_len = len;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci		buffer->len = dma_len;
3048c2ecf20Sopenharmony_ci		buffer->dma_addr = dma_addr;
3058c2ecf20Sopenharmony_ci		buffer->flags = EFX_TX_BUF_CONT;
3068c2ecf20Sopenharmony_ci		len -= dma_len;
3078c2ecf20Sopenharmony_ci		dma_addr += dma_len;
3088c2ecf20Sopenharmony_ci		++tx_queue->insert_count;
3098c2ecf20Sopenharmony_ci	} while (len);
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	return buffer;
3128c2ecf20Sopenharmony_ci}
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ciint efx_tx_tso_header_length(struct sk_buff *skb)
3158c2ecf20Sopenharmony_ci{
3168c2ecf20Sopenharmony_ci	size_t header_len;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	if (skb->encapsulation)
3198c2ecf20Sopenharmony_ci		header_len = skb_inner_transport_header(skb) -
3208c2ecf20Sopenharmony_ci				skb->data +
3218c2ecf20Sopenharmony_ci				(inner_tcp_hdr(skb)->doff << 2u);
3228c2ecf20Sopenharmony_ci	else
3238c2ecf20Sopenharmony_ci		header_len = skb_transport_header(skb) - skb->data +
3248c2ecf20Sopenharmony_ci				(tcp_hdr(skb)->doff << 2u);
3258c2ecf20Sopenharmony_ci	return header_len;
3268c2ecf20Sopenharmony_ci}
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci/* Map all data from an SKB for DMA and create descriptors on the queue. */
3298c2ecf20Sopenharmony_ciint efx_tx_map_data(struct efx_tx_queue *tx_queue, struct sk_buff *skb,
3308c2ecf20Sopenharmony_ci		    unsigned int segment_count)
3318c2ecf20Sopenharmony_ci{
3328c2ecf20Sopenharmony_ci	struct efx_nic *efx = tx_queue->efx;
3338c2ecf20Sopenharmony_ci	struct device *dma_dev = &efx->pci_dev->dev;
3348c2ecf20Sopenharmony_ci	unsigned int frag_index, nr_frags;
3358c2ecf20Sopenharmony_ci	dma_addr_t dma_addr, unmap_addr;
3368c2ecf20Sopenharmony_ci	unsigned short dma_flags;
3378c2ecf20Sopenharmony_ci	size_t len, unmap_len;
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	nr_frags = skb_shinfo(skb)->nr_frags;
3408c2ecf20Sopenharmony_ci	frag_index = 0;
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	/* Map header data. */
3438c2ecf20Sopenharmony_ci	len = skb_headlen(skb);
3448c2ecf20Sopenharmony_ci	dma_addr = dma_map_single(dma_dev, skb->data, len, DMA_TO_DEVICE);
3458c2ecf20Sopenharmony_ci	dma_flags = EFX_TX_BUF_MAP_SINGLE;
3468c2ecf20Sopenharmony_ci	unmap_len = len;
3478c2ecf20Sopenharmony_ci	unmap_addr = dma_addr;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	if (unlikely(dma_mapping_error(dma_dev, dma_addr)))
3508c2ecf20Sopenharmony_ci		return -EIO;
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	if (segment_count) {
3538c2ecf20Sopenharmony_ci		/* For TSO we need to put the header in to a separate
3548c2ecf20Sopenharmony_ci		 * descriptor. Map this separately if necessary.
3558c2ecf20Sopenharmony_ci		 */
3568c2ecf20Sopenharmony_ci		size_t header_len = efx_tx_tso_header_length(skb);
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci		if (header_len != len) {
3598c2ecf20Sopenharmony_ci			tx_queue->tso_long_headers++;
3608c2ecf20Sopenharmony_ci			efx_tx_map_chunk(tx_queue, dma_addr, header_len);
3618c2ecf20Sopenharmony_ci			len -= header_len;
3628c2ecf20Sopenharmony_ci			dma_addr += header_len;
3638c2ecf20Sopenharmony_ci		}
3648c2ecf20Sopenharmony_ci	}
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	/* Add descriptors for each fragment. */
3678c2ecf20Sopenharmony_ci	do {
3688c2ecf20Sopenharmony_ci		struct efx_tx_buffer *buffer;
3698c2ecf20Sopenharmony_ci		skb_frag_t *fragment;
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci		buffer = efx_tx_map_chunk(tx_queue, dma_addr, len);
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci		/* The final descriptor for a fragment is responsible for
3748c2ecf20Sopenharmony_ci		 * unmapping the whole fragment.
3758c2ecf20Sopenharmony_ci		 */
3768c2ecf20Sopenharmony_ci		buffer->flags = EFX_TX_BUF_CONT | dma_flags;
3778c2ecf20Sopenharmony_ci		buffer->unmap_len = unmap_len;
3788c2ecf20Sopenharmony_ci		buffer->dma_offset = buffer->dma_addr - unmap_addr;
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci		if (frag_index >= nr_frags) {
3818c2ecf20Sopenharmony_ci			/* Store SKB details with the final buffer for
3828c2ecf20Sopenharmony_ci			 * the completion.
3838c2ecf20Sopenharmony_ci			 */
3848c2ecf20Sopenharmony_ci			buffer->skb = skb;
3858c2ecf20Sopenharmony_ci			buffer->flags = EFX_TX_BUF_SKB | dma_flags;
3868c2ecf20Sopenharmony_ci			return 0;
3878c2ecf20Sopenharmony_ci		}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci		/* Move on to the next fragment. */
3908c2ecf20Sopenharmony_ci		fragment = &skb_shinfo(skb)->frags[frag_index++];
3918c2ecf20Sopenharmony_ci		len = skb_frag_size(fragment);
3928c2ecf20Sopenharmony_ci		dma_addr = skb_frag_dma_map(dma_dev, fragment, 0, len,
3938c2ecf20Sopenharmony_ci					    DMA_TO_DEVICE);
3948c2ecf20Sopenharmony_ci		dma_flags = 0;
3958c2ecf20Sopenharmony_ci		unmap_len = len;
3968c2ecf20Sopenharmony_ci		unmap_addr = dma_addr;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci		if (unlikely(dma_mapping_error(dma_dev, dma_addr)))
3998c2ecf20Sopenharmony_ci			return -EIO;
4008c2ecf20Sopenharmony_ci	} while (1);
4018c2ecf20Sopenharmony_ci}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ciunsigned int efx_tx_max_skb_descs(struct efx_nic *efx)
4048c2ecf20Sopenharmony_ci{
4058c2ecf20Sopenharmony_ci	/* Header and payload descriptor for each output segment, plus
4068c2ecf20Sopenharmony_ci	 * one for every input fragment boundary within a segment
4078c2ecf20Sopenharmony_ci	 */
4088c2ecf20Sopenharmony_ci	unsigned int max_descs = EFX_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS;
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	/* Possibly one more per segment for option descriptors */
4118c2ecf20Sopenharmony_ci	if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0)
4128c2ecf20Sopenharmony_ci		max_descs += EFX_TSO_MAX_SEGS;
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	/* Possibly more for PCIe page boundaries within input fragments */
4158c2ecf20Sopenharmony_ci	if (PAGE_SIZE > EFX_PAGE_SIZE)
4168c2ecf20Sopenharmony_ci		max_descs += max_t(unsigned int, MAX_SKB_FRAGS,
4178c2ecf20Sopenharmony_ci				   DIV_ROUND_UP(GSO_MAX_SIZE, EFX_PAGE_SIZE));
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	return max_descs;
4208c2ecf20Sopenharmony_ci}
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci/*
4238c2ecf20Sopenharmony_ci * Fallback to software TSO.
4248c2ecf20Sopenharmony_ci *
4258c2ecf20Sopenharmony_ci * This is used if we are unable to send a GSO packet through hardware TSO.
4268c2ecf20Sopenharmony_ci * This should only ever happen due to per-queue restrictions - unsupported
4278c2ecf20Sopenharmony_ci * packets should first be filtered by the feature flags.
4288c2ecf20Sopenharmony_ci *
4298c2ecf20Sopenharmony_ci * Returns 0 on success, error code otherwise.
4308c2ecf20Sopenharmony_ci */
4318c2ecf20Sopenharmony_ciint efx_tx_tso_fallback(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
4328c2ecf20Sopenharmony_ci{
4338c2ecf20Sopenharmony_ci	struct sk_buff *segments, *next;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	segments = skb_gso_segment(skb, 0);
4368c2ecf20Sopenharmony_ci	if (IS_ERR(segments))
4378c2ecf20Sopenharmony_ci		return PTR_ERR(segments);
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	dev_consume_skb_any(skb);
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	skb_list_walk_safe(segments, skb, next) {
4428c2ecf20Sopenharmony_ci		skb_mark_not_on_list(skb);
4438c2ecf20Sopenharmony_ci		efx_enqueue_skb(tx_queue, skb);
4448c2ecf20Sopenharmony_ci	}
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	return 0;
4478c2ecf20Sopenharmony_ci}
448