int ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
{
	unsigned int num_vfs = adapter->num_vfs, vf;
	int rss;

	/* set num VFs to 0 to prevent access to vfinfo */
	adapter->num_vfs = 0;

	/* put the reference to all of the vf devices */
	for (vf = 0; vf < num_vfs; ++vf) {
		struct pci_dev *vfdev = adapter->vfinfo[vf].vfdev;

		if (!vfdev)
			continue;
		adapter->vfinfo[vf].vfdev = NULL;
		pci_dev_put(vfdev);
	}

	/* free VF control structures */
	kfree(adapter->vfinfo);
	adapter->vfinfo = NULL;

	/* free macvlan list */
	kfree(adapter->mv_list);
	adapter->mv_list = NULL;

	/* if SR-IOV is already disabled then there is nothing to do */
	if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
		return 0;

#ifdef CONFIG_PCI_IOV
	/*
	 * If our VFs are assigned we cannot shut down SR-IOV
	 * without causing issues, so just leave the hardware
	 * available but disabled
	 */
	if (pci_vfs_assigned(adapter->pdev)) {
		e_dev_warn("Unloading driver while VFs are assigned - VFs will not be deallocated\n");
		return -EPERM;
	}
	/* disable iov and allow time for transactions to clear */
	pci_disable_sriov(adapter->pdev);
#endif

	/* Disable VMDq flag so device will be set in VM mode */
	if (bitmap_weight(adapter->fwd_bitmask, adapter->num_rx_pools) == 1) {
		adapter->flags &= ~IXGBE_FLAG_VMDQ_ENABLED;
		adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
		rss = min_t(int, ixgbe_max_rss_indices(adapter),
			    num_online_cpus());
	} else {
		rss = min_t(int, IXGBE_MAX_L2A_QUEUES, num_online_cpus());
	}

	adapter->ring_feature[RING_F_VMDQ].offset = 0;
	adapter->ring_feature[RING_F_RSS].limit = rss;

	/* take a breather then clean up driver data */
	msleep(100);
	return 0;
}
int ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
{
	unsigned int num_vfs = adapter->num_vfs, vf;
	int rss;

	 
	adapter->num_vfs = 0;

	 
	for (vf = 0; vf < num_vfs; ++vf) {
		struct pci_dev *vfdev = adapter->vfinfo[vf].vfdev;

		if (!vfdev)
			continue;
		adapter->vfinfo[vf].vfdev = NULL;
		pci_dev_put(vfdev);
	}

	 
	kfree(adapter->vfinfo);
	adapter->vfinfo = NULL;

	 
	kfree(adapter->mv_list);
	adapter->mv_list = NULL;

	 
	if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
		return 0;

#ifdef CONFIG_PCI_IOV
	 
	if (pci_vfs_assigned(adapter->pdev)) {
		e_dev_warn("Unloading driver while VFs are assigned - VFs will not be deallocated\n");
		return -EPERM;
	}
	 
	pci_disable_sriov(adapter->pdev);
#endif

	 
	if (bitmap_weight(adapter->fwd_bitmask, adapter->num_rx_pools) == 1) {
		adapter->flags &= ~IXGBE_FLAG_VMDQ_ENABLED;
		adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
		rss = min_t(int, ixgbe_max_rss_indices(adapter),
			    num_online_cpus());
	} else {
		rss = min_t(int, IXGBE_MAX_L2A_QUEUES, num_online_cpus());
	}

	adapter->ring_feature[RING_F_VMDQ].offset = 0;
	adapter->ring_feature[RING_F_RSS].limit = rss;

	 
	msleep(100);
	return 0;
}