hv_netvsc: fix vf serial matching with pci slot info
authorHaiyang Zhang <haiyangz@microsoft.com>
Mon, 15 Oct 2018 19:06:15 +0000 (19:06 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Nov 2018 19:08:21 +0000 (11:08 -0800)
[ Upstream commit 005479556197f80139771960dda0dfdcd2d2aad5 ]

The VF device's serial number is saved as a string in PCI slot's
kobj name, not the slot->number. This patch corrects the netvsc
driver, so the VF device can be successfully paired with synthetic
NIC.

Fixes: 00d7ddba1143 ("hv_netvsc: pair VF based on serial number")
Reported-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/hyperv/netvsc_drv.c

index 3af6d8d..1c37a82 100644 (file)
@@ -2022,14 +2022,15 @@ static void netvsc_vf_setup(struct work_struct *w)
        rtnl_unlock();
 }
 
-/* Find netvsc by VMBus serial number.
- * The PCI hyperv controller records the serial number as the slot.
+/* Find netvsc by VF serial number.
+ * The PCI hyperv controller records the serial number as the slot kobj name.
  */
 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;
+       u32 serial;
 
        if (!parent || !dev_is_pci(parent))
                return NULL; /* not a PCI device */
@@ -2040,16 +2041,22 @@ static struct net_device *get_netvsc_byslot(const struct net_device *vf_netdev)
                return NULL;
        }
 
+       if (kstrtou32(pci_slot_name(pdev->slot), 10, &serial)) {
+               netdev_notice(vf_netdev, "Invalid vf serial:%s\n",
+                             pci_slot_name(pdev->slot));
+               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)
+               if (ndev_ctx->vf_serial == serial)
                        return hv_get_drvdata(ndev_ctx->device_ctx);
        }
 
        netdev_notice(vf_netdev,
-                     "no netdev found for slot %u\n", pdev->slot->number);
+                     "no netdev found for vf serial:%u\n", serial);
        return NULL;
 }