+++ /dev/null
-From foo@baz Tue Oct 16 11:10:21 CEST 2018
-From: Stephen Hemminger <stephen@networkplumber.org>
-Date: Fri, 14 Sep 2018 12:54:57 -0700
-Subject: hv_netvsc: pair VF based on serial number
-
-From: Stephen Hemminger <stephen@networkplumber.org>
-
-[ Upstream commit 00d7ddba1143623b31bc2c15d18216e2da031b14 ]
-
-Matching network device based on MAC address is problematic
-since a non VF network device can be creted with a duplicate MAC
-address causing confusion and problems. The VMBus API does provide
-a serial number that is a better matching method.
-
-Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/net/hyperv/netvsc.c | 3 ++
- drivers/net/hyperv/netvsc_drv.c | 58 ++++++++++++++++++++++------------------
- 2 files changed, 36 insertions(+), 25 deletions(-)
-
---- a/drivers/net/hyperv/netvsc.c
-+++ b/drivers/net/hyperv/netvsc.c
-@@ -1203,6 +1203,9 @@ static void netvsc_send_vf(struct net_de
-
- net_device_ctx->vf_alloc = nvmsg->msg.v4_msg.vf_assoc.allocated;
- net_device_ctx->vf_serial = nvmsg->msg.v4_msg.vf_assoc.serial;
-+ netdev_info(ndev, "VF slot %u %s\n",
-+ net_device_ctx->vf_serial,
-+ net_device_ctx->vf_alloc ? "added" : "removed");
- }
-
- static void netvsc_receive_inband(struct net_device *ndev,
---- a/drivers/net/hyperv/netvsc_drv.c
-+++ b/drivers/net/hyperv/netvsc_drv.c
-@@ -1794,20 +1794,6 @@ out_unlock:
- rtnl_unlock();
- }
-
--static struct net_device *get_netvsc_bymac(const u8 *mac)
--{
-- struct net_device_context *ndev_ctx;
--
-- list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
-- struct net_device *dev = hv_get_drvdata(ndev_ctx->device_ctx);
--
-- if (ether_addr_equal(mac, dev->perm_addr))
-- return dev;
-- }
--
-- return NULL;
--}
--
- static struct net_device *get_netvsc_byref(struct net_device *vf_netdev)
- {
- struct net_device_context *net_device_ctx;
-@@ -1936,26 +1922,48 @@ static void netvsc_vf_setup(struct work_
- rtnl_unlock();
- }
-
-+/* Find netvsc by VMBus serial number.
-+ * The PCI hyperv controller records the serial number as the slot.
-+ */
-+static struct net_device *get_netvsc_byslot(const struct net_device *vf_netdev)
-+{
-+ struct device *parent = vf_netdev->dev.parent;
-+ struct net_device_context *ndev_ctx;
-+ struct pci_dev *pdev;
-+
-+ if (!parent || !dev_is_pci(parent))
-+ return NULL; /* not a PCI device */
-+
-+ pdev = to_pci_dev(parent);
-+ if (!pdev->slot) {
-+ netdev_notice(vf_netdev, "no PCI slot information\n");
-+ return NULL;
-+ }
-+
-+ list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
-+ if (!ndev_ctx->vf_alloc)
-+ continue;
-+
-+ if (ndev_ctx->vf_serial == pdev->slot->number)
-+ return hv_get_drvdata(ndev_ctx->device_ctx);
-+ }
-+
-+ netdev_notice(vf_netdev,
-+ "no netdev found for slot %u\n", pdev->slot->number);
-+ return NULL;
-+}
-+
- static int netvsc_register_vf(struct net_device *vf_netdev)
- {
-- struct net_device *ndev;
- struct net_device_context *net_device_ctx;
-- struct device *pdev = vf_netdev->dev.parent;
- struct netvsc_device *netvsc_dev;
-+ struct net_device *ndev;
- int ret;
-
- if (vf_netdev->addr_len != ETH_ALEN)
- return NOTIFY_DONE;
-
-- if (!pdev || !dev_is_pci(pdev) || dev_is_pf(pdev))
-- return NOTIFY_DONE;
--
-- /*
-- * We will use the MAC address to locate the synthetic interface to
-- * associate with the VF interface. If we don't find a matching
-- * synthetic interface, move on.
-- */
-- ndev = get_netvsc_bymac(vf_netdev->perm_addr);
-+ ndev = get_netvsc_byslot(vf_netdev);
- if (!ndev)
- return NOTIFY_DONE;
-