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

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



Edward Cree says:

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

This continues the work started by Alex Maftei <amaftei@solarflare.com>
 in the series "sfc: code refactoring", "sfc: more code refactoring",
 "sfc: even more code refactoring" and "sfc: refactor mcdi filtering
 code", to prepare for a new driver which will share much of the code
 to support the new EF100 family of Solarflare/Xilinx NICs.
After this series, there will be approximately two more of these
 'prerequisites' series, followed by the sfc_ef100 driver itself.

v2: fix reverse xmas tree in patch 5.  (Left the cases in patches 7,
 9 and 14 alone as those are all in pure movement of existing code.)
====================

Reviewed-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5f035af7 4d9c0a2d
Loading
Loading
Loading
Loading
+29 −5
Original line number Diff line number Diff line
@@ -282,7 +282,10 @@ typedef union efx_oword {
				 field7, value7,			\
				 field8, value8,			\
				 field9, value9,			\
				 field10, value10)			\
				 field10, value10,			\
				 field11, value11,			\
				 field12, value12,			\
				 field13, value13)			\
	(EFX_INSERT_FIELD_NATIVE((min), (max), field1, (value1)) |	\
	 EFX_INSERT_FIELD_NATIVE((min), (max), field2, (value2)) |	\
	 EFX_INSERT_FIELD_NATIVE((min), (max), field3, (value3)) |	\
@@ -292,7 +295,10 @@ typedef union efx_oword {
	 EFX_INSERT_FIELD_NATIVE((min), (max), field7, (value7)) |	\
	 EFX_INSERT_FIELD_NATIVE((min), (max), field8, (value8)) |	\
	 EFX_INSERT_FIELD_NATIVE((min), (max), field9, (value9)) |	\
	 EFX_INSERT_FIELD_NATIVE((min), (max), field10, (value10)))
	 EFX_INSERT_FIELD_NATIVE((min), (max), field10, (value10)) |	\
	 EFX_INSERT_FIELD_NATIVE((min), (max), field11, (value11)) |	\
	 EFX_INSERT_FIELD_NATIVE((min), (max), field12, (value12)) |	\
	 EFX_INSERT_FIELD_NATIVE((min), (max), field13, (value13)))

#define EFX_INSERT_FIELDS64(...)				\
	cpu_to_le64(EFX_INSERT_FIELDS_NATIVE(__VA_ARGS__))
