mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
PCI/CXL: Add 'cxl_bus' reset method for devices below CXL Ports
By default Secondary Bus Reset (SBR) is masked for CXL Ports (see CXL r3.1, sec 8.1.5.2). Add cxl_reset_bus_function() (method "cxl_bus") to set the "Unmask SBR" bit in the upstream CXL Port before performing the bus reset and restore the original value afterwards. This method allows the user to perform a bus reset on a CXL device without needing to set the "Unmask SBR" bit via a user tool. Link: https://lore.kernel.org/r/20240502165851.1948523-5-dave.jiang@intel.com Signed-off-by: Dave Jiang <dave.jiang@intel.com> [bhelgaas: simplify commit log, invert condition to avoid negation] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
parent
b1956e2d07
commit
53c49b6e6d
@ -4980,6 +4980,44 @@ static int pci_reset_bus_function(struct pci_dev *dev, bool probe)
|
||||
return pci_parent_bus_reset(dev, probe);
|
||||
}
|
||||
|
||||
static int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
|
||||
{
|
||||
struct pci_dev *bridge;
|
||||
u16 dvsec, reg, val;
|
||||
int rc;
|
||||
|
||||
bridge = pci_upstream_bridge(dev);
|
||||
if (!bridge)
|
||||
return -ENOTTY;
|
||||
|
||||
dvsec = cxl_port_dvsec(bridge);
|
||||
if (!dvsec)
|
||||
return -ENOTTY;
|
||||
|
||||
if (probe)
|
||||
return 0;
|
||||
|
||||
rc = pci_read_config_word(bridge, dvsec + PCI_DVSEC_CXL_PORT_CTL, ®);
|
||||
if (rc)
|
||||
return -ENOTTY;
|
||||
|
||||
if (reg & PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR) {
|
||||
val = reg;
|
||||
} else {
|
||||
val = reg | PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR;
|
||||
pci_write_config_word(bridge, dvsec + PCI_DVSEC_CXL_PORT_CTL,
|
||||
val);
|
||||
}
|
||||
|
||||
rc = pci_reset_bus_function(dev, probe);
|
||||
|
||||
if (reg != val)
|
||||
pci_write_config_word(bridge, dvsec + PCI_DVSEC_CXL_PORT_CTL,
|
||||
reg);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void pci_dev_lock(struct pci_dev *dev)
|
||||
{
|
||||
/* block PM suspend, driver probe, etc. */
|
||||
@ -5064,6 +5102,7 @@ static const struct pci_reset_fn_method pci_reset_fn_methods[] = {
|
||||
{ pci_af_flr, .name = "af_flr" },
|
||||
{ pci_pm_reset, .name = "pm" },
|
||||
{ pci_reset_bus_function, .name = "bus" },
|
||||
{ cxl_reset_bus_function, .name = "cxl_bus" },
|
||||
};
|
||||
|
||||
static ssize_t reset_method_show(struct device *dev,
|
||||
|
@ -51,7 +51,7 @@
|
||||
PCI_STATUS_PARITY)
|
||||
|
||||
/* Number of reset methods used in pci_reset_fn_methods array in pci.c */
|
||||
#define PCI_NUM_RESET_METHODS 7
|
||||
#define PCI_NUM_RESET_METHODS 8
|
||||
|
||||
#define PCI_RESET_PROBE true
|
||||
#define PCI_RESET_DO_RESET false
|
||||
|
Loading…
Reference in New Issue
Block a user