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

Merge branch 'sfc-prerequisites-for-EF100-driver-part-3'

Edward Cree says:

====================
sfc: prerequisites for EF100 driver, part 3

Continuing on from [1] and [2], this series assembles the last pieces
 of the common codebase that will be used by the forthcoming EF100
 driver.
Patch #1 also adds a minor feature to EF10 (setting MTU on VFs) since
 EF10 supports the same MCDI extension which that feature will use on
 EF100.
Patches #5 & #7, while they should have no externally-visible effect
 on driver functionality, change how that functionality is implemented
 and how the driver represents TXQ configuration internally, so are
 not mere cleanup/refactoring like most of these prerequisites have
 (from the perspective of the existing sfc driver) been.

Changes in v2:
* Patch #1: use efx_mcdi_set_mtu() directly, instead of as a fallback,
  in the mtu_only case (Jakub)
* Patch #3: fix symbol collision in non-modular builds by renaming
  interrupt_mode to efx_interrupt_mode (kernel test robot)
* Patch #6: check for failure of netif_set_real_num_[tr]x_queues (Jakub)
* Patch #12: cleaner solution for ethtool drvinfo (Jakub, David)

[1]: https://lore.kernel.org/netdev/20200629.173812.1532344417590172093.davem@davemloft.net/T/
[2]: https://lore.kernel.org/netdev/20200630.130923.402514193016248355.davem@davemloft.net/T/


====================