@@ -334,7 +340,13 @@ typedef union efx_oword {
#endif

/* Populate an octword field with various numbers of arguments */
#define EFX_POPULATE_OWORD_10 EFX_POPULATE_OWORD
#define EFX_POPULATE_OWORD_13 EFX_POPULATE_OWORD
#define EFX_POPULATE_OWORD_12(oword, ...) \
	EFX_POPULATE_OWORD_13(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
#define EFX_POPULATE_OWORD_11(oword, ...) \
	EFX_POPULATE_OWORD_12(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
#define EFX_POPULATE_OWORD_10(oword, ...) \
	EFX_POPULATE_OWORD_11(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
#define EFX_POPULATE_OWORD_9(oword, ...) \
	EFX_POPULATE_OWORD_10(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
#define EFX_POPULATE_OWORD_8(oword, ...) \
@@ -363,7 +375,13 @@ typedef union efx_oword {
			     EFX_DWORD_3, 0xffffffff)

/* Populate a quadword field with various numbers of arguments */
#define EFX_POPULATE_QWORD_10 EFX_POPULATE_QWORD
#define EFX_POPULATE_QWORD_13 EFX_POPULATE_QWORD
#define EFX_POPULATE_QWORD_12(qword, ...) \
	EFX_POPULATE_QWORD_13(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
#define EFX_POPULATE_QWORD_11(qword, ...) \
	EFX_POPULATE_QWORD_12(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
#define EFX_POPULATE_QWORD_10(qword, ...) \
	EFX_POPULATE_QWORD_11(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
#define EFX_POPULATE_QWORD_9(qword, ...) \
	EFX_POPULATE_QWORD_10(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
#define EFX_POPULATE_QWORD_8(qword, ...) \
@@ -390,7 +408,13 @@ typedef union efx_oword {
			     EFX_DWORD_1, 0xffffffff)

/* Populate a dword field with various numbers of arguments */
#define EFX_POPULATE_DWORD_10 EFX_POPULATE_DWORD
#define EFX_POPULATE_DWORD_13 EFX_POPULATE_DWORD
#define EFX_POPULATE_DWORD_12(dword, ...) \
	EFX_POPULATE_DWORD_13(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
#define EFX_POPULATE_DWORD_11(dword, ...) \
	EFX_POPULATE_DWORD_12(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
#define EFX_POPULATE_DWORD_10(dword, ...) \
	EFX_POPULATE_DWORD_11(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
#define EFX_POPULATE_DWORD_9(dword, ...) \
	EFX_POPULATE_DWORD_10(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
#define EFX_POPULATE_DWORD_8(dword, ...) \
+50 −50
Original line number Diff line number Diff line
@@ -601,10 +601,14 @@ static int efx_ef10_probe(struct efx_nic *efx)
	 * However, until we use TX option descriptors we need two TX queues
	 * per channel.
	 */
	efx->max_channels = min_t(unsigned int,
				  EFX_MAX_CHANNELS,
				  efx_ef10_mem_map_size(efx) /
				  (efx->vi_stride * EFX_TXQ_TYPES));
	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");
		rc = -EIO;
		goto fail5;
	}
	efx->max_channels = min_t(unsigned int, EFX_MAX_CHANNELS,
				  efx->max_vis / EFX_TXQ_TYPES);
	efx->max_tx_channels = efx->max_channels;
	if (WARN_ON(efx->max_channels == 0)) {
		rc = -EIO;
@@ -1129,6 +1133,12 @@ static int efx_ef10_dimension_resources(struct efx_nic *efx)
			  ((efx->n_tx_channels + efx->n_extra_tx_channels) *
			   EFX_TXQ_TYPES) +
			   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,
			  "Reducing channel VIs from %u to %u\n",
			  channel_vis, efx->max_vis);
		channel_vis = efx->max_vis;
	}

#ifdef EFX_USE_PIO
	/* Try to allocate PIO buffers if wanted and if the full
@@ -1269,6 +1279,14 @@ static int efx_ef10_dimension_resources(struct efx_nic *efx)
	return 0;
}

static void efx_ef10_fini_nic(struct efx_nic *efx)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;

	kfree(nic_data->mc_stats);
	nic_data->mc_stats = NULL;
}

static int efx_ef10_init_nic(struct efx_nic *efx)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
@@ -1290,6 +1308,11 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
		efx->must_realloc_vis = false;
	}

	nic_data->mc_stats = kmalloc(efx->num_mac_stats * sizeof(__le64),
				     GFP_KERNEL);
	if (!nic_data->mc_stats)
		return -ENOMEM;

	if (nic_data->must_restore_piobufs && nic_data->n_piobufs) {
		rc = efx_ef10_alloc_piobufs(efx, nic_data->n_piobufs);
		if (rc == 0) {
@@ -1410,8 +1433,6 @@ static int efx_ef10_reset(struct efx_nic *efx, enum reset_type reset_type)
	{ NULL, 64, 8 * MC_CMD_MAC_ ## mcdi_name }
#define EF10_OTHER_STAT(ext_name)				\
	[EF10_STAT_ ## ext_name] = { #ext_name, 0, 0 }
#define GENERIC_SW_STAT(ext_name)				\
	[GENERIC_STAT_ ## ext_name] = { #ext_name, 0, 0 }

static const struct efx_hw_stat_desc efx_ef10_stat_desc[EF10_STAT_COUNT] = {
	EF10_DMA_STAT(port_tx_bytes, TX_BYTES),
@@ -1455,8 +1476,8 @@ static const struct efx_hw_stat_desc efx_ef10_stat_desc[EF10_STAT_COUNT] = {
	EF10_DMA_STAT(port_rx_align_error, RX_ALIGN_ERROR_PKTS),
	EF10_DMA_STAT(port_rx_length_error, RX_LENGTH_ERROR_PKTS),
	EF10_DMA_STAT(port_rx_nodesc_drops, RX_NODESC_DROPS),
	GENERIC_SW_STAT(rx_nodesc_trunc),
	GENERIC_SW_STAT(rx_noskb_drops),
	EFX_GENERIC_SW_STAT(rx_nodesc_trunc),
	EFX_GENERIC_SW_STAT(rx_noskb_drops),
	EF10_DMA_STAT(port_rx_pm_trunc_bb_overflow, PM_TRUNC_BB_OVERFLOW),
	EF10_DMA_STAT(port_rx_pm_discard_bb_overflow, PM_DISCARD_BB_OVERFLOW),
	EF10_DMA_STAT(port_rx_pm_trunc_vfifo_full, PM_TRUNC_VFIFO_FULL),
@@ -1765,55 +1786,42 @@ static size_t efx_ef10_update_stats_common(struct efx_nic *efx, u64 *full_stats,
	return stats_count;
}

static int efx_ef10_try_update_nic_stats_pf(struct efx_nic *efx)
static size_t efx_ef10_update_stats_pf(struct efx_nic *efx, u64 *full_stats,
				       struct rtnl_link_stats64 *core_stats)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	DECLARE_BITMAP(mask, EF10_STAT_COUNT);
	__le64 generation_start, generation_end;
	u64 *stats = nic_data->stats;
	__le64 *dma_stats;

	efx_ef10_get_stat_mask(efx, mask);

	dma_stats = efx->stats_buffer.addr;

	generation_end = dma_stats[efx->num_mac_stats - 1];
	if (generation_end == EFX_MC_STATS_GENERATION_INVALID)
		return 0;
	rmb();
	efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT, mask,
			     stats, efx->stats_buffer.addr, false);
	rmb();
	generation_start = dma_stats[MC_CMD_MAC_GENERATION_START];
	if (generation_end != generation_start)
		return -EAGAIN;
	efx_nic_copy_stats(efx, nic_data->mc_stats);
	efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT,
			     mask, stats, nic_data->mc_stats, false);

	/* Update derived statistics */
	efx_nic_fix_nodesc_drop_stat(efx,
				     &stats[EF10_STAT_port_rx_nodesc_drops]);
	/* MC Firmware reads RX_BYTES and RX_GOOD_BYTES from the MAC.
	 * It then calculates RX_BAD_BYTES and DMAs it to us with RX_BYTES.
	 * We report these as port_rx_ stats. We are not given RX_GOOD_BYTES.
	 * Here we calculate port_rx_good_bytes.
	 */
	stats[EF10_STAT_port_rx_good_bytes] =
		stats[EF10_STAT_port_rx_bytes] -
		stats[EF10_STAT_port_rx_bytes_minus_good_bytes];

	/* The asynchronous reads used to calculate RX_BAD_BYTES in
	 * MC Firmware are done such that we should not see an increase in
	 * RX_BAD_BYTES when a good packet has arrived. Unfortunately this
	 * does mean that the stat can decrease at times. Here we do not
	 * update the stat unless it has increased or has gone to zero
	 * (In the case of the NIC rebooting).
	 * Please see Bug 33781 for a discussion of why things work this way.
	 */
	efx_update_diff_stat(&stats[EF10_STAT_port_rx_bad_bytes],
			     stats[EF10_STAT_port_rx_bytes_minus_good_bytes]);
	efx_update_sw_stats(efx, stats);
	return 0;
}


static size_t efx_ef10_update_stats_pf(struct efx_nic *efx, u64 *full_stats,
				       struct rtnl_link_stats64 *core_stats)
{
	int retry;

	/* If we're unlucky enough to read statistics during the DMA, wait
	 * up to 10ms for it to finish (typically takes <500us)
	 */
	for (retry = 0; retry < 100; ++retry) {
		if (efx_ef10_try_update_nic_stats_pf(efx) == 0)
			break;
		udelay(100);
	}

	return efx_ef10_update_stats_common(efx, full_stats, core_stats);
}
@@ -3109,14 +3117,6 @@ fail:
	netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
}

void efx_ef10_handle_drain_event(struct efx_nic *efx)
{
	if (atomic_dec_and_test(&efx->active_queues))
		wake_up(&efx->flush_wq);

	WARN_ON(atomic_read(&efx->active_queues) < 0);
}

static int efx_ef10_fini_dmaq(struct efx_nic *efx)
{
	struct efx_tx_queue *tx_queue;
@@ -4023,7 +4023,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
	.remove = efx_ef10_remove,
	.dimension_resources = efx_ef10_dimension_resources,
	.init = efx_ef10_init_nic,
	.fini = efx_port_dummy_op_void,
	.fini = efx_ef10_fini_nic,
	.map_reset_reason = efx_ef10_map_reset_reason,
	.map_reset_flags = efx_ef10_map_reset_flags,
	.reset = efx_ef10_reset,
@@ -4132,7 +4132,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
	.remove = efx_ef10_remove,
	.dimension_resources = efx_ef10_dimension_resources,
	.init = efx_ef10_init_nic,
	.fini = efx_port_dummy_op_void,
	.fini = efx_ef10_fini_nic,
	.map_reset_reason = efx_ef10_map_reset_reason,
	.map_reset_flags = efx_ef10_map_reset_flags,
	.reset = efx_ef10_reset,
+2 −117
Original line number Diff line number Diff line
@@ -133,30 +133,6 @@ static int efx_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **xdpfs,
 *
 **************************************************************************/

/* Equivalent to efx_link_set_advertising with all-zeroes, except does not
 * force the Autoneg bit on.
 */
void efx_link_clear_advertising(struct efx_nic *efx)
{
	bitmap_zero(efx->link_advertising, __ETHTOOL_LINK_MODE_MASK_NBITS);
	efx->wanted_fc &= ~(EFX_FC_TX | EFX_FC_RX);
}

void efx_link_set_wanted_fc(struct efx_nic *efx, u8 wanted_fc)
{
	efx->wanted_fc = wanted_fc;
	if (efx->link_advertising[0]) {
		if (wanted_fc & EFX_FC_RX)
			efx->link_advertising[0] |= (ADVERTISED_Pause |
						     ADVERTISED_Asym_Pause);
		else
			efx->link_advertising[0] &= ~(ADVERTISED_Pause |
						      ADVERTISED_Asym_Pause);
		if (wanted_fc & EFX_FC_TX)
			efx->link_advertising[0] ^= ADVERTISED_Asym_Pause;
	}
}

static void efx_fini_port(struct efx_nic *efx);

static int efx_probe_port(struct efx_nic *efx)
@@ -1098,7 +1074,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev)

	efx_pci_remove_main(efx);

	efx_fini_io(efx, efx->type->mem_bar(efx));
	efx_fini_io(efx);
	netif_dbg(efx, drv, efx->net_dev, "shutdown successful\n");

	efx_fini_struct(efx);
@@ -1366,7 +1342,7 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
	return 0;

 fail3:
	efx_fini_io(efx, efx->type->mem_bar(efx));
	efx_fini_io(efx);
 fail2:
	efx_fini_struct(efx);
 fail1:
@@ -1514,97 +1490,6 @@ static const struct dev_pm_ops efx_pm_ops = {
	.restore	= efx_pm_resume,
};

/* A PCI error affecting this device was detected.
 * At this point MMIO and DMA may be disabled.
 * Stop the software path and request a slot reset.
 */
static pci_ers_result_t efx_io_error_detected(struct pci_dev *pdev,
					      enum pci_channel_state state)
{
	pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
	struct efx_nic *efx = pci_get_drvdata(pdev);

	if (state == pci_channel_io_perm_failure)
		return PCI_ERS_RESULT_DISCONNECT;

	rtnl_lock();

	if (efx->state != STATE_DISABLED) {
		efx->state = STATE_RECOVERY;
		efx->reset_pending = 0;

		efx_device_detach_sync(efx);

		efx_stop_all(efx);
		efx_disable_interrupts(efx);

		status = PCI_ERS_RESULT_NEED_RESET;
	} else {
		/* If the interface is disabled we don't want to do anything
		 * with it.
		 */
		status = PCI_ERS_RESULT_RECOVERED;
	}

	rtnl_unlock();

	pci_disable_device(pdev);

	return status;
}

/* Fake a successful reset, which will be performed later in efx_io_resume. */
static pci_ers_result_t efx_io_slot_reset(struct pci_dev *pdev)
{
	struct efx_nic *efx = pci_get_drvdata(pdev);
	pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;

	if (pci_enable_device(pdev)) {
		netif_err(efx, hw, efx->net_dev,
			  "Cannot re-enable PCI device after reset.\n");
		status =  PCI_ERS_RESULT_DISCONNECT;
	}

	return status;
}

/* Perform the actual reset and resume I/O operations. */
static void efx_io_resume(struct pci_dev *pdev)
{
	struct efx_nic *efx = pci_get_drvdata(pdev);
	int rc;

	rtnl_lock();

	if (efx->state == STATE_DISABLED)
		goto out;

	rc = efx_reset(efx, RESET_TYPE_ALL);
	if (rc) {
		netif_err(efx, hw, efx->net_dev,
			  "efx_reset failed after PCI error (%d)\n", rc);
	} else {
		efx->state = STATE_READY;
		netif_dbg(efx, hw, efx->net_dev,
			  "Done resetting and resuming IO after PCI error.\n");
	}

out:
	rtnl_unlock();
}

/* For simplicity and reliability, we always require a slot reset and try to
 * reset the hardware when a pci error affecting the device is detected.
 * We leave both the link_reset and mmio_enabled callback unimplemented:
 * with our request for slot reset the mmio_enabled callback will never be
 * called, and the link_reset callback is not used by AER or EEH mechanisms.
 */
static const struct pci_error_handlers efx_err_handlers = {
	.error_detected = efx_io_error_detected,
	.slot_reset	= efx_io_slot_reset,
	.resume		= efx_io_resume,
};

static struct pci_driver efx_pci_driver = {
	.name		= KBUILD_MODNAME,
	.id_table	= efx_pci_table,
+0 −8
Original line number Diff line number Diff line
@@ -147,11 +147,6 @@ static inline s32 efx_filter_get_rx_ids(struct efx_nic *efx,
{
	return efx->type->filter_get_rx_ids(efx, priority, buf, size);
}
#ifdef CONFIG_RFS_ACCEL
int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
		   u16 rxq_index, u32 flow_id);
bool __efx_filter_rfs_expire(struct efx_channel *channel, unsigned int quota);
#endif

/* RSS contexts */
static inline bool efx_rss_active(struct efx_rss_context *ctx)
@@ -216,9 +211,6 @@ static inline void efx_schedule_channel_irq(struct efx_channel *channel)
	efx_schedule_channel(channel);
}

void efx_link_clear_advertising(struct efx_nic *efx);
void efx_link_set_wanted_fc(struct efx_nic *efx, u8);

static inline void efx_device_detach_sync(struct efx_nic *efx)
{
	struct net_device *dev = efx->net_dev;
+7 −0
Original line number Diff line number Diff line
@@ -175,6 +175,13 @@ static int efx_allocate_msix_channels(struct efx_nic *efx,
		efx->n_xdp_channels = 0;
		efx->xdp_tx_per_channel = 0;
		efx->xdp_tx_queue_count = 0;
	} else if (n_channels + n_xdp_tx > efx->max_vis) {
		netif_err(efx, drv, efx->net_dev,
			  "Insufficient resources for %d XDP TX queues (%d other channels, max VIs %d)\n",
			  n_xdp_tx, n_channels, efx->max_vis);
		efx->n_xdp_channels = 0;
		efx->xdp_tx_per_channel = 0;
		efx->xdp_tx_queue_count = 0;
	} else {
		efx->n_xdp_channels = n_xdp_ev;
		efx->xdp_tx_per_channel = EFX_TXQ_TYPES;
Loading