mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-28 15:13:55 +08:00
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
b478af0cd7
File diff suppressed because it is too large
Load Diff
@ -232,6 +232,35 @@ fail:
|
||||
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 @@ fail1:
|
||||
|
||||
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 @@ restore_filters:
|
||||
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 @@ restore_filters:
|
||||
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,
|
||||
|
@ -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 */
|
||||
|
@ -600,6 +600,7 @@ fail:
|
||||
*/
|
||||
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);
|
||||
|
@ -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 */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -868,6 +868,7 @@ struct vfdi_status;
|
||||
* be held to modify it.
|
||||
* @port_initialized: Port initialized?
|
||||
* @net_dev: Operating system network device. Consider holding the rtnl lock
|
||||
* @fixed_features: Features which cannot be turned off
|
||||
* @stats_buffer: DMA buffer for statistics
|
||||
* @phy_type: PHY type
|
||||
* @phy_op: PHY interface
|
||||
@ -916,7 +917,6 @@ struct vfdi_status;
|
||||
* @stats_lock: Statistics update lock. Must be held when calling
|
||||
* efx_nic_type::{update,start,stop}_stats.
|
||||
* @n_rx_noskb_drops: Count of RX packets dropped due to failure to allocate an skb
|
||||
* @mc_promisc: Whether in multicast promiscuous mode when last changed
|
||||
*
|
||||
* This is stored in the private area of the &struct net_device.
|
||||
*/
|
||||
@ -1008,6 +1008,8 @@ struct efx_nic {
|
||||
bool port_initialized;
|
||||
struct net_device *net_dev;
|
||||
|
||||
netdev_features_t fixed_features;
|
||||
|
||||
struct efx_buffer stats_buffer;
|
||||
u64 rx_nodesc_drops_total;
|
||||
u64 rx_nodesc_drops_while_down;
|
||||
@ -1065,7 +1067,6 @@ struct efx_nic {
|
||||
int last_irq_cpu;
|
||||
spinlock_t stats_lock;
|
||||
atomic_t n_rx_noskb_drops;
|
||||
bool mc_promisc;
|
||||
};
|
||||
|
||||
static inline int efx_dev_registered(struct efx_nic *efx)
|
||||
@ -1333,6 +1334,8 @@ struct efx_nic_type {
|
||||
int (*ptp_set_ts_config)(struct efx_nic *efx,
|
||||
struct hwtstamp_config *init);
|
||||
int (*sriov_configure)(struct efx_nic *efx, int num_vfs);
|
||||
int (*vlan_rx_add_vid)(struct efx_nic *efx, __be16 proto, u16 vid);
|
||||
int (*vlan_rx_kill_vid)(struct efx_nic *efx, __be16 proto, u16 vid);
|
||||
int (*sriov_init)(struct efx_nic *efx);
|
||||
void (*sriov_fini)(struct efx_nic *efx);
|
||||
bool (*sriov_wanted)(struct efx_nic *efx);
|
||||
@ -1521,4 +1524,16 @@ static inline void efx_xmit_hwtstamp_pending(struct sk_buff *skb)
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/* Get all supported features.
|
||||
* If a feature is not fixed, it is present in hw_features.
|
||||
* If a feature is fixed, it does not present in hw_features, but
|
||||
* always in features.
|
||||
*/
|
||||
static inline netdev_features_t efx_supported_features(const struct efx_nic *efx)
|
||||
{
|
||||
const struct net_device *net_dev = efx->net_dev;
|
||||
|
||||
return net_dev->features | net_dev->hw_features;
|
||||
}
|
||||
|
||||
#endif /* EFX_NET_DRIVER_H */
|
||||
|
@ -519,6 +519,9 @@ enum {
|
||||
#ifdef CONFIG_SFC_SRIOV
|
||||
* @vf: Pointer to VF data structure
|
||||
#endif
|
||||
* @vport_mac: The MAC address on the vport, only for PFs; VFs will be zero
|
||||
* @vlan_list: List of VLANs added over the interface. Serialised by vlan_lock.
|
||||
* @vlan_lock: Lock to serialize access to vlan_list.
|
||||
*/
|
||||
struct efx_ef10_nic_data {
|
||||
struct efx_buffer mcdi_buf;
|
||||
@ -550,6 +553,8 @@ struct efx_ef10_nic_data {
|
||||
struct ef10_vf *vf;
|
||||
#endif
|
||||
u8 vport_mac[ETH_ALEN];
|
||||
struct list_head vlan_list;
|
||||
struct mutex vlan_lock;
|
||||
};
|
||||
|
||||
int efx_init_sriov(void);
|
||||
|
Loading…
Reference in New Issue
Block a user