aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-09-17 10:59:41 -0400
committerDavid S. Miller <davem@davemloft.net>2018-09-17 10:59:41 -0400
commitaa079bd05032bc068c28fc9111d952d67134b395 (patch)
treee0815806a52bc6669417949d52257c22539bdf70
parent28ea334bd1657f3c43485b4a8592672fc6835fac (diff)
parent00d7ddba1143623b31bc2c15d18216e2da031b14 (diff)
Merge branch 'hv_netvsc-associate-VF-and-PV-device-by-serial-number'
Stephen Hemminger says: ==================== hv_netvsc: associate VF and PV device by serial number The Hyper-V implementation of PCI controller has concept of 32 bit serial number (not to be confused with PCI-E serial number). This value is sent in the protocol from the host to indicate SR-IOV VF device is attached to a synthetic NIC. Using the serial number (instead of MAC address) to associate the two devices avoids lots of potential problems when there are duplicate MAC addresses from tunnels or layered devices. The patch set is broken into two parts, one is for the PCI controller and the other is for the netvsc device. Normally, these go through different trees but sending them together here for better review. The PCI changes were submitted previously, but the main review comment was "why do you need this?". This is why. v2 - slot name can be shorter. remove locking when creating pci_slots; see comment for explaination ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/hyperv/netvsc.c3
-rw-r--r--drivers/net/hyperv/netvsc_drv.c58
-rw-r--r--drivers/pci/controller/pci-hyperv.c37
3 files changed, 73 insertions, 25 deletions
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 31c3d77b4733..fe01e141c8f8 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -1203,6 +1203,9 @@ static void netvsc_send_vf(struct net_device *ndev,
1203 1203
1204 net_device_ctx->vf_alloc = nvmsg->msg.v4_msg.vf_assoc.allocated; 1204 net_device_ctx->vf_alloc = nvmsg->msg.v4_msg.vf_assoc.allocated;
1205 net_device_ctx->vf_serial = nvmsg->msg.v4_msg.vf_assoc.serial; 1205 net_device_ctx->vf_serial = nvmsg->msg.v4_msg.vf_assoc.serial;
1206 netdev_info(ndev, "VF slot %u %s\n",
1207 net_device_ctx->vf_serial,
1208 net_device_ctx->vf_alloc ? "added" : "removed");
1206} 1209}
1207 1210
1208static void netvsc_receive_inband(struct net_device *ndev, 1211static void netvsc_receive_inband(struct net_device *ndev,
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 915fbd66a02b..3af6d8d15233 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1894,20 +1894,6 @@ out_unlock:
1894 rtnl_unlock(); 1894 rtnl_unlock();
1895} 1895}
1896 1896
1897static struct net_device *get_netvsc_bymac(const u8 *mac)
1898{
1899 struct net_device_context *ndev_ctx;
1900
1901 list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
1902 struct net_device *dev = hv_get_drvdata(ndev_ctx->device_ctx);
1903
1904 if (ether_addr_equal(mac, dev->perm_addr))
1905 return dev;
1906 }
1907
1908 return NULL;
1909}
1910
1911static struct net_device *get_netvsc_byref(struct net_device *vf_netdev) 1897static struct net_device *get_netvsc_byref(struct net_device *vf_netdev)
1912{ 1898{
1913 struct net_device_context *net_device_ctx; 1899 struct net_device_context *net_device_ctx;
@@ -2036,26 +2022,48 @@ static void netvsc_vf_setup(struct work_struct *w)
2036 rtnl_unlock(); 2022 rtnl_unlock();
2037} 2023}
2038 2024
2025/* Find netvsc by VMBus serial number.
2026 * The PCI hyperv controller records the serial number as the slot.
2027 */
2028static struct net_device *get_netvsc_byslot(const struct net_device *vf_netdev)
2029{
2030 struct device *parent = vf_netdev->dev.parent;
2031 struct net_device_context *ndev_ctx;
2032 struct pci_dev *pdev;
2033
2034 if (!parent || !dev_is_pci(parent))
2035 return NULL; /* not a PCI device */
2036
2037 pdev = to_pci_dev(parent);
2038 if (!pdev->slot) {
2039 netdev_notice(vf_netdev, "no PCI slot information\n");
2040 return NULL;
2041 }
2042
2043 list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
2044 if (!ndev_ctx->vf_alloc)
2045 continue;
2046
2047 if (ndev_ctx->vf_serial == pdev->slot->number)
2048 return hv_get_drvdata(ndev_ctx->device_ctx);
2049 }
2050
2051 netdev_notice(vf_netdev,
2052 "no netdev found for slot %u\n", pdev->slot->number);
2053 return NULL;
2054}
2055
2039static int netvsc_register_vf(struct net_device *vf_netdev) 2056static int netvsc_register_vf(struct net_device *vf_netdev)
2040{ 2057{
2041 struct net_device *ndev;
2042 struct net_device_context *net_device_ctx; 2058 struct net_device_context *net_device_ctx;
2043 struct device *pdev = vf_netdev->dev.parent;
2044 struct netvsc_device *netvsc_dev; 2059 struct netvsc_device *netvsc_dev;
2060 struct net_device *ndev;
2045 int ret; 2061 int ret;
2046 2062
2047 if (vf_netdev->addr_len != ETH_ALEN) 2063 if (vf_netdev->addr_len != ETH_ALEN)
2048 return NOTIFY_DONE; 2064 return NOTIFY_DONE;
2049 2065
2050 if (!pdev || !dev_is_pci(pdev) || dev_is_pf(pdev)) 2066 ndev = get_netvsc_byslot(vf_netdev);
2051 return NOTIFY_DONE;
2052
2053 /*
2054 * We will use the MAC address to locate the synthetic interface to
2055 * associate with the VF interface. If we don't find a matching
2056 * synthetic interface, move on.
2057 */
2058 ndev = get_netvsc_bymac(vf_netdev->perm_addr);
2059 if (!ndev) 2067 if (!ndev)
2060 return NOTIFY_DONE; 2068 return NOTIFY_DONE;
2061 2069
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index c00f82cc54aa..ee80e79db21a 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -89,6 +89,9 @@ static enum pci_protocol_version_t pci_protocol_version;
89 89
90#define STATUS_REVISION_MISMATCH 0xC0000059 90#define STATUS_REVISION_MISMATCH 0xC0000059
91 91
92/* space for 32bit serial number as string */
93#define SLOT_NAME_SIZE 11
94
92/* 95/*
93 * Message Types 96 * Message Types
94 */ 97 */
@@ -494,6 +497,7 @@ struct hv_pci_dev {
494 struct list_head list_entry; 497 struct list_head list_entry;
495 refcount_t refs; 498 refcount_t refs;
496 enum hv_pcichild_state state; 499 enum hv_pcichild_state state;
500 struct pci_slot *pci_slot;
497 struct pci_function_description desc; 501 struct pci_function_description desc;
498 bool reported_missing; 502 bool reported_missing;
499 struct hv_pcibus_device *hbus; 503 struct hv_pcibus_device *hbus;
@@ -1457,6 +1461,34 @@ static void prepopulate_bars(struct hv_pcibus_device *hbus)
1457 spin_unlock_irqrestore(&hbus->device_list_lock, flags); 1461 spin_unlock_irqrestore(&hbus->device_list_lock, flags);
1458} 1462}
1459 1463
1464/*
1465 * Assign entries in sysfs pci slot directory.
1466 *
1467 * Note that this function does not need to lock the children list
1468 * because it is called from pci_devices_present_work which
1469 * is serialized with hv_eject_device_work because they are on the
1470 * same ordered workqueue. Therefore hbus->children list will not change
1471 * even when pci_create_slot sleeps.
1472 */
1473static void hv_pci_assign_slots(struct hv_pcibus_device *hbus)
1474{
1475 struct hv_pci_dev *hpdev;
1476 char name[SLOT_NAME_SIZE];
1477 int slot_nr;
1478
1479 list_for_each_entry(hpdev, &hbus->children, list_entry) {
1480 if (hpdev->pci_slot)
1481 continue;
1482
1483 slot_nr = PCI_SLOT(wslot_to_devfn(hpdev->desc.win_slot.slot));
1484 snprintf(name, SLOT_NAME_SIZE, "%u", hpdev->desc.ser);
1485 hpdev->pci_slot = pci_create_slot(hbus->pci_bus, slot_nr,
1486 name, NULL);
1487 if (!hpdev->pci_slot)
1488 pr_warn("pci_create slot %s failed\n", name);
1489 }
1490}
1491
1460/** 1492/**
1461 * create_root_hv_pci_bus() - Expose a new root PCI bus 1493 * create_root_hv_pci_bus() - Expose a new root PCI bus
1462 * @hbus: Root PCI bus, as understood by this driver 1494 * @hbus: Root PCI bus, as understood by this driver
@@ -1480,6 +1512,7 @@ static int create_root_hv_pci_bus(struct hv_pcibus_device *hbus)
1480 pci_lock_rescan_remove(); 1512 pci_lock_rescan_remove();
1481 pci_scan_child_bus(hbus->pci_bus); 1513 pci_scan_child_bus(hbus->pci_bus);
1482 pci_bus_assign_resources(hbus->pci_bus); 1514 pci_bus_assign_resources(hbus->pci_bus);
1515 hv_pci_assign_slots(hbus);
1483 pci_bus_add_devices(hbus->pci_bus); 1516 pci_bus_add_devices(hbus->pci_bus);
1484 pci_unlock_rescan_remove(); 1517 pci_unlock_rescan_remove();
1485 hbus->state = hv_pcibus_installed; 1518 hbus->state = hv_pcibus_installed;
@@ -1742,6 +1775,7 @@ static void pci_devices_present_work(struct work_struct *work)
1742 */ 1775 */
1743 pci_lock_rescan_remove(); 1776 pci_lock_rescan_remove();
1744 pci_scan_child_bus(hbus->pci_bus); 1777 pci_scan_child_bus(hbus->pci_bus);
1778 hv_pci_assign_slots(hbus);
1745 pci_unlock_rescan_remove(); 1779 pci_unlock_rescan_remove();
1746 break; 1780 break;
1747 1781
@@ -1858,6 +1892,9 @@ static void hv_eject_device_work(struct work_struct *work)
1858 list_del(&hpdev->list_entry); 1892 list_del(&hpdev->list_entry);
1859 spin_unlock_irqrestore(&hpdev->hbus->device_list_lock, flags); 1893 spin_unlock_irqrestore(&hpdev->hbus->device_list_lock, flags);
1860 1894
1895 if (hpdev->pci_slot)
1896 pci_destroy_slot(hpdev->pci_slot);
1897
1861 memset(&ctxt, 0, sizeof(ctxt)); 1898 memset(&ctxt, 0, sizeof(ctxt));
1862 ejct_pkt = (struct pci_eject_response *)&ctxt.pkt.message; 1899 ejct_pkt = (struct pci_eject_response *)&ctxt.pkt.message;
1863 ejct_pkt->message_type.type = PCI_EJECTION_COMPLETE; 1900 ejct_pkt->message_type.type = PCI_EJECTION_COMPLETE;