diff options
author | Jacob Keller <jacob.e.keller@intel.com> | 2020-03-03 05:25:00 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-03-06 04:36:24 +0300 |
commit | 70c0923b0ef10b1c8d8f78fb50fcaef8eaae619d (patch) | |
tree | 13fa85fb4022d726761d0e49f3c01ffc014d8d03 /drivers/pci/pci.c | |
parent | 367ab29e3d88be42504aca0af13f8ebb9451a1ed (diff) | |
download | linux-70c0923b0ef10b1c8d8f78fb50fcaef8eaae619d.tar.xz |
PCI: Introduce pci_get_dsn
Several device drivers read their Device Serial Number from the PCIe
extended config space.
Introduce a new helper function, pci_get_dsn(). This function reads the
eight bytes of the DSN and returns them as a u64. If the capability does not
exist for the device, the function returns 0.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Michael Chan <michael.chan@broadcom.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index c16b0ba2a895..86821313c007 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -580,6 +580,40 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap) } EXPORT_SYMBOL_GPL(pci_find_ext_capability); +/** + * pci_get_dsn - Read and return the 8-byte Device Serial Number + * @dev: PCI device to query + * + * Looks up the PCI_EXT_CAP_ID_DSN and reads the 8 bytes of the Device Serial + * Number. + * + * Returns the DSN, or zero if the capability does not exist. + */ +u64 pci_get_dsn(struct pci_dev *dev) +{ + u32 dword; + u64 dsn; + int pos; + + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DSN); + if (!pos) + return 0; + + /* + * The Device Serial Number is two dwords offset 4 bytes from the + * capability position. The specification says that the first dword is + * the lower half, and the second dword is the upper half. + */ + pos += 4; + pci_read_config_dword(dev, pos, &dword); + dsn = (u64)dword; + pci_read_config_dword(dev, pos + 4, &dword); + dsn |= ((u64)dword) << 32; + + return dsn; +} +EXPORT_SYMBOL_GPL(pci_get_dsn); + static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap) { int rc, ttl = PCI_FIND_CAP_TTL; |