diff options
Diffstat (limited to 'drivers/pci/controller/pci-hyperv.c')
-rw-r--r-- | drivers/pci/controller/pci-hyperv.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index c00f82cc54aa..9ba4d12c179c 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,36 @@ 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 | */ | ||
1473 | static 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 (IS_ERR(hpdev->pci_slot)) { | ||
1488 | pr_warn("pci_create slot %s failed\n", name); | ||
1489 | hpdev->pci_slot = NULL; | ||
1490 | } | ||
1491 | } | ||
1492 | } | ||
1493 | |||
1460 | /** | 1494 | /** |
1461 | * create_root_hv_pci_bus() - Expose a new root PCI bus | 1495 | * create_root_hv_pci_bus() - Expose a new root PCI bus |
1462 | * @hbus: Root PCI bus, as understood by this driver | 1496 | * @hbus: Root PCI bus, as understood by this driver |
@@ -1480,6 +1514,7 @@ static int create_root_hv_pci_bus(struct hv_pcibus_device *hbus) | |||
1480 | pci_lock_rescan_remove(); | 1514 | pci_lock_rescan_remove(); |
1481 | pci_scan_child_bus(hbus->pci_bus); | 1515 | pci_scan_child_bus(hbus->pci_bus); |
1482 | pci_bus_assign_resources(hbus->pci_bus); | 1516 | pci_bus_assign_resources(hbus->pci_bus); |
1517 | hv_pci_assign_slots(hbus); | ||
1483 | pci_bus_add_devices(hbus->pci_bus); | 1518 | pci_bus_add_devices(hbus->pci_bus); |
1484 | pci_unlock_rescan_remove(); | 1519 | pci_unlock_rescan_remove(); |
1485 | hbus->state = hv_pcibus_installed; | 1520 | hbus->state = hv_pcibus_installed; |
@@ -1742,6 +1777,7 @@ static void pci_devices_present_work(struct work_struct *work) | |||
1742 | */ | 1777 | */ |
1743 | pci_lock_rescan_remove(); | 1778 | pci_lock_rescan_remove(); |
1744 | pci_scan_child_bus(hbus->pci_bus); | 1779 | pci_scan_child_bus(hbus->pci_bus); |
1780 | hv_pci_assign_slots(hbus); | ||
1745 | pci_unlock_rescan_remove(); | 1781 | pci_unlock_rescan_remove(); |
1746 | break; | 1782 | break; |
1747 | 1783 | ||
@@ -1858,6 +1894,9 @@ static void hv_eject_device_work(struct work_struct *work) | |||
1858 | list_del(&hpdev->list_entry); | 1894 | list_del(&hpdev->list_entry); |
1859 | spin_unlock_irqrestore(&hpdev->hbus->device_list_lock, flags); | 1895 | spin_unlock_irqrestore(&hpdev->hbus->device_list_lock, flags); |
1860 | 1896 | ||
1897 | if (hpdev->pci_slot) | ||
1898 | pci_destroy_slot(hpdev->pci_slot); | ||
1899 | |||
1861 | memset(&ctxt, 0, sizeof(ctxt)); | 1900 | memset(&ctxt, 0, sizeof(ctxt)); |
1862 | ejct_pkt = (struct pci_eject_response *)&ctxt.pkt.message; | 1901 | ejct_pkt = (struct pci_eject_response *)&ctxt.pkt.message; |
1863 | ejct_pkt->message_type.type = PCI_EJECTION_COMPLETE; | 1902 | ejct_pkt->message_type.type = PCI_EJECTION_COMPLETE; |