Merge branch 'pci/controller/dwc'

- Apply ECRC TLP Digest workaround for all DesignWare cores prior to 5.10a,
  not just 4.90a and 5.00a (Manikanta Maddireddy)

- Use common struct dw_pcie 'mode' rather than duplicating it in artpec6,
  dra7xx, dwc-pcie, and keembay driver structs (Hans Zhang)

- Use DEFINE_SHOW_ATTRIBUTE for ltssm_status debugfs to reduce boilerplate
  and fix a seq_file memory leak by including a .release() callback (Hans
  Zhang)

- Fix a signedness bug in fault injection test code (Dan Carpenter)

- Avoid NULL pointer dereference when tearing down debugfs for controller
  that lacks RAS DES capability (Shuvam Pandey)

* pci/controller/dwc:
  PCI: dwc: Avoid dwc_pcie_rasdes_debugfs_deinit() NULL dereference when no RAS DES capability
  PCI: dwc: Fix signedness bug in fault injection test code
  PCI: dwc: Use DEFINE_SHOW_ATTRIBUTE for ltssm_status debugfs
  PCI: keembay: Use common mode field in struct dw_pcie
  PCI: dwc: Use common mode field in struct dw_pcie
  PCI: artpec6: Use common mode field in struct dw_pcie
  PCI: dra7xx: Use common mode field in struct dw_pcie
  PCI: dwc: Apply ECRC workaround for DesignWare cores prior to 5.10a
This commit is contained in:
Bjorn Helgaas
2026-06-23 17:32:05 -05:00
7 changed files with 34 additions and 41 deletions

View File

