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

Merge branch 'sfc-add-extra-states-for-VDPA'



Martin Habets says:

====================
sfc: Add extra states for VDPA

For EF100 VDPA support we need to enhance the sfc driver's load and
unload functionality so that it can probe and then unregister its
network device, so that VDPA can use services such as MCDI to initialise
VDPA resources.

v2:
- Fix checkpatch errors.
- Correct signoffs.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents da8ff2a2 98ff4c7c
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -3874,7 +3874,7 @@ static int efx_ef10_udp_tnl_set_port(struct net_device *dev,
				     unsigned int table, unsigned int entry,
				     struct udp_tunnel_info *ti)
{
	struct efx_nic *efx = netdev_priv(dev);
	struct efx_nic *efx = efx_netdev_priv(dev);
	struct efx_ef10_nic_data *nic_data;
	int efx_tunnel_type, rc;

@@ -3934,7 +3934,7 @@ static int efx_ef10_udp_tnl_unset_port(struct net_device *dev,
				       unsigned int table, unsigned int entry,
				       struct udp_tunnel_info *ti)
{
	struct efx_nic *efx = netdev_priv(dev);
	struct efx_nic *efx = efx_netdev_priv(dev);
	struct efx_ef10_nic_data *nic_data;
	int rc;

+29 −40
Original line number Diff line number Diff line
@@ -423,63 +423,56 @@ static int ef100_pci_find_func_ctrl_window(struct efx_nic *efx,
 */
static void ef100_pci_remove(struct pci_dev *pci_dev)
{
	struct efx_nic *efx;
	struct efx_nic *efx = pci_get_drvdata(pci_dev);
	struct efx_probe_data *probe_data;

	efx = pci_get_drvdata(pci_dev);
	if (!efx)
		return;

	rtnl_lock();
	dev_close(efx->net_dev);
	rtnl_unlock();
	probe_data = container_of(efx, struct efx_probe_data, efx);
	ef100_remove_netdev(probe_data);

	/* Unregistering our netdev notifier triggers unbinding of TC indirect
	 * blocks, so we have to do it before PCI removal.
	 */
	unregister_netdevice_notifier(&efx->netdev_notifier);
#if defined(CONFIG_SFC_SRIOV)
	if (!efx->type->is_vf)
		efx_ef100_pci_sriov_disable(efx);
#endif
	ef100_remove(efx);
	efx_fini_io(efx);
	netif_dbg(efx, drv, efx->net_dev, "shutdown successful\n");

	pci_set_drvdata(pci_dev, NULL);
	efx_fini_struct(efx);
	free_netdev(efx->net_dev);
	pci_dbg(pci_dev, "shutdown successful\n");

	pci_disable_pcie_error_reporting(pci_dev);

	pci_set_drvdata(pci_dev, NULL);
	efx_fini_struct(efx);
	kfree(probe_data);
};

static int ef100_pci_probe(struct pci_dev *pci_dev,
			   const struct pci_device_id *entry)
{
	struct ef100_func_ctl_window fcw = { 0 };
	struct net_device *net_dev;
	struct efx_probe_data *probe_data;
	struct efx_nic *efx;
	int rc;

	/* Allocate and initialise a struct net_device and struct efx_nic */
	net_dev = alloc_etherdev_mq(sizeof(*efx), EFX_MAX_CORE_TX_QUEUES);
	if (!net_dev)
	/* Allocate probe data and struct efx_nic */
	probe_data = kzalloc(sizeof(*probe_data), GFP_KERNEL);
	if (!probe_data)
		return -ENOMEM;
	efx = netdev_priv(net_dev);
	probe_data->pci_dev = pci_dev;
	efx = &probe_data->efx;

	efx->type = (const struct efx_nic_type *)entry->driver_data;

	efx->pci_dev = pci_dev;
	pci_set_drvdata(pci_dev, efx);
	SET_NETDEV_DEV(net_dev, &pci_dev->dev);
	rc = efx_init_struct(efx, pci_dev, net_dev);
	rc = efx_init_struct(efx, pci_dev);
	if (rc)
		goto fail;

	efx->vi_stride = EF100_DEFAULT_VI_STRIDE;
	netif_info(efx, probe, efx->net_dev,
		   "Solarflare EF100 NIC detected\n");
	pci_info(pci_dev, "Solarflare EF100 NIC detected\n");

	rc = ef100_pci_find_func_ctrl_window(efx, &fcw);
	if (rc) {
		netif_err(efx, probe, efx->net_dev,
		pci_err(pci_dev,
			"Error looking for ef100 function control window, rc=%d\n",
			rc);
		goto fail;
@@ -493,8 +486,7 @@ static int ef100_pci_probe(struct pci_dev *pci_dev,
	}

	if (fcw.offset > pci_resource_len(efx->pci_dev, fcw.bar) - ESE_GZ_FCW_LEN) {
		netif_err(efx, probe, efx->net_dev,
			  "Func control window overruns BAR\n");
		pci_err(pci_dev, "Func control window overruns BAR\n");
		rc = -EIO;
		goto fail;
	}
@@ -508,19 +500,16 @@ static int ef100_pci_probe(struct pci_dev *pci_dev,

	efx->reg_base = fcw.offset;

	efx->netdev_notifier.notifier_call = ef100_netdev_event;
	rc = register_netdevice_notifier(&efx->netdev_notifier);
	if (rc) {
		netif_err(efx, probe, efx->net_dev,
			  "Failed to register netdevice notifier, rc=%d\n", rc);
	rc = efx->type->probe(efx);
	if (rc)
		goto fail;
	}

	rc = efx->type->probe(efx);
	efx->state = STATE_PROBED;
	rc = ef100_probe_netdev(probe_data);
	if (rc)
		goto fail;

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

	return 0;

+1 −1
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ ef100_ethtool_get_ringparam(struct net_device *net_dev,
			    struct kernel_ethtool_ringparam *kernel_ring,
			    struct netlink_ext_ack *extack)
{
	struct efx_nic *efx = netdev_priv(net_dev);
	struct efx_nic *efx = efx_netdev_priv(net_dev);

	ring->rx_max_pending = EFX_EF100_MAX_DMAQ_SIZE;
	ring->tx_max_pending = EFX_EF100_MAX_DMAQ_SIZE;
+122 −8
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include "ef100_regs.h"
#include "mcdi_filters.h"
#include "rx_common.h"
#include "ef100_sriov.h"

static void ef100_update_name(struct efx_nic *efx)
{
@@ -79,7 +80,7 @@ static int ef100_remap_bar(struct efx_nic *efx, int max_vis)
 */
static int ef100_net_stop(struct net_device *net_dev)
{
	struct efx_nic *efx = netdev_priv(net_dev);
	struct efx_nic *efx = efx_netdev_priv(net_dev);

	netif_dbg(efx, ifdown, efx->net_dev, "closing on CPU %d\n",
		  raw_smp_processor_id());
@@ -96,13 +97,15 @@ static int ef100_net_stop(struct net_device *net_dev)
	efx_mcdi_free_vis(efx);
	efx_remove_interrupts(efx);

	efx->state = STATE_NET_DOWN;

	return 0;
}

/* Context: process, rtnl_lock() held. */
static int ef100_net_open(struct net_device *net_dev)
{
	struct efx_nic *efx = netdev_priv(net_dev);
	struct efx_nic *efx = efx_netdev_priv(net_dev);
	unsigned int allocated_vis;
	int rc;

@@ -172,6 +175,8 @@ static int ef100_net_open(struct net_device *net_dev)
		efx_link_status_changed(efx);
	mutex_unlock(&efx->mac_lock);

	efx->state = STATE_NET_UP;

	return 0;

fail:
@@ -189,7 +194,7 @@ static int ef100_net_open(struct net_device *net_dev)
static netdev_tx_t ef100_hard_start_xmit(struct sk_buff *skb,
					 struct net_device *net_dev)
{
	struct efx_nic *efx = netdev_priv(net_dev);
	struct efx_nic *efx = efx_netdev_priv(net_dev);
	struct efx_tx_queue *tx_queue;
	struct efx_channel *channel;
	int rc;
@@ -239,13 +244,14 @@ int ef100_netdev_event(struct notifier_block *this,
	struct efx_nic *efx = container_of(this, struct efx_nic, netdev_notifier);
	struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);

	if (netdev_priv(net_dev) == efx && event == NETDEV_CHANGENAME)
	if (efx->net_dev == net_dev &&
	    (event == NETDEV_CHANGENAME || event == NETDEV_REGISTER))
		ef100_update_name(efx);

	return NOTIFY_DONE;
}

int ef100_register_netdev(struct efx_nic *efx)
static int ef100_register_netdev(struct efx_nic *efx)
{
	struct net_device *net_dev = efx->net_dev;
	int rc;
@@ -271,7 +277,7 @@ int ef100_register_netdev(struct efx_nic *efx)
	/* Always start with carrier off; PHY events will detect the link */
	netif_carrier_off(net_dev);

	efx->state = STATE_READY;
	efx->state = STATE_NET_DOWN;
	rtnl_unlock();
	efx_init_mcdi_logging(efx);

@@ -283,11 +289,119 @@ int ef100_register_netdev(struct efx_nic *efx)
	return rc;
}

void ef100_unregister_netdev(struct efx_nic *efx)
static void ef100_unregister_netdev(struct efx_nic *efx)
{
	if (efx_dev_registered(efx)) {
		efx_fini_mcdi_logging(efx);
		efx->state = STATE_UNINIT;
		efx->state = STATE_PROBED;
		unregister_netdev(efx->net_dev);
	}
}

void ef100_remove_netdev(struct efx_probe_data *probe_data)
{
	struct efx_nic *efx = &probe_data->efx;

	if (!efx->net_dev)
		return;

	rtnl_lock();
	dev_close(efx->net_dev);
	rtnl_unlock();

	unregister_netdevice_notifier(&efx->netdev_notifier);
#if defined(CONFIG_SFC_SRIOV)
	if (!efx->type->is_vf)
		efx_ef100_pci_sriov_disable(efx);
#endif

	ef100_unregister_netdev(efx);

	down_write(&efx->filter_sem);
	efx_mcdi_filter_table_remove(efx);
	up_write(&efx->filter_sem);
	efx_fini_channels(efx);
	kfree(efx->phy_data);
	efx->phy_data = NULL;

	free_netdev(efx->net_dev);
	efx->net_dev = NULL;
	efx->state = STATE_PROBED;
}

int ef100_probe_netdev(struct efx_probe_data *probe_data)
{
	struct efx_nic *efx = &probe_data->efx;
	struct efx_probe_data **probe_ptr;
	struct net_device *net_dev;
	int rc;

	if (efx->mcdi->fn_flags &
			(1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_NO_ACTIVE_PORT)) {
		pci_info(efx->pci_dev, "No network port on this PCI function");
		return 0;
	}

	/* Allocate and initialise a struct net_device */
	net_dev = alloc_etherdev_mq(sizeof(probe_data), EFX_MAX_CORE_TX_QUEUES);
	if (!net_dev)
		return -ENOMEM;
	probe_ptr = netdev_priv(net_dev);
	*probe_ptr = probe_data;
	efx->net_dev = net_dev;
	SET_NETDEV_DEV(net_dev, &efx->pci_dev->dev);

	net_dev->features |= efx->type->offload_features;
	net_dev->hw_features |= efx->type->offload_features;
	net_dev->hw_enc_features |= efx->type->offload_features;
	net_dev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_SG |
				  NETIF_F_HIGHDMA | NETIF_F_ALL_TSO;
	netif_set_tso_max_segs(net_dev,
			       ESE_EF100_DP_GZ_TSO_MAX_HDR_NUM_SEGS_DEFAULT);
	efx->mdio.dev = net_dev;

	rc = efx_ef100_init_datapath_caps(efx);
	if (rc < 0)
		goto fail;

	rc = ef100_phy_probe(efx);
	if (rc)
		goto fail;

	rc = efx_init_channels(efx);
	if (rc)
		goto fail;

	down_write(&efx->filter_sem);
	rc = ef100_filter_table_probe(efx);
	up_write(&efx->filter_sem);
	if (rc)
		goto fail;

	netdev_rss_key_fill(efx->rss_context.rx_hash_key,
			    sizeof(efx->rss_context.rx_hash_key));

	/* Don't fail init if RSS setup doesn't work. */
	efx_mcdi_push_default_indir_table(efx, efx->n_rx_channels);

	rc = ef100_register_netdev(efx);
	if (rc)
		goto fail;

	if (!efx->type->is_vf) {
		rc = ef100_probe_netdev_pf(efx);
		if (rc)
			goto fail;
	}

	efx->netdev_notifier.notifier_call = ef100_netdev_event;
	rc = register_netdevice_notifier(&efx->netdev_notifier);
	if (rc) {
		netif_err(efx, probe, efx->net_dev,
			  "Failed to register netdevice notifier, rc=%d\n", rc);
		goto fail;
	}

fail:
	return rc;
}
+2 −2
Original line number Diff line number Diff line
@@ -13,5 +13,5 @@

int ef100_netdev_event(struct notifier_block *this,
		       unsigned long event, void *ptr);
int ef100_register_netdev(struct efx_nic *efx);
void ef100_unregister_netdev(struct efx_nic *efx);
int ef100_probe_netdev(struct efx_probe_data *probe_data);
void ef100_remove_netdev(struct efx_probe_data *probe_data);
Loading