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

Commit 525da907 authored by Ben Hutchings's avatar Ben Hutchings
Browse files

sfc: Distinguish queue lookup from test for queue existence



efx_channel_get_{rx,tx}_queue() currently return NULL if the channel
isn't used for traffic in that direction.  In most cases this is a
bug, but some callers rely on it as an existence test.

Add existence test functions efx_channel_has_{rx_queue,tx_queues}()
and use them as appropriate.

Change efx_channel_get_{rx,tx}_queue() to assert that the requested
queue exists.

Remove now-redundant initialisation from efx_set_channels().

Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
parent 60031fcc
Loading
Loading
Loading
Loading
+2 −15
Original line number Diff line number Diff line
@@ -1271,21 +1271,8 @@ static void efx_remove_interrupts(struct efx_nic *efx)

static void efx_set_channels(struct efx_nic *efx)
{
	struct efx_channel *channel;
	struct efx_tx_queue *tx_queue;

	efx->tx_channel_offset =
		separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0;

	/* Channel pointers were set in efx_init_struct() but we now
	 * need to clear them for TX queues in any RX-only channels. */
	efx_for_each_channel(channel, efx) {
		if (channel->channel - efx->tx_channel_offset >=
		    efx->n_tx_channels) {
			efx_for_each_channel_tx_queue(tx_queue, channel)
				tx_queue->channel = NULL;
		}
	}
}

static int efx_probe_nic(struct efx_nic *efx)
@@ -1531,9 +1518,9 @@ void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs,
	efx->irq_rx_adaptive = rx_adaptive;
	efx->irq_rx_moderation = rx_ticks;
	efx_for_each_channel(channel, efx) {
		if (efx_channel_get_rx_queue(channel))
		if (efx_channel_has_rx_queue(channel))
			channel->irq_moderation = rx_ticks;
		else if (efx_channel_get_tx_queue(channel, 0))
		else if (efx_channel_has_tx_queues(channel))
			channel->irq_moderation = tx_ticks;
	}
}
+3 −3
Original line number Diff line number Diff line
@@ -631,7 +631,7 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev,
	/* Find lowest IRQ moderation across all used TX queues */
	coalesce->tx_coalesce_usecs_irq = ~((u32) 0);
	efx_for_each_channel(channel, efx) {
		if (!efx_channel_get_tx_queue(channel, 0))
		if (!efx_channel_has_tx_queues(channel))
			continue;
		if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) {
			if (channel->channel < efx->n_rx_channels)
@@ -676,8 +676,8 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev,

	/* If the channel is shared only allow RX parameters to be set */
	efx_for_each_channel(channel, efx) {
		if (efx_channel_get_rx_queue(channel) &&
		    efx_channel_get_tx_queue(channel, 0) &&
		if (efx_channel_has_rx_queue(channel) &&
		    efx_channel_has_tx_queues(channel) &&
		    tx_usecs) {
			netif_err(efx, drv, efx->net_dev, "Channel is shared. "
				  "Only RX coalescing may be set\n");
+28 −11
Original line number Diff line number Diff line
@@ -938,18 +938,27 @@ efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type)
	return &efx->channel[efx->tx_channel_offset + index]->tx_queue[type];
}

static inline bool efx_channel_has_tx_queues(struct efx_channel *channel)
{
	return channel->channel - channel->efx->tx_channel_offset <
		channel->efx->n_tx_channels;
}

static inline struct efx_tx_queue *
efx_channel_get_tx_queue(struct efx_channel *channel, unsigned type)
{
	struct efx_tx_queue *tx_queue = channel->tx_queue;
	EFX_BUG_ON_PARANOID(type >= EFX_TXQ_TYPES);
	return tx_queue->channel ? tx_queue + type : NULL;
	EFX_BUG_ON_PARANOID(!efx_channel_has_tx_queues(channel) ||
			    type >= EFX_TXQ_TYPES);
	return &channel->tx_queue[type];
}

/* Iterate over all TX queues belonging to a channel */
#define efx_for_each_channel_tx_queue(_tx_queue, _channel)		\
	for (_tx_queue = efx_channel_get_tx_queue(channel, 0);		\
	     _tx_queue && _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES; \
	if (!efx_channel_has_tx_queues(_channel))			\
		;							\
	else								\
		for (_tx_queue = (_channel)->tx_queue;			\
		     _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES;	\
		     _tx_queue++)

static inline struct efx_rx_queue *
@@ -959,16 +968,24 @@ efx_get_rx_queue(struct efx_nic *efx, unsigned index)
	return &efx->channel[index]->rx_queue;
}

static inline bool efx_channel_has_rx_queue(struct efx_channel *channel)
{
	return channel->channel < channel->efx->n_rx_channels;
}

static inline struct efx_rx_queue *
efx_channel_get_rx_queue(struct efx_channel *channel)
{
	return channel->channel < channel->efx->n_rx_channels ?
		&channel->rx_queue : NULL;
	EFX_BUG_ON_PARANOID(!efx_channel_has_rx_queue(channel));
	return &channel->rx_queue;
}

/* Iterate over all RX queues belonging to a channel */
#define efx_for_each_channel_rx_queue(_rx_queue, _channel)		\
	for (_rx_queue = efx_channel_get_rx_queue(channel);		\
	if (!efx_channel_has_rx_queue(_channel))			\
		;							\
	else								\
		for (_rx_queue = &(_channel)->rx_queue;			\
		     _rx_queue;						\
		     _rx_queue = NULL)