Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932646AbcLHGig (ORCPT ); Thu, 8 Dec 2016 01:38:36 -0500 Received: from p3plsmtps2ded02.prod.phx3.secureserver.net ([208.109.80.59]:54770 "EHLO p3plsmtps2ded02.prod.phx3.secureserver.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932371AbcLHGid (ORCPT ); Thu, 8 Dec 2016 01:38:33 -0500 x-originating-ip: 72.167.245.219 From: kys@exchange.microsoft.com To: gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, devel@linuxdriverproject.org, olaf@aepfle.de, apw@canonical.com, vkuznets@redhat.com, jasowang@redhat.com, leann.ogasawara@canonical.com, bjorn.helgaas@gmail.com Cc: Haiyang Zhang , "K. Y. Srinivasan" Subject: [PATCH 3/3] hv_netvsc: Implement VF matching based on serial numbers Date: Thu, 8 Dec 2016 00:33:43 -0800 Message-Id: <1481186023-30429-3-git-send-email-kys@exchange.microsoft.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1481186023-30429-1-git-send-email-kys@exchange.microsoft.com> References: <1481185988-30383-1-git-send-email-kys@exchange.microsoft.com> <1481186023-30429-1-git-send-email-kys@exchange.microsoft.com> Reply-To: kys@microsoft.com X-CMAE-Envelope: MS4wfH06jp0HHWNT0P+FFgwTi+ak3NK5plWt0dG1dSRsQpZEfMk3OMXnk4FhYOCdbgVG9HNf7E25/OdOXXJO+PZxP2pj2LRX8xvFamVABg/xJL5PeyrtGSVP hTplxhxXatPwpGEKfFp0jrGNhDfBaz4n8k8kKJkoaQI+8CwfQAZ5zTmSHT7+2/we5lxmnPr9rxk0hPx7lDeVxRn8/1wo+lva4QjbO9dvrJhPLNSsVgW03cwE CbPAZQZLH9sTwiW0zyEmfYEUIuGs/ZSe4Bba42zU6HrXQKZS1tgw+ShqnvqQoK7hA8ZYobvWDesen0VZySSC58VfbgEhQ1Cb31Vkak5Aud9z1zKJF+vxWsI0 CUXxvdLVNjCYT9FNVCkqSEV0ATDw0NghULuyPCRl9K9t5MkOzJmTZxGv4eJToIA5gglhM7ODU9PDfbkZT1agDdOP99DWXb2aKqcdmSj5CsE7C93zSkc9MFSR 7KJMfqxxP0ZqhLm53O4b8JjB3JsObB6JaW1vsc1F5hD5uBDyh5SQel/REVE= Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2993 Lines: 110 From: Haiyang Zhang 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 Signed-off-by: K. Y. Srinivasan --- 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