Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9b39b62 authored by Ben Hutchings's avatar Ben Hutchings Committed by Jeff Garzik
Browse files

[netdrvr] sfc: Add TSO support



The SFC4000 controller does not have hardware support for TSO, and the
core GSO code incurs a high cost in allocating and freeing skbs.  This
TSO implementation uses lightweight packet header structures and is
substantially faster.

Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 48cfb14f
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -1873,6 +1873,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
		tx_queue->queue = i;
		tx_queue->buffer = NULL;
		tx_queue->channel = &efx->channel[0]; /* for safety */
		tx_queue->tso_headers_free = NULL;
	}
	for (i = 0; i < EFX_MAX_RX_QUEUES; i++) {
		rx_queue = &efx->rx_queue[i];
@@ -2071,7 +2072,8 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
	net_dev = alloc_etherdev(sizeof(*efx));
	if (!net_dev)
		return -ENOMEM;
	net_dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA;
	net_dev->features |= (NETIF_F_IP_CSUM | NETIF_F_SG |
			      NETIF_F_HIGHDMA | NETIF_F_TSO);
	if (lro)
		net_dev->features |= NETIF_F_LRO;
	efx = net_dev->priv;
+27 −0
Original line number Diff line number Diff line
@@ -272,6 +272,22 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
	}
}

static int efx_ethtool_set_tso(struct net_device *net_dev, u32 enable)
{
	int rc;

	/* Our TSO requires TX checksumming, so force TX checksumming
	 * on when TSO is enabled.
	 */
	if (enable) {
		rc = efx_ethtool_set_tx_csum(net_dev, 1);
		if (rc)
			return rc;
	}

	return ethtool_op_set_tso(net_dev, enable);
}

static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable)
{
	struct efx_nic *efx = net_dev->priv;
@@ -283,6 +299,15 @@ static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable)

	efx_flush_queues(efx);

	/* Our TSO requires TX checksumming, so disable TSO when
	 * checksumming is disabled
	 */
	if (!enable) {
		rc = efx_ethtool_set_tso(net_dev, 0);
		if (rc)
			return rc;
	}

	return 0;
}

@@ -451,6 +476,8 @@ struct ethtool_ops efx_ethtool_ops = {
	.set_tx_csum		= efx_ethtool_set_tx_csum,
	.get_sg			= ethtool_op_get_sg,
	.set_sg			= ethtool_op_set_sg,
	.get_tso		= ethtool_op_get_tso,
	.set_tso		= efx_ethtool_set_tso,
	.get_flags		= ethtool_op_get_flags,
	.set_flags		= ethtool_op_set_flags,
	.get_strings		= efx_ethtool_get_strings,
+14 −0
Original line number Diff line number Diff line
@@ -134,6 +134,8 @@ struct efx_special_buffer {
 *	Set only on the final fragment of a packet; %NULL for all other
 *	fragments.  When this fragment completes, then we can free this
 *	skb.
 * @tsoh: The associated TSO header structure, or %NULL if this
 *	buffer is not a TSO header.
 * @dma_addr: DMA address of the fragment.
 * @len: Length of this fragment.
 *	This field is zero when the queue slot is empty.
@@ -144,6 +146,7 @@ struct efx_special_buffer {
 */
struct efx_tx_buffer {
	const struct sk_buff *skb;
	struct efx_tso_header *tsoh;
	dma_addr_t dma_addr;
	unsigned short len;
	unsigned char continuation;
@@ -187,6 +190,13 @@ struct efx_tx_buffer {
 *	variable indicates that the queue is full.  This is to
 *	avoid cache-line ping-pong between the xmit path and the
 *	completion path.
 * @tso_headers_free: A list of TSO headers allocated for this TX queue
 *	that are not in use, and so available for new TSO sends. The list
 *	is protected by the TX queue lock.
 * @tso_bursts: Number of times TSO xmit invoked by kernel
 * @tso_long_headers: Number of packets with headers too long for standard
 *	blocks
 * @tso_packets: Number of packets via the TSO xmit path
 */
struct efx_tx_queue {
	/* Members which don't change on the fast path */
@@ -206,6 +216,10 @@ struct efx_tx_queue {
	unsigned int insert_count ____cacheline_aligned_in_smp;
	unsigned int write_count;
	unsigned int old_read_count;
	struct efx_tso_header *tso_headers_free;
	unsigned int tso_bursts;
	unsigned int tso_long_headers;
	unsigned int tso_packets;
};

/**
+664 −0

File changed.

Preview size limit exceeded, changes collapsed.