fm10k: Add support for SR-IOV to driver

This patch combines the recently added VF messaging and configuration
functionality with the interfaces provided by the kernel to allow for
configuration and management of SR-IOV.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
index 9cc4d62..7935c1a 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -152,6 +152,8 @@
 
 	rtnl_lock();
 
+	fm10k_iov_suspend(interface->pdev);
+
 	if (netif_running(netdev))
 		fm10k_close(netdev);
 
@@ -171,6 +173,8 @@
 	if (netif_running(netdev))
 		fm10k_open(netdev);
 
+	fm10k_iov_resume(interface->pdev);
+
 	rtnl_unlock();
 
 	clear_bit(__FM10K_RESETTING, &interface->state);
@@ -260,6 +264,9 @@
 {
 	/* process upstream mailbox and update device state */
 	fm10k_watchdog_update_host_state(interface);
+
+	/* process downstream mailboxes */
+	fm10k_iov_mbx(interface);
 }
 
 /**
@@ -975,6 +982,7 @@
 	/* service mailboxes */
 	if (fm10k_mbx_trylock(interface)) {
 		mbx->ops.process(hw, mbx);
+		fm10k_iov_event(interface);
 		fm10k_mbx_unlock(interface);
 	}
 
@@ -1159,6 +1167,11 @@
 
 	interface = container_of(hw, struct fm10k_intfc, hw);
 
+	/* check to see if this belongs to one of the VFs */
+	err = fm10k_iov_update_pvid(interface, glort, pvid);
+	if (!err)
+		return 0;
+
 	/* we need to reset if default VLAN was just updated */
 	if (pvid != hw->mac.default_vid)
 		interface->flags |= FM10K_FLAG_RESET_REQUESTED;
@@ -1477,6 +1490,10 @@
 	memcpy(&hw->mac.ops, fi->mac_ops, sizeof(hw->mac.ops));
 	hw->mac.type = fi->mac;
 
+	/* Setup IOV handlers */
+	if (fi->iov_ops)
+		memcpy(&hw->iov.ops, fi->iov_ops, sizeof(hw->iov.ops));
+
 	/* Set common capability flags and settings */
 	rss = min_t(int, FM10K_MAX_RSS_INDICES, num_online_cpus());
 	interface->ring_feature[RING_F_RSS].limit = rss;
@@ -1509,6 +1526,9 @@
 	/* initialize hardware statistics */
 	hw->mac.ops.update_hw_stats(hw, &interface->stats);
 
+	/* Set upper limit on IOV VFs that can be allocated */
+	pci_sriov_set_totalvfs(pdev, hw->iov.total_vfs);
+
 	/* Start with random Ethernet address */
 	eth_random_addr(hw->mac.addr);
 
@@ -1708,6 +1728,9 @@
 	/* print warning for non-optimal configurations */
 	fm10k_slot_warn(interface);
 
+	/* enable SR-IOV after registering netdev to enforce PF/VF ordering */
+	fm10k_iov_configure(pdev, 0);
+
 	/* clear the service task disable bit to allow service task to start */
 	clear_bit(__FM10K_SERVICE_DISABLE, &interface->state);
 
@@ -1751,6 +1774,9 @@
 	if (netdev->reg_state == NETREG_REGISTERED)
 		unregister_netdev(netdev);
 
+	/* release VFs */
+	fm10k_iov_disable(pdev);
+
 	/* disable mailbox interrupt */
 	fm10k_mbx_free_irq(interface);
 
@@ -1827,6 +1853,9 @@
 	if (err)
 		return err;
 
+	/* restore SR-IOV interface */
+	fm10k_iov_resume(pdev);
+
 	netif_device_attach(netdev);
 
 	return 0;
@@ -1848,6 +1877,8 @@
 
 	netif_device_detach(netdev);
 
+	fm10k_iov_suspend(pdev);
+
 	rtnl_lock();
 
 	if (netif_running(netdev))
@@ -1989,6 +2020,7 @@
 	.suspend		= fm10k_suspend,
 	.resume			= fm10k_resume,
 #endif
+	.sriov_configure	= fm10k_iov_configure,
 	.err_handler		= &fm10k_err_handler
 };