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.
Unified · Split
| @@ -580,6 +580,40 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap) · 579 unmodified lines | ||
| 580 | 580 | } |
| 581 | 581 | EXPORT_SYMBOL_GPL(pci_find_ext_capability); |
| 582 | 582 | |
| 583 | +/** | |
| 584 | + * pci_get_dsn - Read and return the 8-byte Device Serial Number | |
| 585 | + * @dev: PCI device to query | |
| 586 | + * | |
| 587 | + * Looks up the PCI_EXT_CAP_ID_DSN and reads the 8 bytes of the Device Serial | |
| 588 | + * Number. | |
| 589 | + * | |
| 590 | + * Returns the DSN, or zero if the capability does not exist. | |
| 591 | + */ | |
| 592 | +u64 pci_get_dsn(struct pci_dev *dev) | |
| 593 | +{ | |
| 594 | + u32 dword; | |
| 595 | + u64 dsn; | |
| 596 | + int pos; | |
| 597 | + | |
| 598 | + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DSN); | |
| 599 | + if (!pos) | |
| 600 | + return 0; | |
| 601 | + | |
| 602 | + /* | |
| 603 | + * The Device Serial Number is two dwords offset 4 bytes from the | |
| 604 | + * capability position. The specification says that the first dword is | |
| 605 | + * the lower half, and the second dword is the upper half. | |
| 606 | + */ | |
| 607 | + pos += 4; | |
| 608 | + pci_read_config_dword(dev, pos, &dword); | |
| 609 | + dsn = (u64)dword; | |
| 610 | + pci_read_config_dword(dev, pos + 4, &dword); | |
| 611 | + dsn |= ((u64)dword) << 32; | |
| 612 | + | |
| 613 | + return dsn; | |
| 614 | +} | |
| 615 | +EXPORT_SYMBOL_GPL(pci_get_dsn); | |
| 616 | + | |
| 583 | 617 | static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap) |
| 584 | 618 | { |
| 585 | 619 | int rc, ttl = PCI_FIND_CAP_TTL; |
| @@ -1052,6 +1052,8 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap); · 1051 unmodified lines | ||
| 1052 | 1052 | int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap); |
| 1053 | 1053 | struct pci_bus *pci_find_next_bus(const struct pci_bus *from); |
| 1054 | 1054 | |
| 1055 | +u64 pci_get_dsn(struct pci_dev *dev); | |
| 1056 | + | |
| 1055 | 1057 | struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device, |
| 1056 | 1058 | struct pci_dev *from); |
| 1057 | 1059 | struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, |
| @@ -1707,6 +1709,9 @@ static inline int pci_find_next_capability(struct pci_dev *dev, u8 post, · 649 unmodified lines | ||
| 1707 | 1709 | static inline int pci_find_ext_capability(struct pci_dev *dev, int cap) |
| 1708 | 1710 | { return 0; } |
| 1709 | 1711 | |
| 1712 | +static inline u64 pci_get_dsn(struct pci_dev *dev) | |
| 1713 | +{ return 0; } | |
| 1714 | + | |
| 1710 | 1715 | /* Power management related routines */ |
| 1711 | 1716 | static inline int pci_save_state(struct pci_dev *dev) { return 0; } |
| 1712 | 1717 | static inline void pci_restore_state(struct pci_dev *dev) { } |