Commit 1679c72c authored by Edward Cree's avatar Edward Cree Committed by David S. Miller
Browse files

sfc: de-indirect TSO handling



Remove the tx_queue->handle_tso function pointer, and just use
 tx_queue->tso_version to decide which function to call, thus removing
 an indirect call from the fast path.
Instead of passing a tso_v2 flag to efx_mcdi_tx_init(), set the desired
 tx_queue->tso_version before calling it.
In efx_mcdi_tx_init(), report back failure to obtain a TSOv2 context by
 setting tx_queue->tso_version to 0, which will cause the TX path to
 use the GSO-based fallback.

Signed-off-by: default avatarEdward Cree <ecree@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fe0c4060
Loading
Loading
Loading
Loading
+14 −21
Original line number Diff line number Diff line
@@ -2175,8 +2175,7 @@ static inline void efx_ef10_push_tx_desc(struct efx_tx_queue *tx_queue,

/* Add Firmware-Assisted TSO v2 option descriptors to a queue.
 */
static int efx_ef10_tx_tso_desc(struct efx_tx_queue *tx_queue,
				struct sk_buff *skb,
int efx_ef10_tx_tso_desc(struct efx_tx_queue *tx_queue, struct sk_buff *skb,
			 bool *data_mapped)
{
	struct efx_tx_buffer *buffer;
@@ -2266,7 +2265,6 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
	struct efx_channel *channel = tx_queue->channel;
	struct efx_nic *efx = tx_queue->efx;
	struct efx_ef10_nic_data *nic_data;
	bool tso_v2 = false;
	efx_qword_t *txd;
	int rc;

@@ -2289,15 +2287,18 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
	 * TSOv2 cannot be used with Hardware timestamping, and is never needed
	 * for XDP tx.
	 */
	if ((csum_offload || inner_csum) && (nic_data->datapath_caps2 &
			(1 << MC_CMD_GET_CAPABILITIES_V2_OUT_TX_TSO_V2_LBN)) &&
	if (efx_has_cap(efx, TX_TSO_V2)) {
		if ((csum_offload || inner_csum) &&
		    !tx_queue->timestamping && !tx_queue->xdp_tx) {
		tso_v2 = true;
			tx_queue->tso_version = 2;
			netif_dbg(efx, hw, efx->net_dev, "Using TSOv2 for channel %u\n",
				  channel->channel);
		}
	} else if (efx_has_cap(efx, TX_TSO)) {
		tx_queue->tso_version = 1;
	}

	rc = efx_mcdi_tx_init(tx_queue, tso_v2);
	rc = efx_mcdi_tx_init(tx_queue);
	if (rc)
		goto fail;

@@ -2315,20 +2316,12 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
			     ESF_DZ_TX_OPTION_TYPE,
			     ESE_DZ_TX_OPTION_DESC_CRC_CSUM,
			     ESF_DZ_TX_OPTION_UDP_TCP_CSUM, csum_offload,
			     ESF_DZ_TX_OPTION_IP_CSUM, csum_offload && !tso_v2,
			     ESF_DZ_TX_OPTION_IP_CSUM, csum_offload && tx_queue->tso_version != 2,
			     ESF_DZ_TX_OPTION_INNER_UDP_TCP_CSUM, inner_csum,
			     ESF_DZ_TX_OPTION_INNER_IP_CSUM, inner_csum && !tso_v2,
			     ESF_DZ_TX_OPTION_INNER_IP_CSUM, inner_csum && tx_queue->tso_version != 2,
			     ESF_DZ_TX_TIMESTAMP, tx_queue->timestamping);
	tx_queue->write_count = 1;

	if (tso_v2) {
		tx_queue->handle_tso = efx_ef10_tx_tso_desc;
		tx_queue->tso_version = 2;
	} else if (nic_data->datapath_caps &
			(1 << MC_CMD_GET_CAPABILITIES_OUT_TX_TSO_LBN)) {
		tx_queue->tso_version = 1;
	}

	wmb();
	efx_ef10_push_tx_desc(tx_queue, txd);

+8 −1
Original line number Diff line number Diff line
@@ -37,7 +37,14 @@ void ef100_tx_init(struct efx_tx_queue *tx_queue)
				    tx_queue->channel->channel -
				    tx_queue->efx->tx_channel_offset);

	if (efx_mcdi_tx_init(tx_queue, false))
	/* This value is purely documentational; as EF100 never passes through
	 * the switch statement in tx.c:__efx_enqueue_skb(), that switch does
	 * not handle case 3.  EF100's TSOv3 descriptors are generated by
	 * ef100_make_tso_desc().
	 * Meanwhile, all efx_mcdi_tx_init() cares about is that it's not 2.
	 */
	tx_queue->tso_version = 3;
	if (efx_mcdi_tx_init(tx_queue))
		netdev_WARN(tx_queue->efx->net_dev,
			    "failed to initialise TXQ %d\n", tx_queue->queue);
}
+2 −0
Original line number Diff line number Diff line
@@ -415,6 +415,8 @@ void efx_farch_tx_init(struct efx_tx_queue *tx_queue)
			     FFE_BZ_TX_PACE_OFF :
			     FFE_BZ_TX_PACE_RESERVED);
	efx_writeo_table(efx, &reg, FR_BZ_TX_PACE_TBL, tx_queue->queue);

	tx_queue->tso_version = 1;
}