Reviewed-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e44f65fd b6d02dd2
Loading
Loading
Loading
Loading
+16 −60
Original line number Diff line number Diff line
@@ -552,8 +552,6 @@ static int efx_ef10_probe(struct efx_nic *efx)
	}
	nic_data->warm_boot_count = rc;

	efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID;

	/* In case we're recovering from a crash (kexec), we want to
	 * cancel any outstanding request by the previous user of this
	 * function.  We send a special message using the least
@@ -600,6 +598,7 @@ static int efx_ef10_probe(struct efx_nic *efx)
	 * However, until we use TX option descriptors we need two TX queues
	 * per channel.
	 */
	efx->tx_queues_per_channel = 2;
	efx->max_vis = efx_ef10_mem_map_size(efx) / efx->vi_stride;
	if (!efx->max_vis) {
		netif_err(efx, drv, efx->net_dev, "error determining max VIs\n");
@@ -607,7 +606,7 @@ static int efx_ef10_probe(struct efx_nic *efx)
		goto fail5;
	}
	efx->max_channels = min_t(unsigned int, EFX_MAX_CHANNELS,
				  efx->max_vis / EFX_TXQ_TYPES);
				  efx->max_vis / efx->tx_queues_per_channel);
	efx->max_tx_channels = efx->max_channels;
	if (WARN_ON(efx->max_channels == 0)) {
		rc = -EIO;
@@ -1120,17 +1119,17 @@ static int efx_ef10_alloc_vis(struct efx_nic *efx,
 */
static int efx_ef10_dimension_resources(struct efx_nic *efx)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	unsigned int uc_mem_map_size, wc_mem_map_size;
	unsigned int min_vis = max(EFX_TXQ_TYPES,
	unsigned int min_vis = max_t(unsigned int, efx->tx_queues_per_channel,
				     efx_separate_tx_channels ? 2 : 1);
	unsigned int channel_vis, pio_write_vi_base, max_vis;
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	unsigned int uc_mem_map_size, wc_mem_map_size;
	void __iomem *membase;
	int rc;

	channel_vis = max(efx->n_channels,
			  ((efx->n_tx_channels + efx->n_extra_tx_channels) *
			   EFX_TXQ_TYPES) +
			   efx->tx_queues_per_channel) +
			   efx->n_xdp_channels * efx->xdp_tx_per_channel);
	if (efx->max_vis && efx->max_vis < channel_vis) {
		netif_dbg(efx, drv, efx->net_dev,
@@ -1219,7 +1218,7 @@ static int efx_ef10_dimension_resources(struct efx_nic *efx)
		 */
		efx->max_channels = nic_data->n_allocated_vis;
		efx->max_tx_channels =
			nic_data->n_allocated_vis / EFX_TXQ_TYPES;
			nic_data->n_allocated_vis / efx->tx_queues_per_channel;

		efx_mcdi_free_vis(efx);
		return -EAGAIN;
@@ -2243,7 +2242,7 @@ static u32 efx_ef10_tso_versions(struct efx_nic *efx)

static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
{
	bool csum_offload = tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD;
	bool csum_offload = tx_queue->label & EFX_TXQ_TYPE_OFFLOAD;
	struct efx_channel *channel = tx_queue->channel;
	struct efx_nic *efx = tx_queue->efx;
	struct efx_ef10_nic_data *nic_data;
@@ -3116,44 +3115,6 @@ static void efx_ef10_ev_test_generate(struct efx_channel *channel)
	netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
}

static int efx_ef10_fini_dmaq(struct efx_nic *efx)
{
	struct efx_tx_queue *tx_queue;
	struct efx_rx_queue *rx_queue;
	struct efx_channel *channel;
	int pending;

	/* If the MC has just rebooted, the TX/RX queues will have already been
	 * torn down, but efx->active_queues needs to be set to zero.
	 */
	if (efx->must_realloc_vis) {
		atomic_set(&efx->active_queues, 0);
		return 0;
	}

	/* Do not attempt to write to the NIC during EEH recovery */
	if (efx->state != STATE_RECOVERY) {
		efx_for_each_channel(channel, efx) {
			efx_for_each_channel_rx_queue(rx_queue, channel)
				efx_mcdi_rx_fini(rx_queue);
			efx_for_each_channel_tx_queue(tx_queue, channel)
				efx_mcdi_tx_fini(tx_queue);
		}

		wait_event_timeout(efx->flush_wq,
				   atomic_read(&efx->active_queues) == 0,
				   msecs_to_jiffies(EFX_MAX_FLUSH_TIME));
		pending = atomic_read(&efx->active_queues);
		if (pending) {
			netif_err(efx, hw, efx->net_dev, "failed to flush %d queues\n",
				  pending);
			return -ETIMEDOUT;
		}
	}

	return 0;
}

static void efx_ef10_prepare_flr(struct efx_nic *efx)
{
	atomic_set(&efx->active_queues, 0);
@@ -3306,18 +3267,15 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
	return rc;
}

static int efx_ef10_mac_reconfigure(struct efx_nic *efx)
static int efx_ef10_mac_reconfigure(struct efx_nic *efx, bool mtu_only)
{
	efx_mcdi_filter_sync_rx_mode(efx);

	return efx_mcdi_set_mac(efx);
}
	WARN_ON(!mutex_is_locked(&efx->mac_lock));

static int efx_ef10_mac_reconfigure_vf(struct efx_nic *efx)
{
	efx_mcdi_filter_sync_rx_mode(efx);

	return 0;
	if (mtu_only && efx_has_cap(efx, SET_MAC_ENHANCED))
		return efx_mcdi_set_mtu(efx);
	return efx_mcdi_set_mac(efx);
}

static int efx_ef10_start_bist(struct efx_nic *efx, u32 bist_type)
@@ -4028,7 +3986,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
	.reset = efx_ef10_reset,
	.probe_port = efx_mcdi_port_probe,
	.remove_port = efx_mcdi_port_remove,
	.fini_dmaq = efx_ef10_fini_dmaq,
	.fini_dmaq = efx_fini_dmaq,
	.prepare_flr = efx_ef10_prepare_flr,
	.finish_flr = efx_port_dummy_op_void,
	.describe_stats = efx_ef10_describe_stats,
@@ -4038,7 +3996,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
	.stop_stats = efx_port_dummy_op_void,
	.set_id_led = efx_mcdi_set_id_led,
	.push_irq_moderation = efx_ef10_push_irq_moderation,
	.reconfigure_mac = efx_ef10_mac_reconfigure_vf,
	.reconfigure_mac = efx_ef10_mac_reconfigure,
	.check_mac_fault = efx_mcdi_mac_check_fault,
	.reconfigure_port = efx_mcdi_port_reconfigure,
	.get_wol = efx_ef10_get_wol_vf,
@@ -4111,7 +4069,6 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
	.can_rx_scatter = true,
	.always_rx_scatter = true,
	.min_interrupt_mode = EFX_INT_MODE_MSIX,
	.max_interrupt_mode = EFX_INT_MODE_MSIX,
	.timer_period_max = 1 << ERF_DD_EVQ_IND_TIMER_VAL_WIDTH,
	.offload_features = EF10_OFFLOAD_FEATURES,
	.mcdi_max_ver = 2,
@@ -4137,7 +4094,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
	.reset = efx_ef10_reset,
	.probe_port = efx_mcdi_port_probe,
	.remove_port = efx_mcdi_port_remove,
	.fini_dmaq = efx_ef10_fini_dmaq,
	.fini_dmaq = efx_fini_dmaq,
	.prepare_flr = efx_ef10_prepare_flr,
	.finish_flr = efx_port_dummy_op_void,
	.describe_stats = efx_ef10_describe_stats,
@@ -4248,7 +4205,6 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
	.always_rx_scatter = true,
	.option_descriptors = true,
	.min_interrupt_mode = EFX_INT_MODE_LEGACY,
	.max_interrupt_mode = EFX_INT_MODE_MSIX,
	.timer_period_max = 1 << ERF_DD_EVQ_IND_TIMER_VAL_WIDTH,
	.offload_features = EF10_OFFLOAD_FEATURES,
	.mcdi_max_ver = 2,
+7 −7
Original line number Diff line number Diff line
@@ -64,6 +64,13 @@ void efx_get_udp_tunnel_type_name(u16 type, char *buf, size_t buflen)
 *
 *************************************************************************/

module_param_named(interrupt_mode, efx_interrupt_mode, uint, 0444);
MODULE_PARM_DESC(interrupt_mode,
		 "Interrupt mode (0=>MSIX 1=>MSI 2=>legacy)");

module_param(rss_cpus, uint, 0444);
MODULE_PARM_DESC(rss_cpus, "Number of CPUs to use for Receive-Side Scaling");

/*
 * Use separate channels for TX and RX events
 *
@@ -169,10 +176,6 @@ static int efx_init_port(struct efx_nic *efx)

	efx->port_initialized = true;

	/* Reconfigure the MAC before creating dma queues (required for
	 * Falcon/A1 where RX_INGR_EN/TX_DRAIN_EN isn't supported) */
	efx_mac_reconfigure(efx);

	/* Ensure the PHY advertises the correct flow control settings */
	rc = efx->phy_op->reconfigure(efx);
	if (rc && rc != -EPERM)
@@ -333,9 +336,6 @@ static int efx_probe_nic(struct efx_nic *efx)
				    sizeof(efx->rss_context.rx_hash_key));
	efx_set_default_rx_indir_table(efx, &efx->rss_context);

	netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
	netif_set_real_num_rx_queues(efx->net_dev, efx->n_rx_channels);

	/* Initialise the interrupt moderation settings */
	efx->irq_mod_step_us = DIV_ROUND_UP(efx->timer_quantum_ns, 1000);
	efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true,
+39 −27
Original line number Diff line number Diff line
@@ -23,10 +23,7 @@
 * 1 => MSI
 * 2 => legacy
 */
static unsigned int interrupt_mode;
module_param(interrupt_mode, uint, 0444);
MODULE_PARM_DESC(interrupt_mode,
		 "Interrupt mode (0=>MSIX 1=>MSI 2=>legacy)");
unsigned int efx_interrupt_mode = EFX_INT_MODE_MSIX;

/* This is the requested number of CPUs to use for Receive-Side Scaling (RSS),
 * i.e. the number of CPUs among which we may distribute simultaneous
@@ -35,9 +32,7 @@ MODULE_PARM_DESC(interrupt_mode,
 * Cards without MSI-X will only target one CPU via legacy or MSI interrupt.
 * The default (0) means to assign an interrupt to each core.
 */
static unsigned int rss_cpus;
module_param(rss_cpus, uint, 0444);
MODULE_PARM_DESC(rss_cpus, "Number of CPUs to use for Receive-Side Scaling");
unsigned int rss_cpus;

static unsigned int irq_adapt_low_thresh = 8000;
module_param(irq_adapt_low_thresh, uint, 0644);
@@ -529,7 +524,8 @@ efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel)
	for (j = 0; j < EFX_TXQ_TYPES; j++) {
		tx_queue = &channel->tx_queue[j];
		tx_queue->efx = efx;
		tx_queue->queue = i * EFX_TXQ_TYPES + j;
		tx_queue->queue = -1;
		tx_queue->label = j;
		tx_queue->channel = channel;
	}

@@ -557,14 +553,8 @@ int efx_init_channels(struct efx_nic *efx)
	}

	/* Higher numbered interrupt modes are less capable! */
	if (WARN_ON_ONCE(efx->type->max_interrupt_mode >
			 efx->type->min_interrupt_mode)) {
		return -EIO;
	}
	efx->interrupt_mode = max(efx->type->max_interrupt_mode,
				  interrupt_mode);
	efx->interrupt_mode = min(efx->type->min_interrupt_mode,
				  interrupt_mode);
				  efx_interrupt_mode);

	efx->max_channels = EFX_MAX_CHANNELS;
	efx->max_tx_channels = EFX_MAX_CHANNELS;
