Commit 5e0db7e4 authored by David S. Miller's avatar David S. Miller

Merge branch 'PCI-Implement-function-to-read-Device-Serial-Number'

Jacob Keller says:

====================
PCI: Implement function to read Device Serial Number

Several drivers read the Device Serial Number from the PCIe extended
configuration space. Each of these drivers implements a similar approach to
finding the position and then extracting the 8 bytes of data.

Implement a new helper function, pci_get_dsn, which can be used to extract
this data into an 8 byte array.

Modify the bnxt_en, qedf, ice, ixgbe and nfp drivers to use this new
function.

The intent for this is to reduce duplicate code across the various drivers,
and make it easier to write future code that wants to read the DSN. In
particular the ice driver will be using the DSN as its serial number when
implementing the DEVLINK_CMD_INFO_GET.

The new implementation in v2 significantly simplifies some of the callers
which just want to print the value out in MSB order. By returning things as
a u64 in CPU Endian order, the "%016llX" printf format specifier can be used
to correctly format the value.

Per patch changes since v1
  PCI: Introduce pci_get_dsn
  * Update commit message based on feedback from Bjorn Helgaas
  * Modify the function to return a u64 (zero on no capability)
  * This new implementation ensures that the first dword is the lower 32
    bits and the second dword is the upper 32 bits.

  bnxt_en: Use pci_get_dsn()
  * Use the u64 return value from pci_get_dsn()
  * Copy it into the dsn[] array by using put_unaligned_le64
  * Fix a pre-existing typo in the netdev_info error message

  scsi: qedf: Use pci_get_dsn()
  * Use the u64 return value from pci_get_dsn()
  * simplify the snprintf to use "%016llX"
  * remove the unused 'i' variable

  ice: Use pci_get_dsn()
  * Use the u64 return value from pci_get_dsn()
  * simplify the snprintf to use "%016llX"

  ixgbe: Use pci_get_dsn()
  * Use the u64 return value from pci_get_dsn()
  * simplify the snprintf to use "%016llX"

  nfp: Use pci_get_dsn()
  * Added in v2
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 367ab29e 61600112
......@@ -11751,20 +11751,16 @@ static int bnxt_init_mac_addr(struct bnxt *bp)
static int bnxt_pcie_dsn_get(struct bnxt *bp, u8 dsn[])
{
struct pci_dev *pdev = bp->pdev;
int pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DSN);
u32 dw;
u64 qword;
if (!pos) {
netdev_info(bp->dev, "Unable do read adapter's DSN\n");
qword = pci_get_dsn(pdev);
if (!qword) {
netdev_info(bp->dev, "Unable to read adapter's DSN\n");
return -EOPNOTSUPP;
}
/* DSN (two dw) is at an offset of 4 from the cap pos */
pos += 4;
pci_read_config_dword(pdev, pos, &dw);
put_unaligned_le32(dw, &dsn[0]);
pci_read_config_dword(pdev, pos + 4, &dw);
put_unaligned_le32(dw, &dsn[4]);
put_unaligned_le64(qword, dsn);
bp->flags |= BNXT_FLAG_DSN_VALID;
return 0;
}
......
......@@ -3087,30 +3087,22 @@ static char *ice_get_opt_fw_name(struct ice_pf *pf)
* followed by a EUI-64 identifier (PCIe Device Serial Number)
*/
struct pci_dev *pdev = pf->pdev;
char *opt_fw_filename = NULL;
u32 dword;
u8 dsn[8];
int pos;
char *opt_fw_filename;
u64 dsn;
/* Determine the name of the optional file using the DSN (two
* dwords following the start of the DSN Capability).
*/
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DSN);
if (pos) {
dsn = pci_get_dsn(pdev);
if (!dsn)
return NULL;
opt_fw_filename = kzalloc(NAME_MAX, GFP_KERNEL);
if (!opt_fw_filename)
return NULL;
pci_read_config_dword(pdev, pos + 4, &dword);
put_unaligned_le32(dword, &dsn[0]);
pci_read_config_dword(pdev, pos + 8, &dword);
put_unaligned_le32(dword, &dsn[4]);
snprintf(opt_fw_filename, NAME_MAX,
"%sice-%02x%02x%02x%02x%02x%02x%02x%02x.pkg",
ICE_DDP_PKG_PATH,
dsn[7], dsn[6], dsn[5], dsn[4],
dsn[3], dsn[2], dsn[1], dsn[0]);
}
snprintf(opt_fw_filename, NAME_MAX, "%sice-%016llX.pkg",
ICE_DDP_PKG_PATH, dsn);
return opt_fw_filename;
}
......
......@@ -968,8 +968,7 @@ int ixgbe_fcoe_get_hbainfo(struct net_device *netdev,
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
int i, pos;
u8 buf[8];
u64 dsn;
if (!info)
return -EINVAL;
......@@ -985,17 +984,11 @@ int ixgbe_fcoe_get_hbainfo(struct net_device *netdev,
/* Serial Number */
/* Get the PCI-e Device Serial Number Capability */
pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_DSN);
if (pos) {
pos += 4;
for (i = 0; i < 8; i++)
pci_read_config_byte(adapter->pdev, pos + i, &buf[i]);
dsn = pci_get_dsn(adapter->pdev);
if (dsn)
snprintf(info->serial_number, sizeof(info->serial_number),
"%02X%02X%02X%02X%02X%02X%02X%02X",
buf[7], buf[6], buf[5], buf[4],
buf[3], buf[2], buf[1], buf[0]);
} else
"%016llX", dsn);
else
snprintf(info->serial_number, sizeof(info->serial_number),
"Unknown");
......
......@@ -1247,19 +1247,16 @@ static void nfp6000_free(struct nfp_cpp *cpp)
static int nfp6000_read_serial(struct device *dev, u8 *serial)
{
struct pci_dev *pdev = to_pci_dev(dev);
int pos;
u32 reg;
u64 dsn;
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DSN);
if (!pos) {
dsn = pci_get_dsn(pdev);
if (!dsn) {
dev_err(dev, "can't find PCIe Serial Number Capability\n");
return -EINVAL;
}
pci_read_config_dword(pdev, pos + 4, &reg);
put_unaligned_be16(reg >> 16, serial + 4);
pci_read_config_dword(pdev, pos + 8, &reg);
put_unaligned_be32(reg, serial);
put_unaligned_be32((u32)(dsn >> 32), serial);
put_unaligned_be16((u16)(dsn >> 16), serial + 4);
return 0;
}
......@@ -1267,18 +1264,15 @@ static int nfp6000_read_serial(struct device *dev, u8 *serial)
static int nfp6000_get_interface(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
int pos;
u32 reg;
u64 dsn;
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DSN);
if (!pos) {
dsn = pci_get_dsn(pdev);
if (!dsn) {
dev_err(dev, "can't find PCIe Serial Number Capability\n");
return -EINVAL;
}
pci_read_config_dword(pdev, pos + 4, &reg);
return reg & 0xffff;
return dsn & 0xffff;
}
static const struct nfp_cpp_operations nfp6000_pcie_ops = {
......
......@@ -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;
......
......@@ -1577,8 +1577,7 @@ static void qedf_setup_fdmi(struct qedf_ctx *qedf)
{
struct fc_lport *lport = qedf->lport;
struct fc_host_attrs *fc_host = shost_to_fc_host(lport->host);
u8 buf[8];
int i, pos;
u64 dsn;
/*
* fdmi_enabled needs to be set for libfc to execute FDMI registration.
......@@ -1591,18 +1590,11 @@ static void qedf_setup_fdmi(struct qedf_ctx *qedf)
*/
/* Get the PCI-e Device Serial Number Capability */
pos = pci_find_ext_capability(qedf->pdev, PCI_EXT_CAP_ID_DSN);
if (pos) {
pos += 4;
for (i = 0; i < 8; i++)
pci_read_config_byte(qedf->pdev, pos + i, &buf[i]);
dsn = pci_get_dsn(qedf->pdev);
if (dsn)
snprintf(fc_host->serial_number,
sizeof(fc_host->serial_number),
"%02X%02X%02X%02X%02X%02X%02X%02X",
buf[7], buf[6], buf[5], buf[4],
buf[3], buf[2], buf[1], buf[0]);
} else
sizeof(fc_host->serial_number), "%016llX", dsn);
else
snprintf(fc_host->serial_number,
sizeof(fc_host->serial_number), "Unknown");
......
......@@ -1052,6 +1052,8 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
u64 pci_get_dsn(struct pci_dev *dev);
struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
struct pci_dev *from);
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,
static inline int pci_find_ext_capability(struct pci_dev *dev, int cap)
{ return 0; }
static inline u64 pci_get_dsn(struct pci_dev *dev)
{ return 0; }
/* Power management related routines */
static inline int pci_save_state(struct pci_dev *dev) { return 0; }
static inline void pci_restore_state(struct pci_dev *dev) { }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment