Skip to content

Commit a15f2c0

Browse files
shemmingerdavem330
authored andcommitted
PCI: hv: support reporting serial number as slot information
The Hyper-V host API for PCI provides a unique "serial number" which can be used as basis for sysfs PCI slot table. This can be useful for cases where userspace wants to find the PCI device based on serial number. When an SR-IOV NIC is added, the host sends an attach message with serial number. The kernel doesn't use the serial number, but it is useful when doing the same thing in a userspace driver such as the DPDK. By having /sys/bus/pci/slots/N it provides a direct way to find the matching PCI device. There maybe some cases where serial number is not unique such as when using GPU's. But the PCI slot infrastructure will handle that. This has a side effect which may also be useful. The common udev network device naming policy uses the slot information (rather than PCI address). Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 28ea334 commit a15f2c0

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

drivers/pci/controller/pci-hyperv.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ static enum pci_protocol_version_t pci_protocol_version;
8989

9090
#define STATUS_REVISION_MISMATCH 0xC0000059
9191

92+
/* space for 32bit serial number as string */
93+
#define SLOT_NAME_SIZE 11
94+
9295
/*
9396
* Message Types
9497
*/
@@ -494,6 +497,7 @@ struct hv_pci_dev {
494497
struct list_head list_entry;
495498
refcount_t refs;
496499
enum hv_pcichild_state state;
500+
struct pci_slot *pci_slot;
497501
struct pci_function_description desc;
498502
bool reported_missing;
499503
struct hv_pcibus_device *hbus;
@@ -1457,6 +1461,34 @@ static void prepopulate_bars(struct hv_pcibus_device *hbus)
14571461
spin_unlock_irqrestore(&hbus->device_list_lock, flags);
14581462
}
14591463

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 (!hpdev->pci_slot)
1488+
pr_warn("pci_create slot %s failed\n", name);
1489+
}
1490+
}
1491+
14601492
/**
14611493
* create_root_hv_pci_bus() - Expose a new root PCI bus
14621494
* @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)
14801512
pci_lock_rescan_remove();
14811513
pci_scan_child_bus(hbus->pci_bus);
14821514
pci_bus_assign_resources(hbus->pci_bus);
1515+
hv_pci_assign_slots(hbus);
14831516
pci_bus_add_devices(hbus->pci_bus);
14841517
pci_unlock_rescan_remove();
14851518
hbus->state = hv_pcibus_installed;
@@ -1742,6 +1775,7 @@ static void pci_devices_present_work(struct work_struct *work)
17421775
*/
17431776
pci_lock_rescan_remove();
17441777
pci_scan_child_bus(hbus->pci_bus);
1778+
hv_pci_assign_slots(hbus);
17451779
pci_unlock_rescan_remove();
17461780
break;
17471781

@@ -1858,6 +1892,9 @@ static void hv_eject_device_work(struct work_struct *work)
18581892
list_del(&hpdev->list_entry);
18591893
spin_unlock_irqrestore(&hpdev->hbus->device_list_lock, flags);
18601894

1895+
if (hpdev->pci_slot)
1896+
pci_destroy_slot(hpdev->pci_slot);
1897+
18611898
memset(&ctxt, 0, sizeof(ctxt));
18621899
ejct_pkt = (struct pci_eject_response *)&ctxt.pkt.message;
18631900
ejct_pkt->message_type.type = PCI_EJECTION_COMPLETE;

0 commit comments

Comments
 (0)