@@ -737,7 +727,7 @@ void efx_remove_channel(struct efx_channel *channel)

	efx_for_each_channel_rx_queue(rx_queue, channel)
		efx_remove_rx_queue(rx_queue);
	efx_for_each_possible_channel_tx_queue(tx_queue, channel)
	efx_for_each_channel_tx_queue(tx_queue, channel)
		efx_remove_tx_queue(tx_queue);
	efx_remove_eventq(channel);
	channel->type->post_remove(channel);
@@ -864,9 +854,11 @@ int efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)

int efx_set_channels(struct efx_nic *efx)
{
	struct efx_channel *channel;
	struct efx_tx_queue *tx_queue;
	struct efx_channel *channel;
	unsigned int next_queue = 0;
	int xdp_queue_number;
	int rc;

	efx->tx_channel_offset =
		efx_separate_tx_channels ?
@@ -894,18 +886,38 @@ int efx_set_channels(struct efx_nic *efx)
		else
			channel->rx_queue.core_index = -1;

		if (channel->channel >= efx->tx_channel_offset) {
			if (efx_channel_is_xdp_tx(channel)) {
				efx_for_each_channel_tx_queue(tx_queue, channel) {
			tx_queue->queue -= (efx->tx_channel_offset *
					    EFX_TXQ_TYPES);

			if (efx_channel_is_xdp_tx(channel) &&
			    xdp_queue_number < efx->xdp_tx_queue_count) {
					tx_queue->queue = next_queue++;
					netif_dbg(efx, drv, efx->net_dev, "Channel %u TXQ %u is XDP %u, HW %u\n",
						  channel->channel, tx_queue->label,
						  xdp_queue_number, tx_queue->queue);
					/* We may have a few left-over XDP TX
					 * queues owing to xdp_tx_queue_count
					 * not dividing evenly by EFX_TXQ_TYPES.
					 * We still allocate and probe those
					 * TXQs, but never use them.
					 */
					if (xdp_queue_number < efx->xdp_tx_queue_count)
						efx->xdp_tx_queues[xdp_queue_number] = tx_queue;
					xdp_queue_number++;
				}
			} else {
				efx_for_each_channel_tx_queue(tx_queue, channel) {
					tx_queue->queue = next_queue++;
					netif_dbg(efx, drv, efx->net_dev, "Channel %u TXQ %u is HW %u\n",
						  channel->channel, tx_queue->label,
						  tx_queue->queue);
				}
			}
		}
	return 0;
	}

	rc = netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
	if (rc)
		return rc;
	return netif_set_real_num_rx_queues(efx->net_dev, efx->n_rx_channels);
}

