Skip to content

Commit

Permalink
Merge branch 'sfc-next'
Browse files Browse the repository at this point in the history
Shradha Shah says:

====================
sfc: Nic specific sriov functions, netdev_ops and sriov_configure

First two patches among the series of patches to support SRIOV on EF10.

First patch declares nic specific sriov functions in nic specific headers,
creates only one instance of the netdev_ops, removes sriov functionality
from Falcon code.

Second patch adds support for sriov_configure.

The Virtual Functions can be enabled but they do not bind to the SFC
driver just yet.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 8, 2015
2 parents b5de97b + 25672db commit 8ae178f
Show file tree
Hide file tree
Showing 16 changed files with 454 additions and 207 deletions.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/sfc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ sfc-y += efx.o nic.o farch.o falcon.o siena.o ef10.o tx.o \
tenxpress.o txc43128_phy.o falcon_boards.o \
mcdi.o mcdi_port.o mcdi_mon.o ptp.o
sfc-$(CONFIG_SFC_MTD) += mtd.o
sfc-$(CONFIG_SFC_SRIOV) += siena_sriov.o
sfc-$(CONFIG_SFC_SRIOV) += sriov.o siena_sriov.o ef10_sriov.o

obj-$(CONFIG_SFC) += sfc.o
7 changes: 7 additions & 0 deletions drivers/net/ethernet/sfc/ef10.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "nic.h"
#include "workarounds.h"
#include "selftest.h"
#include "ef10_sriov.h"
#include <linux/in.h>
#include <linux/jhash.h>
#include <linux/wait.h>
Expand Down Expand Up @@ -3689,11 +3690,17 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
.ptp_write_host_time = efx_ef10_ptp_write_host_time,
.ptp_set_ts_sync_events = efx_ef10_ptp_set_ts_sync_events,
.ptp_set_ts_config = efx_ef10_ptp_set_ts_config,
.sriov_configure = efx_ef10_sriov_configure,
.sriov_init = efx_ef10_sriov_init,
.sriov_fini = efx_ef10_sriov_fini,
.sriov_mac_address_changed = efx_ef10_sriov_mac_address_changed,
.sriov_wanted = efx_ef10_sriov_wanted,
.sriov_reset = efx_ef10_sriov_reset,
.sriov_flr = efx_ef10_sriov_flr,
.sriov_set_vf_mac = efx_ef10_sriov_set_vf_mac,
.sriov_set_vf_vlan = efx_ef10_sriov_set_vf_vlan,
.sriov_set_vf_spoofchk = efx_ef10_sriov_set_vf_spoofchk,
.sriov_get_vf_config = efx_ef10_sriov_get_vf_config,

.revision = EFX_REV_HUNT_A0,
.max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH),
Expand Down
52 changes: 52 additions & 0 deletions drivers/net/ethernet/sfc/ef10_sriov.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/****************************************************************************
* Driver for Solarflare network controllers and boards
* Copyright 2015 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation, incorporated herein by reference.
*/
#include <linux/pci.h>
#include <linux/module.h>
#include "net_driver.h"
#include "efx.h"
#include "nic.h"
#include "mcdi_pcol.h"

#ifdef CONFIG_SFC_SRIOV
static int efx_ef10_pci_sriov_enable(struct efx_nic *efx, int num_vfs)
{
int rc = 0;
struct pci_dev *dev = efx->pci_dev;

efx->vf_count = num_vfs;
rc = pci_enable_sriov(dev, num_vfs);
if (rc) {
efx->vf_count = 0;
netif_err(efx, probe, efx->net_dev,
"Failed to enable SRIOV VFs\n");
}
return rc;
}

static int efx_ef10_pci_sriov_disable(struct efx_nic *efx)
{
struct pci_dev *dev = efx->pci_dev;

efx->vf_count = 0;
pci_disable_sriov(dev);
return 0;
}
#endif

int efx_ef10_sriov_configure(struct efx_nic *efx, int num_vfs)
{
#ifdef CONFIG_SFC_SRIOV
if (num_vfs == 0)
return efx_ef10_pci_sriov_disable(efx);
else
return efx_ef10_pci_sriov_enable(efx, num_vfs);
#else
return -EOPNOTSUPP;
#endif
}
58 changes: 58 additions & 0 deletions drivers/net/ethernet/sfc/ef10_sriov.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/****************************************************************************
* Driver for Solarflare network controllers and boards
* Copyright 2015 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation, incorporated herein by reference.
*/

#ifndef EF10_SRIOV_H
#define EF10_SRIOV_H

#include "net_driver.h"

static inline bool efx_ef10_sriov_wanted(struct efx_nic *efx)
{
return false;
}

int efx_ef10_sriov_configure(struct efx_nic *efx, int num_vfs);

static inline int efx_ef10_sriov_init(struct efx_nic *efx)
{
return -EOPNOTSUPP;
}

