RE: [PATCH v2 08/27] ocxl: Save the device serial number in ocxl_fn
From: Alastair D'Silva <hidden>
Date: 2020-02-19 04:03:28
Also in:
linux-mm, lkml, nvdimm
On Mon, 2020-02-03 at 12:53 +0000, Jonathan Cameron wrote:
On Tue, 3 Dec 2019 14:46:36 +1100 Alastair D'Silva [off-list ref] wrote:quoted
From: Alastair D'Silva <redacted> This patch retrieves the serial number of the card and makes it available to consumers of the ocxl driver via the ocxl_fn struct. Signed-off-by: Alastair D'Silva <redacted> Acked-by: Frederic Barrat <redacted> Acked-by: Andrew Donnellan <redacted> --- drivers/misc/ocxl/config.c | 46 ++++++++++++++++++++++++++++++++++++++ include/misc/ocxl.h | 1 + 2 files changed, 47 insertions(+)diff --git a/drivers/misc/ocxl/config.cb/drivers/misc/ocxl/config.c index fb0c3b6f8312..a9203c309365 100644--- a/drivers/misc/ocxl/config.c +++ b/drivers/misc/ocxl/config.c@@ -71,6 +71,51 @@ static int find_dvsec_afu_ctrl(struct pci_dev*dev, u8 afu_idx) return 0; } +/**Make sure anything you mark as kernel doc with /** is valid kernel-doc.
Ok
quoted
+ * Find a related PCI device (function 0) + * @device: PCI device to match + * + * Returns a pointer to the related device, or null if not found + */ +static struct pci_dev *get_function_0(struct pci_dev *dev) +{ + unsigned int devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 0); // Look for function 0Not sure the trailing comment adds much. I'd personally not bother with this wrapper at all and just call the pci functions directly where needed.
I'm not that familiar with the macros, so its not immediately obvious to me what it's doing, so my preference is to leave it.
quoted
+ + return pci_get_domain_bus_and_slot(pci_domain_nr(dev->bus), + dev->bus->number, devfn); +} + +static void read_serial(struct pci_dev *dev, struct ocxl_fn_config *fn) +{ + u32 low, high; + int pos; + + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DSN); + if (pos) { + pci_read_config_dword(dev, pos + 0x04, &low); + pci_read_config_dword(dev, pos + 0x08, &high); + + fn->serial = low | ((u64)high) << 32; + + return; + } + + if (PCI_FUNC(dev->devfn) != 0) { + struct pci_dev *related = get_function_0(dev); + + if (!related) { + fn->serial = 0; + return; + } + + read_serial(related, fn); + pci_dev_put(related); + return; + } + + fn->serial = 0; +} + static void read_pasid(struct pci_dev *dev, struct ocxl_fn_config *fn) { u16 val;@@ -208,6 +253,7 @@ int ocxl_config_read_function(struct pci_dev*dev, struct ocxl_fn_config *fn) int rc; read_pasid(dev, fn); + read_serial(dev, fn); rc = read_dvsec_tl(dev, fn); if (rc) {diff --git a/include/misc/ocxl.h b/include/misc/ocxl.h index 6f7c02f0d5e3..9843051c3c5b 100644 --- a/include/misc/ocxl.h +++ b/include/misc/ocxl.h@@ -46,6 +46,7 @@ struct ocxl_fn_config { int dvsec_afu_info_pos; /* offset of the AFU information DVSEC*/ s8 max_pasid_log; s8 max_afu_index; + u64 serial; }; enum ocxl_endian {
-- Alastair D'Silva Open Source Developer Linux Technology Centre, IBM Australia mob: 0423 762 819