Commit ed3849e4 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'sfc-vf-representors-for-ef100-rx-side'

Edward Cree says:

====================
sfc: VF representors for EF100 - RX side

This series adds the receive path for EF100 VF representors, plus other
 minor features such as statistics.
====================

Link: https://lore.kernel.org/r/cover.1659034549.git.ecree.xilinx@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 71930846 7267aa6d
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -8,7 +8,8 @@ sfc-y += efx.o efx_common.o efx_channels.o nic.o \
			   ef100.o ef100_nic.o ef100_netdev.o \
			   ef100_ethtool.o ef100_rx.o ef100_tx.o
sfc-$(CONFIG_SFC_MTD)	+= mtd.o
sfc-$(CONFIG_SFC_SRIOV)	+= sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o mae.o
sfc-$(CONFIG_SFC_SRIOV)	+= sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o \
                           mae.o tc.o

obj-$(CONFIG_SFC)	+= sfc.o

+15 −11
Original line number Diff line number Diff line
@@ -2538,23 +2538,33 @@ static int efx_ef10_filter_table_probe(struct efx_nic *efx)

	if (rc)
		return rc;
	down_write(&efx->filter_sem);
	rc = efx_mcdi_filter_table_probe(efx, nic_data->workaround_26807);

	if (rc)
		return rc;
		goto out_unlock;

	list_for_each_entry(vlan, &nic_data->vlan_list, list) {
		rc = efx_mcdi_filter_add_vlan(efx, vlan->vid);
		if (rc)
			goto fail_add_vlan;
	}
	return 0;
	goto out_unlock;

fail_add_vlan:
	efx_mcdi_filter_table_remove(efx);
out_unlock:
	up_write(&efx->filter_sem);
	return rc;
}

static void efx_ef10_filter_table_remove(struct efx_nic *efx)
{
	down_write(&efx->filter_sem);
	efx_mcdi_filter_table_remove(efx);
	up_write(&efx->filter_sem);
}

/* This creates an entry in the RX descriptor queue */
static inline void
efx_ef10_build_rx_desc(struct efx_rx_queue *rx_queue, unsigned int index)
@@ -3211,9 +3221,7 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx)

	efx_device_detach_sync(efx);
	efx_net_stop(efx->net_dev);
	down_write(&efx->filter_sem);
	efx_mcdi_filter_table_remove(efx);
	up_write(&efx->filter_sem);
	efx_ef10_filter_table_remove(efx);

	rc = efx_ef10_vadaptor_free(efx, efx->vport_id);
	if (rc)
@@ -3243,9 +3251,7 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx)
	if (rc2)
		goto reset_nic;
restore_filters:
	down_write(&efx->filter_sem);
	rc2 = efx_ef10_filter_table_probe(efx);
	up_write(&efx->filter_sem);
	if (rc2)
		goto reset_nic;

@@ -3275,8 +3281,7 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
	efx_net_stop(efx->net_dev);

	mutex_lock(&efx->mac_lock);
	down_write(&efx->filter_sem);
	efx_mcdi_filter_table_remove(efx);
	efx_ef10_filter_table_remove(efx);

	ether_addr_copy(MCDI_PTR(inbuf, VADAPTOR_SET_MAC_IN_MACADDR),
			efx->net_dev->dev_addr);
@@ -3286,7 +3291,6 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
				sizeof(inbuf), NULL, 0, NULL);

	efx_ef10_filter_table_probe(efx);
	up_write(&efx->filter_sem);
	mutex_unlock(&efx->mac_lock);

	if (was_enabled)
@@ -4092,7 +4096,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
	.ev_test_generate = efx_ef10_ev_test_generate,
	.filter_table_probe = efx_ef10_filter_table_probe,
	.filter_table_restore = efx_mcdi_filter_table_restore,
	.filter_table_remove = efx_mcdi_filter_table_remove,
	.filter_table_remove = efx_ef10_filter_table_remove,
	.filter_update_rx_scatter = efx_mcdi_update_rx_scatter,
	.filter_insert = efx_mcdi_filter_insert,
	.filter_remove_safe = efx_mcdi_filter_remove_safe,
+3 −0
Original line number Diff line number Diff line
@@ -431,6 +431,9 @@ static void ef100_pci_remove(struct pci_dev *pci_dev)

	probe_data = container_of(efx, struct efx_probe_data, efx);
	ef100_remove_netdev(probe_data);
#ifdef CONFIG_SFC_SRIOV
	efx_fini_struct_tc(efx);
#endif

	ef100_remove(efx);
	efx_fini_io(efx);
+4 −0
Original line number Diff line number Diff line
@@ -329,6 +329,10 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)

	ef100_unregister_netdev(efx);

