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

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

Merge branch 'sfc-rx-vlan-filtering'



Edward Cree says:

====================
sfc: RX VLAN filtering

Adds support for VLAN-qualified receive filters on EF10 hardware.
This is needed when running as a guest if the hypervisor has enabled
vfs-vlan-restrict, in which case the firmware rejects filters not qualified
with VLAN 0.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 56108c11 38d27f38
Loading
Loading
Loading
Loading
+623 −121

File changed.

Preview size limit exceeded, changes collapsed.

+37 −7
Original line number Diff line number Diff line
@@ -232,6 +232,35 @@ static int efx_ef10_sriov_restore_vf_vswitching(struct efx_nic *efx)
	return rc;
}

static int efx_ef10_vadaptor_alloc_set_features(struct efx_nic *efx)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	u32 port_flags;
	int rc;

	rc = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id);
	if (rc)
		goto fail_vadaptor_alloc;

	rc = efx_ef10_vadaptor_query(efx, nic_data->vport_id,
				     &port_flags, NULL, NULL);
	if (rc)
		goto fail_vadaptor_query;

	if (port_flags &
	    (1 << MC_CMD_VPORT_ALLOC_IN_FLAG_VLAN_RESTRICT_LBN))
		efx->fixed_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
	else
		efx->fixed_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;

	return 0;

fail_vadaptor_query:
	efx_ef10_vadaptor_free(efx, EVB_PORT_ID_ASSIGNED);
fail_vadaptor_alloc:
	return rc;
}

/* On top of the default firmware vswitch setup, create a VEB vswitch and
 * expansion vport for use by this function.
 */
@@ -243,7 +272,7 @@ int efx_ef10_vswitching_probe_pf(struct efx_nic *efx)

	if (pci_sriov_get_totalvfs(efx->pci_dev) <= 0) {
		/* vswitch not needed as we have no VFs */
		efx_ef10_vadaptor_alloc(efx, nic_data->vport_id);
		efx_ef10_vadaptor_alloc_set_features(efx);
		return 0;
	}

@@ -263,7 +292,7 @@ int efx_ef10_vswitching_probe_pf(struct efx_nic *efx)
		goto fail3;
	ether_addr_copy(nic_data->vport_mac, net_dev->dev_addr);

	rc = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id);
	rc = efx_ef10_vadaptor_alloc_set_features(efx);
	if (rc)
		goto fail4;

@@ -282,9 +311,7 @@ int efx_ef10_vswitching_probe_pf(struct efx_nic *efx)

int efx_ef10_vswitching_probe_vf(struct efx_nic *efx)
{
	struct efx_ef10_nic_data *nic_data = efx->nic_data;

	return efx_ef10_vadaptor_alloc(efx, nic_data->vport_id);
	return efx_ef10_vadaptor_alloc_set_features(efx);
}

int efx_ef10_vswitching_restore_pf(struct efx_nic *efx)
@@ -554,6 +581,7 @@ int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan,
		efx_device_detach_sync(vf->efx);
		efx_net_stop(vf->efx->net_dev);

		mutex_lock(&vf->efx->mac_lock);
		down_write(&vf->efx->filter_sem);
		vf->efx->type->filter_table_remove(vf->efx);

@@ -630,6 +658,7 @@ int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan,
			goto reset_nic_up_write;

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

		up_write(&vf->efx->filter_sem);

@@ -642,9 +671,10 @@ int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan,
	return rc;

reset_nic_up_write:
	if (vf->efx)
	if (vf->efx) {
		up_write(&vf->efx->filter_sem);

		mutex_unlock(&vf->efx->mac_lock);
	}
reset_nic:
	if (vf->efx) {
		netif_err(efx, drv, efx->net_dev,
+3 −0
Original line number Diff line number Diff line
@@ -70,6 +70,9 @@ int efx_ef10_vport_add_mac(struct efx_nic *efx,
int efx_ef10_vport_del_mac(struct efx_nic *efx,
			   unsigned int port_id, u8 *mac);
int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id);
int efx_ef10_vadaptor_query(struct efx_nic *efx, unsigned int port_id,
			    u32 *port_flags, u32 *vadaptor_flags,
			    unsigned int *vlan_tags);
int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id);

#endif /* EF10_SRIOV_H */
+60 −6
Original line number Diff line number Diff line
@@ -600,6 +600,7 @@ static int efx_probe_channels(struct efx_nic *efx)
 */
static void efx_start_datapath(struct efx_nic *efx)
{
	netdev_features_t old_features = efx->net_dev->features;
	bool old_rx_scatter = efx->rx_scatter;
	struct efx_tx_queue *tx_queue;
	struct efx_rx_queue *rx_queue;
@@ -644,6 +645,15 @@ static void efx_start_datapath(struct efx_nic *efx)
			  efx->rx_dma_len, efx->rx_page_buf_step,
			  efx->rx_bufs_per_page, efx->rx_pages_per_batch);

	/* Restore previously fixed features in hw_features and remove
	 * features which are fixed now
	 */
	efx->net_dev->hw_features |= efx->net_dev->features;
	efx->net_dev->hw_features &= ~efx->fixed_features;
	efx->net_dev->features |= efx->fixed_features;
	if (efx->net_dev->features != old_features)
		netdev_features_change(efx->net_dev);

	/* RX filters may also have scatter-enabled flags */
	if (efx->rx_scatter != old_rx_scatter)
		efx->type->filter_update_rx_scatter(efx);
@@ -1719,6 +1729,7 @@ static int efx_probe_filters(struct efx_nic *efx)

	spin_lock_init(&efx->filter_lock);
	init_rwsem(&efx->filter_sem);
	mutex_lock(&efx->mac_lock);
	down_write(&efx->filter_sem);
	rc = efx->type->filter_table_probe(efx);
	if (rc)
@@ -1757,6 +1768,7 @@ static int efx_probe_filters(struct efx_nic *efx)
#endif
out_unlock:
	up_write(&efx->filter_sem);
	mutex_unlock(&efx->mac_lock);
	return rc;
}

