Messages in this thread Patch in this message | | | From | kys@exchange ... | Subject | [PATCH 3/3] hv_netvsc: Implement VF matching based on serial numbers | Date | Thu, 8 Dec 2016 00:33:43 -0800 |
| |
From: Haiyang Zhang <haiyangz@microsoft.com>
We currently use MAC address to match VF and synthetic NICs. Hyper-V provides a serial number to both devices for this purpose. This patch implements the matching based on VF serial numbers. This is the way specified by the protocol and more reliable.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> --- drivers/net/hyperv/netvsc_drv.c | 55 ++++++++++++++++++++++++++++++++++++--- 1 files changed, 51 insertions(+), 4 deletions(-)
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 9522763..c5778cf 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -1165,9 +1165,10 @@ static void netvsc_free_netdev(struct net_device *netdev) free_netdev(netdev); } -static struct net_device *get_netvsc_bymac(const u8 *mac) +static struct net_device *get_netvsc_byvfser(u32 vfser) { struct net_device *dev; + struct net_device_context *ndev_ctx; ASSERT_RTNL(); @@ -1175,7 +1176,8 @@ static void netvsc_free_netdev(struct net_device *netdev) if (dev->netdev_ops != &device_ops) continue; /* not a netvsc device */ - if (ether_addr_equal(mac, dev->perm_addr)) + ndev_ctx = netdev_priv(dev); + if (ndev_ctx->vf_serial == vfser) return dev; } @@ -1205,21 +1207,66 @@ static void netvsc_free_netdev(struct net_device *netdev) return NULL; } +static u32 netvsc_get_vfser(struct net_device *vf_netdev) +{ + struct device *dev; + struct hv_device *hdev; + struct hv_pcibus_device *hbus = NULL; + struct list_head *iter; + struct hv_pci_dev *hpdev; + unsigned long flags; + u32 vfser = 0; + u32 count = 0; + + for (dev = &vf_netdev->dev; dev; dev = dev->parent) { + if (!dev_is_vmbus(dev)) + continue; + + hdev = device_to_hv_device(dev); + if (hdev->device_id != HV_PCIE) + continue; + + hbus = hv_get_drvdata(hdev); + break; + } + + if (!hbus) + return 0; + + spin_lock_irqsave(&hbus->device_list_lock, flags); + list_for_each(iter, &hbus->children) { + hpdev = container_of(iter, struct hv_pci_dev, list_entry); + vfser = hpdev->desc.ser; + count++; + } + spin_unlock_irqrestore(&hbus->device_list_lock, flags); + + if (count == 1) + return vfser; + + return 0; +} + static int netvsc_register_vf(struct net_device *vf_netdev) { struct net_device *ndev; struct net_device_context *net_device_ctx; struct netvsc_device *netvsc_dev; + u32 vfser; if (vf_netdev->addr_len != ETH_ALEN) return NOTIFY_DONE; + vfser = netvsc_get_vfser(vf_netdev); + if (!vfser) + return NOTIFY_DONE; + /* - * We will use the MAC address to locate the synthetic interface to + * We will use the VF serial 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_byvfser(vfser); if (!ndev) return NOTIFY_DONE; -- 1.7.4.1
| |