@@ -75,6 +75,9 @@ static inline int cxl_hdm_decoder_count(u32 cap_hdr)
#define CXLDEV_MBOX_BG_CMD_STATUS_OFFSET 0x18
#define CXLDEV_MBOX_PAYLOAD_OFFSET 0x20
+#define CXL_DOE_PROTOCOL_COMPLIANCE 0
+#define CXL_DOE_PROTOCOL_TABLE_ACCESS 2
+
/*
* Using struct_group() allows for per register-block-type helper routines,
* without requiring block-type agnostic code to include the prefix.
@@ -97,6 +97,7 @@ struct cxl_mbox_cmd {
* Currently only memory devices are represented.
*
* @dev: The device associated with this CXL state
+ * @cdat_doe: Auxiliary DOE device capabile of reading CDAT
* @regs: Parsed register blocks
* @payload_size: Size of space for payload
* (CXL 2.0 8.2.8.4.3 Mailbox Capabilities Register)
@@ -124,6 +125,7 @@ struct cxl_mbox_cmd {
struct cxl_dev_state {
struct device *dev;
+ struct pci_doe_dev *cdat_doe;
struct cxl_regs regs;
size_t payload_size;
@@ -472,12 +472,53 @@ static int cxl_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
return rc;
}
+static int cxl_match_cdat_doe_device(struct device *dev, const void *data)
+{
+ const struct cxl_dev_state *cxlds = data;
+ struct auxiliary_device *adev;
+ struct pci_doe_dev *doe_dev;
+
+ /* First determine if this auxiliary device belongs to the cxlds */
+ if (cxlds->dev != dev->parent)
+ return 0;
+
+ adev = to_auxiliary_dev(dev);
+ doe_dev = container_of(adev, struct pci_doe_dev, adev);
+
+ /* If it is one of ours check for the CDAT protocol */
+ if (pci_doe_supports_prot(doe_dev, PCI_DVSEC_VENDOR_ID_CXL,
+ CXL_DOE_PROTOCOL_TABLE_ACCESS))
+ return 1;
+
+ return 0;
+}
+
static int cxl_setup_doe_devices(struct cxl_dev_state *cxlds)
{
struct device *dev = cxlds->dev;
struct pci_dev *pdev = to_pci_dev(dev);
+ struct auxiliary_device *adev;
+ int rc;
- return pci_doe_create_doe_devices(pdev);
+ rc = pci_doe_create_doe_devices(pdev);
+ if (rc)
+ return rc;
+
+ adev = auxiliary_find_device(NULL, cxlds, &cxl_match_cdat_doe_device);
+
+ if (adev) {
+ struct pci_doe_dev *doe_dev = container_of(adev,
+ struct pci_doe_dev,
+ adev);
+
+ /*
+ * No reference need be taken. The DOE device lifetime is
+ * longer that the CXL device state lifetime
+ */
+ cxlds->cdat_doe = doe_dev;
+ }
+
+ return 0;
}
static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)