static inline void efx_ef10_sriov_mac_address_changed(struct efx_nic *efx) {}
static inline void efx_ef10_sriov_reset(struct efx_nic *efx) {}
static inline void efx_ef10_sriov_fini(struct efx_nic *efx) {}
static inline void efx_ef10_sriov_flr(struct efx_nic *efx, unsigned vf_i) {}

#ifdef CONFIG_SFC_SRIOV
static inline int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf,
u8 *mac)
{
return -EOPNOTSUPP;
}

static inline int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf,
u16 vlan, u8 qos)
{
return -EOPNOTSUPP;
}

static inline int efx_ef10_sriov_set_vf_spoofchk(struct efx_nic *efx, int vf,
bool spoofchk)
{
return -EOPNOTSUPP;
}

static inline int efx_ef10_sriov_get_vf_config(struct efx_nic *efx, int vf,
struct ifla_vf_info *ivf)
{
return -EOPNOTSUPP;
}
#endif /* CONFIG_SFC_SRIOV */

#endif /* EF10_SRIOV_H */
118 changes: 64 additions & 54 deletions drivers/net/ethernet/sfc/efx.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "efx.h"
#include "nic.h"
#include "selftest.h"
#include "sriov.h"

#include "mcdi.h"
#include "workarounds.h"
Expand Down Expand Up @@ -1314,15 +1315,19 @@ static unsigned int efx_wanted_parallelism(struct efx_nic *efx)
/* If RSS is requested for the PF *and* VFs then we can't write RSS
* table entries that are inaccessible to VFs
*/
if (efx->type->sriov_wanted(efx) && efx_vf_size(efx) > 1 &&
count > efx_vf_size(efx)) {
netif_warn(efx, probe, efx->net_dev,
"Reducing number of RSS channels from %u to %u for "
"VF support. Increase vf-msix-limit to use more "
"channels on the PF.\n",
count, efx_vf_size(efx));
count = efx_vf_size(efx);
#ifdef CONFIG_SFC_SRIOV
if (efx->type->sriov_wanted) {
if (efx->type->sriov_wanted(efx) && efx_vf_size(efx) > 1 &&
count > efx_vf_size(efx)) {
netif_warn(efx, probe, efx->net_dev,
"Reducing number of RSS channels from %u to %u for "
"VF support. Increase vf-msix-limit to use more "
"channels on the PF.\n",
count, efx_vf_size(efx));
count = efx_vf_size(efx);
}
}
#endif

return count;
}
Expand Down Expand Up @@ -1426,10 +1431,13 @@ static int efx_probe_interrupts(struct efx_nic *efx)
}

/* RSS might be usable on VFs even if it is disabled on the PF */

efx->rss_spread = ((efx->n_rx_channels > 1 ||
!efx->type->sriov_wanted(efx)) ?
efx->n_rx_channels : efx_vf_size(efx));
#ifdef CONFIG_SFC_SRIOV
if (efx->type->sriov_wanted) {
efx->rss_spread = ((efx->n_rx_channels > 1 ||
!efx->type->sriov_wanted(efx)) ?
efx->n_rx_channels : efx_vf_size(efx));
}
#endif

return 0;
}
Expand Down Expand Up @@ -2168,7 +2176,8 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
}

ether_addr_copy(net_dev->dev_addr, new_addr);
efx->type->sriov_mac_address_changed(efx);
if (efx->type->sriov_mac_address_changed)
efx->type->sriov_mac_address_changed(efx);

/* Reconfigure the MAC */
mutex_lock(&efx->mac_lock);
Expand Down Expand Up @@ -2199,7 +2208,7 @@ static int efx_set_features(struct net_device *net_dev, netdev_features_t data)
return 0;
}