@@ -92,7 +92,6 @@ struct dra7xx_pcie {
struct phy **phy;
struct irq_domain *irq_domain;
struct clk *clk;
enum dw_pcie_device_mode mode;
};
struct dra7xx_pcie_of_data {
@@ -328,7 +327,7 @@ static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg)
dev_dbg(dev, "Link Request Reset\n");
if (reg & LINK_UP_EVT) {
if (dra7xx->mode == DW_PCIE_EP_TYPE)
if (dra7xx->pci->mode == DW_PCIE_EP_TYPE)
dw_pcie_ep_linkup(ep);
dev_dbg(dev, "Link-up state change\n");
}
@@ -828,7 +827,7 @@ static int dra7xx_pcie_probe(struct platform_device *pdev)
default:
dev_err(dev, "INVALID device type %d\n", mode);
}
dra7xx->mode = mode;
dra7xx->pci->mode = mode;
ret = devm_request_threaded_irq(dev, irq, NULL, dra7xx_pcie_irq_handler,
IRQF_SHARED | IRQF_ONESHOT,
@@ -841,7 +840,7 @@ static int dra7xx_pcie_probe(struct platform_device *pdev)
return 0;
err_deinit:
if (dra7xx->mode == DW_PCIE_RC_TYPE)
if (dra7xx->pci->mode == DW_PCIE_RC_TYPE)
dw_pcie_host_deinit(&dra7xx->pci->pp);
else
dw_pcie_ep_deinit(&dra7xx->pci->ep);
@@ -865,7 +864,7 @@ static int dra7xx_pcie_suspend(struct device *dev)
struct dw_pcie *pci = dra7xx->pci;
u32 val;
if (dra7xx->mode != DW_PCIE_RC_TYPE)
if (pci->mode != DW_PCIE_RC_TYPE)
return 0;
/* clear MSE */
@@ -882,7 +881,7 @@ static int dra7xx_pcie_resume(struct device *dev)
struct dw_pcie *pci = dra7xx->pci;
u32 val;
if (dra7xx->mode != DW_PCIE_RC_TYPE)
if (pci->mode != DW_PCIE_RC_TYPE)
return 0;
/* set MSE */

View File

@@ -34,7 +34,6 @@ struct artpec6_pcie {
struct regmap *regmap; /* DT axis,syscon-pcie */
void __iomem *phy_base; /* DT phy */
enum artpec_pcie_variants variant;
enum dw_pcie_device_mode mode;
};
struct artpec_pcie_of_data {
@@ -100,7 +99,7 @@ static u64 artpec6_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 cpu_addr)
struct dw_pcie_rp *pp = &pci->pp;
struct dw_pcie_ep *ep = &pci->ep;
switch (artpec6_pcie->mode) {
switch (artpec6_pcie->pci->mode) {
case DW_PCIE_RC_TYPE:
return cpu_addr - pp->cfg0_base;
case DW_PCIE_EP_TYPE:
@@ -413,7 +412,7 @@ static int artpec6_pcie_probe(struct platform_device *pdev)
artpec6_pcie->pci = pci;
artpec6_pcie->variant = variant;
artpec6_pcie->mode = mode;
artpec6_pcie->pci->mode = mode;
artpec6_pcie->phy_base =
devm_platform_ioremap_resource_byname(pdev, "phy");
@@ -428,7 +427,7 @@ static int artpec6_pcie_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, artpec6_pcie);
switch (artpec6_pcie->mode) {
switch (artpec6_pcie->pci->mode) {
case DW_PCIE_RC_TYPE:
if (!IS_ENABLED(CONFIG_PCIE_ARTPEC6_HOST))
return -ENODEV;
@@ -464,7 +463,7 @@ static int artpec6_pcie_probe(struct platform_device *pdev)
break;
default:
dev_err(dev, "INVALID device type %d\n", artpec6_pcie->mode);
dev_err(dev, "INVALID device type %d\n", artpec6_pcie->pci->mode);
}
return 0;

View File

@@ -306,6 +306,7 @@ static ssize_t err_inj_write(struct file *file, const char __user *buf,
u32 val, counter, vc_num, err_group, type_mask;
int val_diff = 0;
char *kern_buf;
int ret;
err_group = err_inj_list[pdata->idx].err_inj_group;
type_mask = err_inj_type_mask[err_group];
@@ -327,10 +328,10 @@ static ssize_t err_inj_write(struct file *file, const char __user *buf,
return -EINVAL;
}
} else {
val = kstrtou32(kern_buf, 0, &counter);
if (val) {
ret = kstrtou32(kern_buf, 0, &counter);
if (ret) {
kfree(kern_buf);
return val;
return ret;
}
}
@@ -507,11 +508,6 @@ static int ltssm_status_show(struct seq_file *s, void *v)
return 0;
}
static int ltssm_status_open(struct inode *inode, struct file *file)
{
return single_open(file, ltssm_status_show, inode->i_private);
}
#define dwc_debugfs_create(name) \
debugfs_create_file(#name, 0644, rasdes_debug, pci, \
&dbg_ ## name ## _fops)
@@ -548,15 +544,15 @@ static const struct file_operations dwc_pcie_counter_value_ops = {
.read = counter_value_read,
};
static const struct file_operations dwc_pcie_ltssm_status_ops = {
.open = ltssm_status_open,
.read = seq_read,
};
DEFINE_SHOW_ATTRIBUTE(ltssm_status);
static void dwc_pcie_rasdes_debugfs_deinit(struct dw_pcie *pci)
{
struct dwc_pcie_rasdes_info *rinfo = pci->debugfs->rasdes_info;
if (!rinfo)
return;
mutex_destroy(&rinfo->reg_event_lock);
}
@@ -642,7 +638,7 @@ static int dwc_pcie_rasdes_debugfs_init(struct dw_pcie *pci, struct dentry *dir)
static void dwc_pcie_ltssm_debugfs_init(struct dw_pcie *pci, struct dentry *dir)
{
debugfs_create_file("ltssm_status", 0444, dir, pci,
&dwc_pcie_ltssm_status_ops);
&ltssm_status_fops);
}
static int dw_pcie_ptm_check_capability(void *drvdata)

View File

@@ -22,7 +22,6 @@
struct dw_plat_pcie {
struct dw_pcie *pci;
enum dw_pcie_device_mode mode;
};
struct dw_plat_pcie_of_data {
@@ -118,11 +117,11 @@ static int dw_plat_pcie_probe(struct platform_device *pdev)
pci->dev = dev;
dw_plat_pcie->pci = pci;
dw_plat_pcie->mode = mode;
dw_plat_pcie->pci->mode = mode;
platform_set_drvdata(pdev, dw_plat_pcie);
switch (dw_plat_pcie->mode) {
switch (dw_plat_pcie->pci->mode) {
case DW_PCIE_RC_TYPE:
if (!IS_ENABLED(CONFIG_PCIE_DW_PLAT_HOST))
return -ENODEV;
@@ -148,7 +147,7 @@ static int dw_plat_pcie_probe(struct platform_device *pdev)
break;
default:
dev_err(dev, "INVALID device type %d\n", dw_plat_pcie->mode);
dev_err(dev, "INVALID device type %d\n", dw_plat_pcie->pci->mode);
ret = -EINVAL;
break;
}

View File

@@ -491,13 +491,13 @@ static inline void dw_pcie_writel_atu_ob(struct dw_pcie *pci, u32 index, u32 reg
static inline u32 dw_pcie_enable_ecrc(u32 val)
{
/*
* DWC versions 0x3530302a and 0x3536322a have a design issue where
* the 'TD' bit in the Control register-1 of the ATU outbound
* region acts like an override for the ECRC setting, i.e., the
* presence of TLP Digest (ECRC) in the outgoing TLPs is solely
* determined by this bit. This is contrary to the PCIe spec which
* says that the enablement of the ECRC is solely determined by the
* AER registers.
* DesignWare core versions prior to 5.10A have a design issue where the
* 'TD' bit in the Control register-1 of the ATU outbound region acts
* like an override for the ECRC setting, i.e., the presence of TLP
* Digest (ECRC) in the outgoing TLPs is solely determined by this
* bit. This is contrary to the PCIe spec which says that the
* enablement of the ECRC is solely determined by the AER
* registers.
*
* Because of this, even when the ECRC is enabled through AER
* registers, the transactions going through ATU won't have TLP
@@ -567,7 +567,7 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
if (upper_32_bits(limit_addr) > upper_32_bits(parent_bus_addr) &&
dw_pcie_ver_is_ge(pci, 460A))
val |= PCIE_ATU_INCREASE_REGION_SIZE;
if (dw_pcie_ver_is(pci, 490A) || dw_pcie_ver_is(pci, 500A))
if (!dw_pcie_ver_is_ge(pci, 510A))
val = dw_pcie_enable_ecrc(val);
dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_REGION_CTRL1, val);

View File

@@ -35,6 +35,7 @@
#define DW_PCIE_VER_480A 0x3438302a
#define DW_PCIE_VER_490A 0x3439302a
#define DW_PCIE_VER_500A 0x3530302a
#define DW_PCIE_VER_510A 0x3531302a
#define DW_PCIE_VER_520A 0x3532302a
#define DW_PCIE_VER_540A 0x3534302a
#define DW_PCIE_VER_562A 0x3536322a

View File

@@ -58,7 +58,6 @@
struct keembay_pcie {
struct dw_pcie pci;
void __iomem *apb_base;
enum dw_pcie_device_mode mode;
struct clk *clk_master;
struct clk *clk_aux;
@@ -117,7 +116,7 @@ static int keembay_pcie_start_link(struct dw_pcie *pci)
u32 val;
int ret;
if (pcie->mode == DW_PCIE_EP_TYPE)
if (pcie->pci.mode == DW_PCIE_EP_TYPE)
return 0;
keembay_pcie_ltssm_set(pcie, false);
@@ -409,7 +408,7 @@ static int keembay_pcie_probe(struct platform_device *pdev)
pci->dev = dev;
pci->ops = &keembay_pcie_ops;
pcie->mode = mode;
pcie->pci.mode = mode;
pcie->apb_base = devm_platform_ioremap_resource_byname(pdev, "apb");
if (IS_ERR(pcie->apb_base))
@@ -417,7 +416,7 @@ static int keembay_pcie_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pcie);
switch (pcie->mode) {
switch (pcie->pci.mode) {
case DW_PCIE_RC_TYPE:
if (!IS_ENABLED(CONFIG_PCIE_KEEMBAY_HOST))
return -ENODEV;
@@ -443,7 +442,7 @@ static int keembay_pcie_probe(struct platform_device *pdev)
break;
default:
dev_err(dev, "Invalid device type %d\n", pcie->mode);
dev_err(dev, "Invalid device type %d\n", pcie->pci.mode);
return -ENODEV;
}