bool efx_default_channel_want_txqs(struct efx_channel *channel)
@@ -1101,7 +1113,7 @@ void efx_stop_channels(struct efx_nic *efx)
	efx_for_each_channel(channel, efx) {
		efx_for_each_channel_rx_queue(rx_queue, channel)
			efx_fini_rx_queue(rx_queue);
		efx_for_each_possible_channel_tx_queue(tx_queue, channel)
		efx_for_each_channel_tx_queue(tx_queue, channel)
			efx_fini_tx_queue(tx_queue);
	}
}
+3 −0
Original line number Diff line number Diff line
@@ -11,6 +11,9 @@
#ifndef EFX_CHANNELS_H
#define EFX_CHANNELS_H

extern unsigned int efx_interrupt_mode;
extern unsigned int rss_cpus;

int efx_probe_interrupts(struct efx_nic *efx);
void efx_remove_interrupts(struct efx_nic *efx);
int efx_soft_enable_interrupts(struct efx_nic *efx);
+8 −6
Original line number Diff line number Diff line
@@ -139,11 +139,11 @@ void efx_destroy_reset_workqueue(void)
/* We assume that efx->type->reconfigure_mac will always try to sync RX
 * filters and therefore needs to read-lock the filter table against freeing
 */
void efx_mac_reconfigure(struct efx_nic *efx)
void efx_mac_reconfigure(struct efx_nic *efx, bool mtu_only)
{
	if (efx->type->reconfigure_mac) {
		down_read(&efx->filter_sem);
		efx->type->reconfigure_mac(efx);
		efx->type->reconfigure_mac(efx, mtu_only);
		up_read(&efx->filter_sem);
	}
}
@@ -158,7 +158,7 @@ static void efx_mac_work(struct work_struct *data)

	mutex_lock(&efx->mac_lock);
	if (efx->port_enabled)
		efx_mac_reconfigure(efx);
		efx_mac_reconfigure(efx, false);
	mutex_unlock(&efx->mac_lock);
}

