Commit 447a851b authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'sfc-TXQ-refactor'



Edward Cree says:

====================
sfc: TXQ refactor

Refactor and unify partner-TXQ handling in the EF100 and legacy drivers.

The main thrust of this series is to remove from the legacy (Siena/EF10)
 driver the assumption that a netdev TX queue has precisely two hardware
 TXQs (checksummed and unchecksummed) associated with it, so that in
 future we can have more (e.g. for handling inner-header checksums) or
 fewer (e.g. to free up hardware queues for XDP usage).

Changes from v1:
 * better explain patch #1 in the commit message, and rename
   xmit_more_available to xmit_pending
 * add new patch #2 applying the same approach to ef100, for consistency
====================

Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 44a8c4f3 337792a2
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2367,7 +2367,7 @@ static void efx_ef10_tx_write(struct efx_tx_queue *tx_queue)
	unsigned int write_ptr;
	efx_qword_t *txd;

	tx_queue->xmit_more_available = false;
	tx_queue->xmit_pending = false;
	if (unlikely(tx_queue->write_count == tx_queue->insert_count))
		return;

+19 −15
Original line number Diff line number Diff line
@@ -117,11 +117,13 @@ static efx_oword_t *ef100_tx_desc(struct efx_tx_queue *tx_queue, unsigned int in
		return NULL;
}

void ef100_notify_tx_desc(struct efx_tx_queue *tx_queue)
static void ef100_notify_tx_desc(struct efx_tx_queue *tx_queue)
{
	unsigned int write_ptr;
	efx_dword_t reg;

	tx_queue->xmit_pending = false;

	if (unlikely(tx_queue->notify_count == tx_queue->write_count))
		return;

@@ -131,7 +133,6 @@ void ef100_notify_tx_desc(struct efx_tx_queue *tx_queue)
	efx_writed_page(tx_queue->efx, &reg,
			ER_GZ_TX_RING_DOORBELL, tx_queue->queue);
	tx_queue->notify_count = tx_queue->write_count;
	tx_queue->xmit_more_available = false;
}

static void ef100_tx_push_buffers(struct efx_tx_queue *tx_queue)
@@ -359,28 +360,31 @@ int ef100_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
		goto err;
	ef100_tx_make_descriptors(tx_queue, skb, segments);

	fill_level = efx_channel_tx_fill_level(tx_queue->channel);
	fill_level = efx_channel_tx_old_fill_level(tx_queue->channel);
	if (fill_level > efx->txq_stop_thresh) {
		struct efx_tx_queue *txq2;

		netif_tx_stop_queue(tx_queue->core_txq);
		/* Re-read after a memory barrier in case we've raced with
		 * the completion path. Otherwise there's a danger we'll never
		 * restart the queue if all completions have just happened.
		 */
		smp_mb();
		fill_level = efx_channel_tx_fill_level(tx_queue->channel);
		efx_for_each_channel_tx_queue(txq2, tx_queue->channel)
			txq2->old_read_count = READ_ONCE(txq2->read_count);
		fill_level = efx_channel_tx_old_fill_level(tx_queue->channel);
		if (fill_level < efx->txq_stop_thresh)
			netif_tx_start_queue(tx_queue->core_txq);
	}

	if (__netdev_tx_sent_queue(tx_queue->core_txq, skb->len, xmit_more))
		tx_queue->xmit_more_available = false; /* push doorbell */
	else if (tx_queue->write_count - tx_queue->notify_count > 255)
		/* Ensure we never push more than 256 packets at once */
		tx_queue->xmit_more_available = false; /* push */
	else
		tx_queue->xmit_more_available = true; /* don't push yet */
	tx_queue->xmit_pending = true;

	if (!tx_queue->xmit_more_available)
	/* If xmit_more then we don't need to push the doorbell, unless there
	 * are 256 descriptors already queued in which case we have to push to
	 * ensure we never push more than 256 at once.
	 */
	if (__netdev_tx_sent_queue(tx_queue->core_txq, skb->len, xmit_more) ||
	    tx_queue->write_count - tx_queue->notify_count > 255)
		ef100_tx_push_buffers(tx_queue);

	if (segments) {
@@ -399,10 +403,10 @@ err:

	/* If we're not expecting another transmit and we had something to push
	 * on this queue then we need to push here to get the previous packets
	 * out.  We only enter this branch from before the 'Update BQL' section
	 * above, so xmit_more_available still refers to the old state.
	 * out.  We only enter this branch from before the xmit_more handling
	 * above, so xmit_pending still refers to the old state.
	 */
	if (tx_queue->xmit_more_available && !xmit_more)
	if (tx_queue->xmit_pending && !xmit_more)
		ef100_tx_push_buffers(tx_queue);
	return rc;
}
+0 −1
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
int ef100_tx_probe(struct efx_tx_queue *tx_queue);
void ef100_tx_init(struct efx_tx_queue *tx_queue);
void ef100_tx_write(struct efx_tx_queue *tx_queue);
void ef100_notify_tx_desc(struct efx_tx_queue *tx_queue);
unsigned int ef100_tx_max_skb_descs(struct efx_nic *efx);

void ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event);
+1 −1
Original line number Diff line number Diff line
@@ -320,7 +320,7 @@ void efx_farch_tx_write(struct efx_tx_queue *tx_queue)
	unsigned write_ptr;
	unsigned old_write_count = tx_queue->write_count;

	tx_queue->xmit_more_available = false;
	tx_queue->xmit_pending = false;
	if (unlikely(tx_queue->write_count == tx_queue->insert_count))
		return;

+16 −6
Original line number Diff line number Diff line
@@ -244,7 +244,7 @@ struct efx_tx_buffer {
 * @tso_fallbacks: Number of times TSO fallback used
 * @pushes: Number of times the TX push feature has been used
 * @pio_packets: Number of times the TX PIO feature has been used
 * @xmit_more_available: Are any packets waiting to be pushed to the NIC
 * @xmit_pending: Are any packets waiting to be pushed to the NIC
 * @cb_packets: Number of times the TX copybreak feature has been used
 * @notify_count: Count of notified descriptors to the NIC
 * @empty_read_count: If the completion path has seen the queue as empty
@@ -292,7 +292,7 @@ struct efx_tx_queue {
	unsigned int tso_fallbacks;
	unsigned int pushes;
	unsigned int pio_packets;
	bool xmit_more_available;
	bool xmit_pending;
	unsigned int cb_packets;
	unsigned int notify_count;
	/* Statistics to supplement MAC stats */
@@ -1681,10 +1681,6 @@ efx_channel_tx_fill_level(struct efx_channel *channel)
	struct efx_tx_queue *tx_queue;
	unsigned int fill_level = 0;

	/* This function is currently only used by EF100, which maybe
	 * could do something simpler and just compute the fill level
	 * of the single TXQ that's really in use.
	 */
	efx_for_each_channel_tx_queue(tx_queue, channel)
		fill_level = max(fill_level,
				 tx_queue->insert_count - tx_queue->read_count);
@@ -1692,6 +1688,20 @@ efx_channel_tx_fill_level(struct efx_channel *channel)
	return fill_level;
}

/* Conservative approximation of efx_channel_tx_fill_level using cached value */
static inline unsigned int
efx_channel_tx_old_fill_level(struct efx_channel *channel)
{
	struct efx_tx_queue *tx_queue;
	unsigned int fill_level = 0;

	efx_for_each_channel_tx_queue(tx_queue, channel)
		fill_level = max(fill_level,
				 tx_queue->insert_count - tx_queue->old_read_count);

	return fill_level;
}

/* Get all supported features.
 * If a feature is not fixed, it is present in hw_features.
 * If a feature is fixed, it does not present in hw_features, but
Loading