Commit eeddfd8e authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'sfc-txq-lookups'



Edward Cree says:

====================
sfc: fix TXQ lookups

The TXQ handling changes in 12804793 ("sfc: decouple TXQ type from label")
 which were made as part of the support for encap offloads on EF10 caused some
 breakage on Siena (5000- and 6000-series) NICs, which caused null-dereference
 kernel panics.
This series fixes those issues, and also a similarly incorrect code-path on
 EF10 which worked by chance.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4acd4764 172e269e
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -2928,8 +2928,7 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)

	/* Get the transmit queue */
	tx_ev_q_label = EFX_QWORD_FIELD(*event, ESF_DZ_TX_QLABEL);
	tx_queue = efx_channel_get_tx_queue(channel,
					    tx_ev_q_label % EFX_MAX_TXQ_PER_CHANNEL);
	tx_queue = channel->tx_queue + (tx_ev_q_label % EFX_MAX_TXQ_PER_CHANNEL);

	if (!tx_queue->timestamping) {
		/* Transmit completion */
+8 −8
Original line number Diff line number Diff line
@@ -835,14 +835,14 @@ efx_farch_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
		/* Transmit completion */
		tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_DESC_PTR);
		tx_ev_q_label = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_Q_LABEL);
		tx_queue = efx_channel_get_tx_queue(
			channel, tx_ev_q_label % EFX_MAX_TXQ_PER_CHANNEL);
		tx_queue = channel->tx_queue +
				(tx_ev_q_label % EFX_MAX_TXQ_PER_CHANNEL);
		efx_xmit_done(tx_queue, tx_ev_desc_ptr);
	} else if (EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_WQ_FF_FULL)) {
		/* Rewrite the FIFO write pointer */
		tx_ev_q_label = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_Q_LABEL);
		tx_queue = efx_channel_get_tx_queue(
			channel, tx_ev_q_label % EFX_MAX_TXQ_PER_CHANNEL);
		tx_queue = channel->tx_queue +
				(tx_ev_q_label % EFX_MAX_TXQ_PER_CHANNEL);

		netif_tx_lock(efx->net_dev);
		efx_farch_notify_tx_desc(tx_queue);
@@ -1081,18 +1081,18 @@ static void
efx_farch_handle_tx_flush_done(struct efx_nic *efx, efx_qword_t *event)
{
	struct efx_tx_queue *tx_queue;
	struct efx_channel *channel;
	int qid;

	qid = EFX_QWORD_FIELD(*event, FSF_AZ_DRIVER_EV_SUBDATA);
	if (qid < EFX_MAX_TXQ_PER_CHANNEL * (efx->n_tx_channels + efx->n_extra_tx_channels)) {
		tx_queue = efx_get_tx_queue(efx, qid / EFX_MAX_TXQ_PER_CHANNEL,
					    qid % EFX_MAX_TXQ_PER_CHANNEL);
		if (atomic_cmpxchg(&tx_queue->flush_outstanding, 1, 0)) {
		channel = efx_get_tx_channel(efx, qid / EFX_MAX_TXQ_PER_CHANNEL);
		tx_queue = channel->tx_queue + (qid % EFX_MAX_TXQ_PER_CHANNEL);
		if (atomic_cmpxchg(&tx_queue->flush_outstanding, 1, 0))
			efx_farch_magic_event(tx_queue->channel,
					      EFX_CHANNEL_MAGIC_TX_DRAIN(tx_queue));
	}
}
}

/* If this flush done event corresponds to a &struct efx_rx_queue: If the flush
 * was successful then send an %EFX_CHANNEL_MAGIC_RX_DRAIN, otherwise add