static const struct net_device_ops efx_farch_netdev_ops = {
static const struct net_device_ops efx_netdev_ops = {
.ndo_open = efx_net_open,
.ndo_stop = efx_net_stop,
.ndo_get_stats64 = efx_net_stats,
Expand All @@ -2212,10 +2221,10 @@ static const struct net_device_ops efx_farch_netdev_ops = {
.ndo_set_rx_mode = efx_set_rx_mode,
.ndo_set_features = efx_set_features,
#ifdef CONFIG_SFC_SRIOV
.ndo_set_vf_mac = efx_siena_sriov_set_vf_mac,
.ndo_set_vf_vlan = efx_siena_sriov_set_vf_vlan,
.ndo_set_vf_spoofchk = efx_siena_sriov_set_vf_spoofchk,
.ndo_get_vf_config = efx_siena_sriov_get_vf_config,
.ndo_set_vf_mac = efx_sriov_set_vf_mac,
.ndo_set_vf_vlan = efx_sriov_set_vf_vlan,
.ndo_set_vf_spoofchk = efx_sriov_set_vf_spoofchk,
.ndo_get_vf_config = efx_sriov_get_vf_config,
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = efx_netpoll,
Expand All @@ -2229,29 +2238,6 @@ static const struct net_device_ops efx_farch_netdev_ops = {
#endif
};

static const struct net_device_ops efx_ef10_netdev_ops = {
.ndo_open = efx_net_open,
.ndo_stop = efx_net_stop,
.ndo_get_stats64 = efx_net_stats,
.ndo_tx_timeout = efx_watchdog,
.ndo_start_xmit = efx_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = efx_ioctl,
.ndo_change_mtu = efx_change_mtu,
.ndo_set_mac_address = efx_set_mac_address,
.ndo_set_rx_mode = efx_set_rx_mode,
.ndo_set_features = efx_set_features,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = efx_netpoll,
#endif
#ifdef CONFIG_NET_RX_BUSY_POLL
.ndo_busy_poll = efx_busy_poll,
#endif
#ifdef CONFIG_RFS_ACCEL
.ndo_rx_flow_steer = efx_filter_rfs,
#endif
};

static void efx_update_name(struct efx_nic *efx)
{
strcpy(efx->name, efx->net_dev->name);
Expand All @@ -2264,8 +2250,7 @@ static int efx_netdev_event(struct notifier_block *this,
{
struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);

if ((net_dev->netdev_ops == &efx_farch_netdev_ops ||
net_dev->netdev_ops == &efx_ef10_netdev_ops) &&
if ((net_dev->netdev_ops == &efx_netdev_ops) &&
event == NETDEV_CHANGENAME)
efx_update_name(netdev_priv(net_dev));

Expand All @@ -2292,12 +2277,9 @@ static int efx_register_netdev(struct efx_nic *efx)

net_dev->watchdog_timeo = 5 * HZ;
net_dev->irq = efx->pci_dev->irq;
if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) {
net_dev->netdev_ops = &efx_ef10_netdev_ops;
net_dev->netdev_ops = &efx_netdev_ops;
if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0)
net_dev->priv_flags |= IFF_UNICAST_FLT;
} else {
net_dev->netdev_ops = &efx_farch_netdev_ops;
}
net_dev->ethtool_ops = &efx_ethtool_ops;
net_dev->gso_max_segs = EFX_TSO_MAX_SEGS;

Expand Down Expand Up @@ -2435,7 +2417,8 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
if (rc)
goto fail;
efx_restore_filters(efx);
efx->type->sriov_reset(efx);
if (efx->type->sriov_reset)
efx->type->sriov_reset(efx);

mutex_unlock(&efx->mac_lock);

Expand Down Expand Up @@ -2828,7 +2811,9 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
efx_disable_interrupts(efx);
rtnl_unlock();

efx->type->sriov_fini(efx);
if (efx->type->sriov_fini)
efx->type->sriov_fini(efx);

efx_unregister_netdev(efx);

efx_mtd_remove(efx);
Expand Down Expand Up @@ -3025,10 +3010,12 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
if (rc)
goto fail4;

rc = efx->type->sriov_init(efx);
if (rc)
netif_err(efx, probe, efx->net_dev,
"SR-IOV can't be enabled rc %d\n", rc);
if (efx->type->sriov_init) {
rc = efx->type->sriov_init(efx);
if (rc)
netif_err(efx, probe, efx->net_dev,
"SR-IOV can't be enabled rc %d\n", rc);
}

netif_dbg(efx, probe, efx->net_dev, "initialisation successful\n");

Expand Down Expand Up @@ -3060,6 +3047,26 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
return rc;
}

/* efx_pci_sriov_configure returns the actual number of Virtual Functions
* enabled on success
*/
#ifdef CONFIG_SFC_SRIOV
static int efx_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
{
int rc;
struct efx_nic *efx = pci_get_drvdata(dev);

if (efx->type->sriov_configure) {
rc = efx->type->sriov_configure(efx, num_vfs);
if (rc)
return rc;
else
return num_vfs;
} else
return -ENOSYS;
}
#endif

static int efx_pm_freeze(struct device *dev)
{
struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
Expand Down Expand Up @@ -3282,6 +3289,9 @@ static struct pci_driver efx_pci_driver = {
.remove = efx_pci_remove,
.driver.pm = &efx_pm_ops,
.err_handler = &efx_err_handlers,
#ifdef CONFIG_SFC_SRIOV
.sriov_configure = efx_pci_sriov_configure,
#endif
};

/**************************************************************************
Expand Down
7 changes: 7 additions & 0 deletions drivers/net/ethernet/sfc/efx.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,13 @@ static inline void efx_mtd_rename(struct efx_nic *efx) {}
static inline void efx_mtd_remove(struct efx_nic *efx) {}
#endif

#ifdef CONFIG_SFC_SRIOV
static inline unsigned int efx_vf_size(struct efx_nic *efx)
{
return 1 << efx->vi_scale;
}
#endif

static inline void efx_schedule_channel(struct efx_channel *channel)
{
netif_vdbg(channel->efx, intr, channel->efx->net_dev,
Expand Down
Loading

0 comments on commit 8ae178f

Please sign in to comment.