#ifdef CONFIG_SFC_SRIOV
	efx_fini_tc(efx);
#endif

	down_write(&efx->filter_sem);
	efx_mcdi_filter_table_remove(efx);
	up_write(&efx->filter_sem);
+83 −8
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@
#include "ef100_tx.h"
#include "ef100_sriov.h"
#include "ef100_netdev.h"
#include "tc.h"
#include "mae.h"
#include "rx_common.h"

#define EF100_MAX_VIS 4096
@@ -374,26 +376,46 @@ static int ef100_filter_table_up(struct efx_nic *efx)
{
	int rc;

	down_write(&efx->filter_sem);
	rc = efx_mcdi_filter_add_vlan(efx, EFX_FILTER_VID_UNSPEC);
	if (rc) {
		efx_mcdi_filter_table_down(efx);
		return rc;
	}
	if (rc)
		goto fail_unspec;

	rc = efx_mcdi_filter_add_vlan(efx, 0);
	if (rc) {
	if (rc)
		goto fail_vlan0;
	/* Drop the lock: we've finished altering table existence, and
	 * filter insertion will need to take the lock for read.
	 */
	up_write(&efx->filter_sem);
#ifdef CONFIG_SFC_SRIOV
	rc = efx_tc_insert_rep_filters(efx);
	/* Rep filter failure is nonfatal */
	if (rc)
		netif_warn(efx, drv, efx->net_dev,
			   "Failed to insert representor filters, rc %d\n",
			   rc);
#endif
	return 0;

fail_vlan0:
	efx_mcdi_filter_del_vlan(efx, EFX_FILTER_VID_UNSPEC);
fail_unspec:
	efx_mcdi_filter_table_down(efx);
	}

	up_write(&efx->filter_sem);
	return rc;
}

static void ef100_filter_table_down(struct efx_nic *efx)
{
#ifdef CONFIG_SFC_SRIOV
	efx_tc_remove_rep_filters(efx);
#endif
	down_write(&efx->filter_sem);
	efx_mcdi_filter_del_vlan(efx, 0);
	efx_mcdi_filter_del_vlan(efx, EFX_FILTER_VID_UNSPEC);
	efx_mcdi_filter_table_down(efx);
	up_write(&efx->filter_sem);
}

/*	Other
@@ -704,6 +726,31 @@ static unsigned int efx_ef100_recycle_ring_size(const struct efx_nic *efx)
	return 10 * EFX_RECYCLE_RING_SIZE_10G;
}

#ifdef CONFIG_SFC_SRIOV
static int efx_ef100_get_base_mport(struct efx_nic *efx)
{
	struct ef100_nic_data *nic_data = efx->nic_data;
	u32 selector, id;
	int rc;

	/* Construct mport selector for "physical network port" */
	efx_mae_mport_wire(efx, &selector);
	/* Look up actual mport ID */
	rc = efx_mae_lookup_mport(efx, selector, &id);
	if (rc)
		return rc;
	/* The ID should always fit in 16 bits, because that's how wide the
	 * corresponding fields in the RX prefix & TX override descriptor are
	 */
	if (id >> 16)
		netif_warn(efx, probe, efx->net_dev, "Bad base m-port id %#x\n",
			   id);
	nic_data->base_mport = id;
	nic_data->have_mport = true;
	return 0;
}
#endif

static int compare_versions(const char *a, const char *b)
{
	int a_major, a_minor, a_point, a_patch;
@@ -1064,6 +1111,34 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
	eth_hw_addr_set(net_dev, net_dev->perm_addr);
	memcpy(nic_data->port_id, net_dev->perm_addr, ETH_ALEN);

	if (!nic_data->grp_mae)
		return 0;

#ifdef CONFIG_SFC_SRIOV
	rc = efx_init_struct_tc(efx);
	if (rc)
		return rc;

	rc = efx_ef100_get_base_mport(efx);
	if (rc) {
		netif_warn(efx, probe, net_dev,
			   "Failed to probe base mport rc %d; representors will not function\n",
			   rc);
	}

	rc = efx_init_tc(efx);
	if (rc) {
		/* Either we don't have an MAE at all (i.e. legacy v-switching),
		 * or we do but we failed to probe it.  In the latter case, we
		 * may not have set up default rules, in which case we won't be
		 * able to pass any traffic.  However, we don't fail the probe,
		 * because the user might need to use the netdevice to apply
		 * configuration changes to fix whatever's wrong with the MAE.
		 */
		netif_warn(efx, probe, net_dev, "Failed to probe MAE rc %d\n",
			   rc);
	}
#endif
	return 0;

fail:
Loading