@@ -190,7 +190,7 @@ int efx_set_mac_address(struct net_device *net_dev, void *data)

	/* Reconfigure the MAC */
	mutex_lock(&efx->mac_lock);
	efx_mac_reconfigure(efx);
	efx_mac_reconfigure(efx, false);
	mutex_unlock(&efx->mac_lock);

	return 0;
@@ -304,7 +304,7 @@ int efx_change_mtu(struct net_device *net_dev, int new_mtu)

	mutex_lock(&efx->mac_lock);
	net_dev->mtu = new_mtu;
	efx_mac_reconfigure(efx);
	efx_mac_reconfigure(efx, true);
	mutex_unlock(&efx->mac_lock);

	efx_start_all(efx);
@@ -486,7 +486,7 @@ static void efx_start_port(struct efx_nic *efx)
	efx->port_enabled = true;

	/* Ensure MAC ingress/egress is enabled */
	efx_mac_reconfigure(efx);
	efx_mac_reconfigure(efx, false);

	mutex_unlock(&efx->mac_lock);
}
@@ -1017,6 +1017,7 @@ int efx_init_struct(struct efx_nic *efx,
	efx->rx_packet_ts_offset =
		efx->type->rx_ts_offset - efx->type->rx_prefix_size;
	INIT_LIST_HEAD(&efx->rss_context.list);
	efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID;
	mutex_init(&efx->rss_lock);
	efx->vport_id = EVB_PORT_ID_ASSIGNED;
	spin_lock_init(&efx->stats_lock);
@@ -1036,6 +1037,7 @@ int efx_init_struct(struct efx_nic *efx,
	INIT_WORK(&efx->mac_work, efx_mac_work);
	init_waitqueue_head(&efx->flush_wq);

	efx->tx_queues_per_channel = 1;
	efx->rxq_entries = EFX_DEFAULT_DMAQ_SIZE;
	efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE;

Loading