static void efx_farch_flush_tx_queue(struct efx_tx_queue *tx_queue)
+4 −2
Original line number Diff line number Diff line
@@ -160,7 +160,7 @@ void efx_mcdi_ev_fini(struct efx_channel *channel)
			       outbuf, outlen, rc);
}

int efx_mcdi_tx_init(struct efx_tx_queue *tx_queue, bool tso_v2)
int efx_mcdi_tx_init(struct efx_tx_queue *tx_queue)
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_INIT_TXQ_IN_LEN(EFX_MAX_DMAQ_SIZE * 8 /
						       EFX_BUF_SIZE));
@@ -195,6 +195,8 @@ int efx_mcdi_tx_init(struct efx_tx_queue *tx_queue, bool tso_v2)
	inlen = MC_CMD_INIT_TXQ_IN_LEN(entries);

	do {
		bool tso_v2 = tx_queue->tso_version == 2;

		/* TSOv2 implies IP header checksum offload for TSO frames,
		 * so we can safely disable IP header checksum offload for
		 * everything else.  If we don't have TSOv2, then we have to
@@ -217,7 +219,7 @@ int efx_mcdi_tx_init(struct efx_tx_queue *tx_queue, bool tso_v2)
					NULL, 0, NULL);
		if (rc == -ENOSPC && tso_v2) {
			/* Retry without TSOv2 if we're short on contexts. */
			tso_v2 = false;
			tx_queue->tso_version = 0;
			netif_warn(efx, probe, efx->net_dev,
				   "TSOv2 context not available to segment in "
				   "hardware. TCP performance may be reduced.\n"
+1 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ int efx_mcdi_ev_probe(struct efx_channel *channel);
int efx_mcdi_ev_init(struct efx_channel *channel, bool v1_cut_thru, bool v2);
void efx_mcdi_ev_remove(struct efx_channel *channel);
void efx_mcdi_ev_fini(struct efx_channel *channel);
int efx_mcdi_tx_init(struct efx_tx_queue *tx_queue, bool tso_v2);
int efx_mcdi_tx_init(struct efx_tx_queue *tx_queue);
void efx_mcdi_tx_remove(struct efx_tx_queue *tx_queue);
void efx_mcdi_tx_fini(struct efx_tx_queue *tx_queue);
int efx_mcdi_rx_probe(struct efx_rx_queue *rx_queue);
Loading