cxl fixes for v6.15-rc4

- Series to fix using the wrong GPF DVSEC location
   - Fix caching of dport GPF DVSEC from the first endpoint
   - Ensure that the GPF phase timeout is only updated once by first endpoint
   - Drop is_port parameter for cxl_gpf_get_dvsec()
 
 - Fix the devm_* call host device for CXL fwctl setup
 
 - Set the out_len in Set Features failure case
 
 - Fix RCD initialization by skipping unneeded mem_en check
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE5DAy15EJMCV1R6v9YGjFFmlTOEoFAmgLwNkACgkQYGjFFmlT
 OEpzRg//Y0NCzHzDGwkNyI3B8az5T+X1SLmDmndlvhvMFjS+WOi/fcU8pEYJZWbf
 YEB6bX2Pt8u+rTOMKBTm2xaqJLvQ/mfKMuFRYnyGnZX7moSuHUPjn61CwqQsQOZh
 T89ymkkoy/0F0iRM2aysyM08kFnlAXRtY3yjMtnn1i34d8yRxfqmgcSAkEYXKRp4
 4XhYKoswepZvDYQ8SLIyHFwcuZulbryzRiTHFY+4ZpiFSHg0rbR94nKbPR8DOV/8
 XLPUSuKvhPmt5oZYIt9cFAHuo/HAlj25epsdZOkO73MGHRXHCukOsQ22cxyz58hC
 /YgzluqNI5gXqtDhEHzaR6NxTmlJZ+cPENhEAeEU+B8JLesLt9WgybJoErkazA85
 WBjAcSEBbAV6kMXYxKrlW+PY+PMNmpz7yNK3MhQ0pNAVp8otC29q266z2IYxDKtJ
 Alf5EnzFZHRbr4OZOGYX/Jc1lUOjULTpnFmqvhLJgaVNBH68ZqYZvCB3sa5NoXWs
 EBRGlI1ZksgRmlNlfmwhd051pFJhOhgk1ghEPjg6aGH7IekR9kMlvZx9WlmBJCxE
 1T5h0Qw2gAQQaOlGxZhBSecZMnZ3lFwrE8afXY3OvdlDbljr1oEdk68Tf0LhsgyY
 yyEKI5CVE8zbjVVejNa8SnTVIVCzNlqOY9xwSqGDFVKYvHSeBTY=
 =CgkA
 -----END PGP SIGNATURE-----

Merge tag 'cxl-fixes-6.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl

Pull cxl fixes from Dave Jiang:
 "The fixes address global persistent flush (GPF) changes and CXL
  Features support changes that went in the 6.15 merge window. And also
  a fix to an issue observed on CXL 1.1 platform during device
  enumeration.

  Summary:

   - Fix using the wrong GPF DVSEC location:
       - Fix caching of dport GPF DVSEC from the first endpoint
       - Ensure that the GPF phase timeout is only updated once by first
         endpoint
       - Drop is_port parameter for cxl_gpf_get_dvsec()

   - Fix the devm_* call host device for CXL fwctl setup

   - Set the out_len in Set Features failure case

   - Fix RCD initialization by skipping unneeded mem_en check"

* tag 'cxl-fixes-6.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl:
  cxl/core/regs.c: Skip Memory Space Enable check for RCD and RCH Ports
  cxl/feature: Update out_len in set feature failure case
  cxl: Fix devm host device for CXL fwctl initialization
  cxl/pci: Drop the parameter is_port of cxl_gpf_get_dvsec()
  cxl/pci: Update Port GPF timeout only when the first EP attaching
  cxl/core: Fix caching dport GPF DVSEC issue
This commit is contained in:
Linus Torvalds 2025-04-25 15:21:11 -07:00
commit 4017040ad7
10 changed files with 31 additions and 30 deletions

View File