@@ -2312,14 +2324,46 @@ static void efx_set_rx_mode(struct net_device *net_dev)
static int efx_set_features(struct net_device *net_dev, netdev_features_t data)
{
	struct efx_nic *efx = netdev_priv(net_dev);
	int rc;

	/* If disabling RX n-tuple filtering, clear existing filters */
	if (net_dev->features & ~data & NETIF_F_NTUPLE)
		return efx->type->filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL);
	if (net_dev->features & ~data & NETIF_F_NTUPLE) {
		rc = efx->type->filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL);
		if (rc)
			return rc;
	}

	/* If Rx VLAN filter is changed, update filters via mac_reconfigure */
	if ((net_dev->features ^ data) & NETIF_F_HW_VLAN_CTAG_FILTER) {
		/* efx_set_rx_mode() will schedule MAC work to update filters
		 * when a new features are finally set in net_dev.
		 */
		efx_set_rx_mode(net_dev);
	}

	return 0;
}

static int efx_vlan_rx_add_vid(struct net_device *net_dev, __be16 proto, u16 vid)
{
	struct efx_nic *efx = netdev_priv(net_dev);

	if (efx->type->vlan_rx_add_vid)
		return efx->type->vlan_rx_add_vid(efx, proto, vid);
	else
		return -EOPNOTSUPP;
}

static int efx_vlan_rx_kill_vid(struct net_device *net_dev, __be16 proto, u16 vid)
{
	struct efx_nic *efx = netdev_priv(net_dev);

	if (efx->type->vlan_rx_kill_vid)
		return efx->type->vlan_rx_kill_vid(efx, proto, vid);
	else
		return -EOPNOTSUPP;
}

static const struct net_device_ops efx_netdev_ops = {
	.ndo_open		= efx_net_open,
	.ndo_stop		= efx_net_stop,
@@ -2332,6 +2376,8 @@ static const struct net_device_ops efx_netdev_ops = {
	.ndo_set_mac_address	= efx_set_mac_address,
	.ndo_set_rx_mode	= efx_set_rx_mode,
	.ndo_set_features	= efx_set_features,
	.ndo_vlan_rx_add_vid	= efx_vlan_rx_add_vid,
	.ndo_vlan_rx_kill_vid	= efx_vlan_rx_kill_vid,
#ifdef CONFIG_SFC_SRIOV
	.ndo_set_vf_mac		= efx_sriov_set_vf_mac,
	.ndo_set_vf_vlan	= efx_sriov_set_vf_vlan,
@@ -3147,17 +3193,25 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
		return -ENOMEM;
	efx = netdev_priv(net_dev);
	efx->type = (const struct efx_nic_type *) entry->driver_data;
	efx->fixed_features |= NETIF_F_HIGHDMA;
	net_dev->features |= (efx->type->offload_features | NETIF_F_SG |
			      NETIF_F_HIGHDMA | NETIF_F_TSO |
			      NETIF_F_RXCSUM);
			      NETIF_F_TSO | NETIF_F_RXCSUM);
	if (efx->type->offload_features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM))
		net_dev->features |= NETIF_F_TSO6;
	/* Mask for features that also apply to VLAN devices */
	net_dev->vlan_features |= (NETIF_F_HW_CSUM | NETIF_F_SG |
				   NETIF_F_HIGHDMA | NETIF_F_ALL_TSO |
				   NETIF_F_RXCSUM);
	/* All offloads can be toggled */
	net_dev->hw_features = net_dev->features & ~NETIF_F_HIGHDMA;

	net_dev->hw_features = net_dev->features & ~efx->fixed_features;

	/* Disable VLAN filtering by default.  It may be enforced if
	 * the feature is fixed (i.e. VLAN filters are required to
	 * receive VLAN tagged packets due to vPort restrictions).
	 */
	net_dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
	net_dev->features |= efx->fixed_features;

	pci_set_drvdata(pci_dev, efx);
	SET_NETDEV_DEV(net_dev, &pci_dev->dev);
	rc = efx_init_struct(efx, pci_dev, net_dev);
+9 −0
Original line number Diff line number Diff line
@@ -274,4 +274,13 @@ static inline void efx_device_detach_sync(struct efx_nic *efx)
	netif_tx_unlock_bh(dev);
}

static inline bool efx_rwsem_assert_write_locked(struct rw_semaphore *sem)
{
	if (WARN_ON(down_read_trylock(sem))) {
		up_read(sem);
		return false;
	}
	return true;
}

#endif /* EFX_EFX_H */
Loading