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

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

Merge branch 'sfc-next'



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: default avatarDavid S. Miller <davem@davemloft.net>
parents b5de97bc 25672dba
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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>
@@ -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),
+52 −0
Original line number Diff line number Diff line
/****************************************************************************
 * 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 −0
Original line number Diff line number Diff line
/****************************************************************************
 * 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 */
+64 −54
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include "efx.h"
#include "nic.h"
#include "selftest.h"
#include "sriov.h"

#include "mcdi.h"
#include "workarounds.h"
@@ -1314,6 +1315,8 @@ 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
	 */
#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,
@@ -1323,6 +1326,8 @@ static unsigned int efx_wanted_parallelism(struct efx_nic *efx)
				   count, efx_vf_size(efx));
			count = efx_vf_size(efx);
		}
	}
#endif

	return count;
}
@@ -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 */

#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;
}
@@ -2168,6 +2176,7 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
	}

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

	/* Reconfigure the MAC */
@@ -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,
@@ -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,
@@ -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);
@@ -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));

@@ -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;

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

	mutex_unlock(&efx->mac_lock);
@@ -2828,7 +2811,9 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
	efx_disable_interrupts(efx);
	rtnl_unlock();

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

	efx_unregister_netdev(efx);

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

	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");

@@ -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));
@@ -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
};

/**************************************************************************
Loading