@ -119,7 +119,7 @@ int cxl_port_get_switch_dport_bandwidth(struct cxl_port *port,
int cxl_ras_init(void);
void cxl_ras_exit(void);
int cxl_gpf_port_setup(struct device *dport_dev, struct cxl_port *port);
int cxl_gpf_port_setup(struct cxl_dport *dport);
int cxl_acpi_get_extended_linear_cache_size(struct resource *backing_res,
int nid, resource_size_t *size);

View File

@ -528,13 +528,13 @@ static void *cxlctl_set_feature(struct cxl_features_state *cxlfs,
rc = cxl_set_feature(cxl_mbox, &feat_in->uuid,
feat_in->version, feat_in->feat_data,
data_size, flags, offset, &return_code);
*out_len = sizeof(*rpc_out);
if (rc) {
rpc_out->retval = return_code;
return no_free_ptr(rpc_out);
}
rpc_out->retval = CXL_MBOX_CMD_RC_SUCCESS;
*out_len = sizeof(*rpc_out);
return no_free_ptr(rpc_out);
}
@ -677,7 +677,7 @@ static void free_memdev_fwctl(void *_fwctl_dev)
fwctl_put(fwctl_dev);
}
int devm_cxl_setup_fwctl(struct cxl_memdev *cxlmd)
int devm_cxl_setup_fwctl(struct device *host, struct cxl_memdev *cxlmd)
{
struct cxl_dev_state *cxlds = cxlmd->cxlds;
struct cxl_features_state *cxlfs;
@ -700,7 +700,7 @@ int devm_cxl_setup_fwctl(struct cxl_memdev *cxlmd)
if (rc)
return rc;
return devm_add_action_or_reset(&cxlmd->dev, free_memdev_fwctl,
return devm_add_action_or_reset(host, free_memdev_fwctl,
no_free_ptr(fwctl_dev));
}
EXPORT_SYMBOL_NS_GPL(devm_cxl_setup_fwctl, "CXL");

View File

@ -1072,14 +1072,20 @@ int cxl_pci_get_bandwidth(struct pci_dev *pdev, struct access_coordinate *c)
#define GPF_TIMEOUT_BASE_MAX 2
#define GPF_TIMEOUT_SCALE_MAX 7 /* 10 seconds */
u16 cxl_gpf_get_dvsec(struct device *dev, bool is_port)
u16 cxl_gpf_get_dvsec(struct device *dev)
{
struct pci_dev *pdev;
bool is_port = true;
u16 dvsec;
if (!dev_is_pci(dev))
return 0;
dvsec = pci_find_dvsec_capability(to_pci_dev(dev), PCI_VENDOR_ID_CXL,
pdev = to_pci_dev(dev);
if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ENDPOINT)
is_port = false;
dvsec = pci_find_dvsec_capability(pdev, PCI_VENDOR_ID_CXL,
is_port ? CXL_DVSEC_PORT_GPF : CXL_DVSEC_DEVICE_GPF);
if (!dvsec)
dev_warn(dev, "%s GPF DVSEC not present\n",
@ -1128,26 +1134,24 @@ static int update_gpf_port_dvsec(struct pci_dev *pdev, int dvsec, int phase)
return rc;
}
int cxl_gpf_port_setup(struct device *dport_dev, struct cxl_port *port)
int cxl_gpf_port_setup(struct cxl_dport *dport)
{
struct pci_dev *pdev;
if (!port)
if (!dport)
return -EINVAL;
if (!port->gpf_dvsec) {
if (!dport->gpf_dvsec) {
struct pci_dev *pdev;
int dvsec;
dvsec = cxl_gpf_get_dvsec(dport_dev, true);
dvsec = cxl_gpf_get_dvsec(dport->dport_dev);
if (!dvsec)
return -EINVAL;
port->gpf_dvsec = dvsec;
dport->gpf_dvsec = dvsec;
pdev = to_pci_dev(dport->dport_dev);
update_gpf_port_dvsec(pdev, dport->gpf_dvsec, 1);
update_gpf_port_dvsec(pdev, dport->gpf_dvsec, 2);
}
pdev = to_pci_dev(dport_dev);
update_gpf_port_dvsec(pdev, port->gpf_dvsec, 1);
update_gpf_port_dvsec(pdev, port->gpf_dvsec, 2);
return 0;
}

View File

@ -1678,7 +1678,7 @@ int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd)
if (rc && rc != -EBUSY)
return rc;
cxl_gpf_port_setup(dport_dev, port);
cxl_gpf_port_setup(dport);
/* Any more ports to add between this one and the root? */
if (!dev_is_cxl_root_child(&port->dev))

View File

@ -581,7 +581,6 @@ resource_size_t __rcrb_to_component(struct device *dev, struct cxl_rcrb_info *ri
resource_size_t rcrb = ri->base;
void __iomem *addr;
u32 bar0, bar1;
u16 cmd;
u32 id;
if (which == CXL_RCRB_UPSTREAM)
@ -603,7 +602,6 @@ resource_size_t __rcrb_to_component(struct device *dev, struct cxl_rcrb_info *ri
}
id = readl(addr + PCI_VENDOR_ID);
cmd = readw(addr + PCI_COMMAND);
bar0 = readl(addr + PCI_BASE_ADDRESS_0);
bar1 = readl(addr + PCI_BASE_ADDRESS_1);
iounmap(addr);
@ -618,8 +616,6 @@ resource_size_t __rcrb_to_component(struct device *dev, struct cxl_rcrb_info *ri
dev_err(dev, "Failed to access Downstream Port RCRB\n");
return CXL_RESOURCE_NONE;
}
if (!(cmd & PCI_COMMAND_MEMORY))
return CXL_RESOURCE_NONE;
/* The RCRB is a Memory Window, and the MEM_TYPE_1M bit is obsolete */
if (bar0 & (PCI_BASE_ADDRESS_MEM_TYPE_1M | PCI_BASE_ADDRESS_SPACE_IO))
return CXL_RESOURCE_NONE;

View File

@ -592,7 +592,6 @@ struct cxl_dax_region {
* @cdat: Cached CDAT data
* @cdat_available: Should a CDAT attribute be available in sysfs
* @pci_latency: Upstream latency in picoseconds
* @gpf_dvsec: Cached GPF port DVSEC
*/
struct cxl_port {
struct device dev;
@ -616,7 +615,6 @@ struct cxl_port {
} cdat;
bool cdat_available;
long pci_latency;
int gpf_dvsec;
};
/**
@ -664,6 +662,7 @@ struct cxl_rcrb_info {
* @regs: Dport parsed register blocks
* @coord: access coordinates (bandwidth and latency performance attributes)
* @link_latency: calculated PCIe downstream latency
* @gpf_dvsec: Cached GPF port DVSEC
*/
struct cxl_dport {
struct device *dport_dev;
@ -675,6 +674,7 @@ struct cxl_dport {
struct cxl_regs regs;
struct access_coordinate coord[ACCESS_COORDINATE_MAX];
long link_latency;
int gpf_dvsec;
};
/**
@ -910,6 +910,6 @@ bool cxl_endpoint_decoder_reset_detected(struct cxl_port *port);
#define __mock static
#endif
u16 cxl_gpf_get_dvsec(struct device *dev, bool is_port);
u16 cxl_gpf_get_dvsec(struct device *dev);
#endif /* __CXL_H__ */

View File

@ -1018,7 +1018,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
return rc;
rc = devm_cxl_setup_fwctl(cxlmd);
rc = devm_cxl_setup_fwctl(&pdev->dev, cxlmd);
if (rc)
dev_dbg(&pdev->dev, "No CXL FWCTL setup\n");

View File

@ -108,7 +108,7 @@ static void cxl_nvdimm_arm_dirty_shutdown_tracking(struct cxl_nvdimm *cxl_nvd)
return;
}
if (!cxl_gpf_get_dvsec(cxlds->dev, false))
if (!cxl_gpf_get_dvsec(cxlds->dev))
return;
if (cxl_get_dirty_count(mds, &count)) {

View File

@ -66,7 +66,7 @@ struct cxl_memdev;
#ifdef CONFIG_CXL_FEATURES
inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds);
int devm_cxl_setup_features(struct cxl_dev_state *cxlds);
int devm_cxl_setup_fwctl(struct cxl_memdev *cxlmd);
int devm_cxl_setup_fwctl(struct device *host, struct cxl_memdev *cxlmd);
#else
static inline struct cxl_features_state *to_cxlfs(struct cxl_dev_state *cxlds)
{
@ -78,7 +78,8 @@ static inline int devm_cxl_setup_features(struct cxl_dev_state *cxlds)
return -EOPNOTSUPP;
}
static inline int devm_cxl_setup_fwctl(struct cxl_memdev *cxlmd)
static inline int devm_cxl_setup_fwctl(struct device *host,
struct cxl_memdev *cxlmd)
{
return -EOPNOTSUPP;
}

View File

@ -1780,7 +1780,7 @@ static int cxl_mock_mem_probe(struct platform_device *pdev)
if (rc)
return rc;
rc = devm_cxl_setup_fwctl(cxlmd);
rc = devm_cxl_setup_fwctl(&pdev->dev, cxlmd);
if (rc)
dev_dbg(dev, "No CXL FWCTL setup\n");