Merge branches 'pci/enumeration' and 'pci/misc' into next
* pci/enumeration: PCI: Set MPS to match upstream bridge PCI: Move MPS configuration check to pci_configure_device() PCI: Drop references acquired by of_parse_phandle() PCI/MSI: Remove unused pcibios_msi_controller() hook ARM/PCI: Remove msi_controller from struct pci_sys_data ARM/PCI, designware, xilinx: Use pci_scan_root_bus_msi() PCI: Add pci_scan_root_bus_msi() ARM/PCI: Replace panic with WARN messages on failures PCI: generic: Add arm64 support PCI: Build setup-irq.o for arm64 PCI: generic: Remove dependency on ARM-specific struct hw_pci ARM/PCI: Set MPS before pci_bus_add_devices() * pci/misc: PCI: Disable async suspend/resume for JMicron multi-function SATA/AHCI
This commit is contained in:
@@ -33,6 +33,7 @@ obj-$(CONFIG_PCI_IOV) += iov.o
|
||||
#
|
||||
obj-$(CONFIG_ALPHA) += setup-irq.o
|
||||
obj-$(CONFIG_ARM) += setup-irq.o
|
||||
obj-$(CONFIG_ARM64) += setup-irq.o
|
||||
obj-$(CONFIG_UNICORE32) += setup-irq.o
|
||||
obj-$(CONFIG_SUPERH) += setup-irq.o
|
||||
obj-$(CONFIG_MIPS) += setup-irq.o
|
||||
|
@@ -53,7 +53,7 @@ config PCI_RCAR_GEN2_PCIE
|
||||
|
||||
config PCI_HOST_GENERIC
|
||||
bool "Generic PCI host controller"
|
||||
depends on ARM && OF
|
||||
depends on (ARM || ARM64) && OF
|
||||
help
|
||||
Say Y here if you want to support a simple generic PCI host
|
||||
controller, such as the one emulated by kvmtool.
|
||||
|
@@ -38,7 +38,16 @@ struct gen_pci_cfg_windows {
|
||||
const struct gen_pci_cfg_bus_ops *ops;
|
||||
};
|
||||
|
||||
/*
|
||||
* ARM pcibios functions expect the ARM struct pci_sys_data as the PCI
|
||||
* sysdata. Add pci_sys_data as the first element in struct gen_pci so
|
||||
* that when we use a gen_pci pointer as sysdata, it is also a pointer to
|
||||
* a struct pci_sys_data.
|
||||
*/
|
||||
struct gen_pci {
|
||||
#ifdef CONFIG_ARM
|
||||
struct pci_sys_data sys;
|
||||
#endif
|
||||
struct pci_host_bridge host;
|
||||
struct gen_pci_cfg_windows cfg;
|
||||
struct list_head resources;
|
||||
@@ -48,8 +57,7 @@ static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus,
|
||||
unsigned int devfn,
|
||||
int where)
|
||||
{
|
||||
struct pci_sys_data *sys = bus->sysdata;
|
||||
struct gen_pci *pci = sys->private_data;
|
||||
struct gen_pci *pci = bus->sysdata;
|
||||
resource_size_t idx = bus->number - pci->cfg.bus_range->start;
|
||||
|
||||
return pci->cfg.win[idx] + ((devfn << 8) | where);
|
||||
@@ -64,8 +72,7 @@ static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus,
|
||||
unsigned int devfn,
|
||||
int where)
|
||||
{
|
||||
struct pci_sys_data *sys = bus->sysdata;
|
||||
struct gen_pci *pci = sys->private_data;
|
||||
struct gen_pci *pci = bus->sysdata;
|
||||
resource_size_t idx = bus->number - pci->cfg.bus_range->start;
|
||||
|
||||
return pci->cfg.win[idx] + ((devfn << 12) | where);
|
||||
@@ -198,13 +205,6 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gen_pci_setup(int nr, struct pci_sys_data *sys)
|
||||
{
|
||||
struct gen_pci *pci = sys->private_data;
|
||||
list_splice_init(&pci->resources, &sys->resources);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gen_pci_probe(struct platform_device *pdev)
|
||||
{
|
||||
int err;
|
||||
@@ -214,13 +214,7 @@ static int gen_pci_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
|
||||
struct hw_pci hw = {
|
||||
.nr_controllers = 1,
|
||||
.private_data = (void **)&pci,
|
||||
.setup = gen_pci_setup,
|
||||
.map_irq = of_irq_parse_and_map_pci,
|
||||
.ops = &gen_pci_ops,
|
||||
};
|
||||
struct pci_bus *bus, *child;
|
||||
|
||||
if (!pci)
|
||||
return -ENOMEM;
|
||||
@@ -258,7 +252,27 @@ static int gen_pci_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
pci_common_init_dev(dev, &hw);
|
||||
/* Do not reassign resources if probe only */
|
||||
if (!pci_has_flag(PCI_PROBE_ONLY))
|
||||
pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
|
||||
|
||||
bus = pci_scan_root_bus(dev, 0, &gen_pci_ops, pci, &pci->resources);
|
||||
if (!bus) {
|
||||
dev_err(dev, "Scanning rootbus failed");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
|
||||
|
||||
if (!pci_has_flag(PCI_PROBE_ONLY)) {
|
||||
pci_bus_size_bridges(bus);
|
||||
pci_bus_assign_resources(bus);
|
||||
|
||||
list_for_each_entry(child, &bus->children, node)
|
||||
pcie_bus_configure_settings(child);
|
||||
}
|
||||
|
||||
pci_bus_add_devices(bus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -879,6 +879,7 @@ static void mvebu_pcie_msi_enable(struct mvebu_pcie *pcie)
|
||||
return;
|
||||
|
||||
pcie->msi = of_pci_find_msi_chip_by_node(msi_node);
|
||||
of_node_put(msi_node);
|
||||
|
||||
if (pcie->msi)
|
||||
pcie->msi->dev = &pcie->pdev->dev;
|
||||
|
@@ -522,6 +522,7 @@ static int xgene_pcie_msi_enable(struct pci_bus *bus)
|
||||
if (!bus->msi)
|
||||
return -ENODEV;
|
||||
|
||||
of_node_put(msi_node);
|
||||
bus->msi->dev = &bus->dev;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -525,7 +525,6 @@ int dw_pcie_host_init(struct pcie_port *pp)
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
dw_pcie_msi_chip.dev = pp->dev;
|
||||
dw_pci.msi_ctrl = &dw_pcie_msi_chip;
|
||||
#endif
|
||||
|
||||
dw_pci.nr_controllers = 1;
|
||||
@@ -707,8 +706,15 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
|
||||
struct pcie_port *pp = sys_to_pcie(sys);
|
||||
|
||||
pp->root_bus_nr = sys->busnr;
|
||||
bus = pci_scan_root_bus(pp->dev, sys->busnr,
|
||||
&dw_pcie_ops, sys, &sys->resources);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI))
|
||||
bus = pci_scan_root_bus_msi(pp->dev, sys->busnr, &dw_pcie_ops,
|
||||
sys, &sys->resources,
|
||||
&dw_pcie_msi_chip);
|
||||
else
|
||||
bus = pci_scan_root_bus(pp->dev, sys->busnr, &dw_pcie_ops,
|
||||
sys, &sys->resources);
|
||||
|
||||
if (!bus)
|
||||
return NULL;
|
||||
|
||||
|
@@ -648,9 +648,15 @@ static struct pci_bus *xilinx_pcie_scan_bus(int nr, struct pci_sys_data *sys)
|
||||
struct pci_bus *bus;
|
||||
|
||||
port->root_busno = sys->busnr;
|
||||
bus = pci_scan_root_bus(port->dev, sys->busnr, &xilinx_pcie_ops,
|
||||
sys, &sys->resources);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI))
|
||||
bus = pci_scan_root_bus_msi(port->dev, sys->busnr,
|
||||
&xilinx_pcie_ops, sys,
|
||||
&sys->resources,
|
||||
&xilinx_pcie_msi_chip);
|
||||
else
|
||||
bus = pci_scan_root_bus(port->dev, sys->busnr,
|
||||
&xilinx_pcie_ops, sys, &sys->resources);
|
||||
return bus;
|
||||
}
|
||||
|
||||
@@ -848,7 +854,6 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
xilinx_pcie_msi_chip.dev = port->dev;
|
||||
hw.msi_ctrl = &xilinx_pcie_msi_chip;
|
||||
#endif
|
||||
pci_common_init_dev(dev, &hw);
|
||||
|
||||
|
@@ -77,24 +77,9 @@ static void pci_msi_teardown_msi_irqs(struct pci_dev *dev)
|
||||
|
||||
/* Arch hooks */
|
||||
|
||||
struct msi_controller * __weak pcibios_msi_controller(struct pci_dev *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct msi_controller *pci_msi_controller(struct pci_dev *dev)
|
||||
{
|
||||
struct msi_controller *msi_ctrl = dev->bus->msi;
|
||||
|
||||
if (msi_ctrl)
|
||||
return msi_ctrl;
|
||||
|
||||
return pcibios_msi_controller(dev);
|
||||
}
|
||||
|
||||
int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
|
||||
{
|
||||
struct msi_controller *chip = pci_msi_controller(dev);
|
||||
struct msi_controller *chip = dev->bus->msi;
|
||||
int err;
|
||||
|
||||
if (!chip || !chip->setup_irq)
|
||||
|
@@ -81,7 +81,7 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
|
||||
unsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE;
|
||||
unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;
|
||||
|
||||
enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_TUNE_OFF;
|
||||
enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_DEFAULT;
|
||||
|
||||
/*
|
||||
* The default CLS is used if arch didn't set CLS explicitly and not
|
||||
|
@@ -1277,6 +1277,44 @@ int pci_setup_device(struct pci_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pci_configure_mps(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_dev *bridge = pci_upstream_bridge(dev);
|
||||
int mps, p_mps, rc;
|
||||
|
||||
if (!pci_is_pcie(dev) || !bridge || !pci_is_pcie(bridge))
|
||||
return;
|
||||
|
||||
mps = pcie_get_mps(dev);
|
||||
p_mps = pcie_get_mps(bridge);
|
||||
|
||||
if (mps == p_mps)
|
||||
return;
|
||||
|
||||
if (pcie_bus_config == PCIE_BUS_TUNE_OFF) {
|
||||
dev_warn(&dev->dev, "Max Payload Size %d, but upstream %s set to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n",
|
||||
mps, pci_name(bridge), p_mps);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fancier MPS configuration is done later by
|
||||
* pcie_bus_configure_settings()
|
||||
*/
|
||||
if (pcie_bus_config != PCIE_BUS_DEFAULT)
|
||||
return;
|
||||
|
||||
rc = pcie_set_mps(dev, p_mps);
|
||||
if (rc) {
|
||||
dev_warn(&dev->dev, "can't set Max Payload Size to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n",
|
||||
p_mps);
|
||||
return;
|
||||
}
|
||||
|
||||
dev_info(&dev->dev, "Max Payload Size set to %d (was %d, max %d)\n",
|
||||
p_mps, mps, 128 << dev->pcie_mpss);
|
||||
}
|
||||
|
||||
static struct hpp_type0 pci_default_type0 = {
|
||||
.revision = 1,
|
||||
.cache_line_size = 8,
|
||||
@@ -1398,6 +1436,8 @@ static void pci_configure_device(struct pci_dev *dev)
|
||||
struct hotplug_params hpp;
|
||||
int ret;
|
||||
|
||||
pci_configure_mps(dev);
|
||||
|
||||
memset(&hpp, 0, sizeof(hpp));
|
||||
ret = pci_get_hp_params(dev, &hpp);
|
||||
if (ret)
|
||||
@@ -1796,22 +1836,6 @@ static void pcie_write_mrrs(struct pci_dev *dev)
|
||||
dev_err(&dev->dev, "MRRS was unable to be configured with a safe value. If problems are experienced, try running with pci=pcie_bus_safe\n");
|
||||
}
|
||||
|
||||
static void pcie_bus_detect_mps(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_dev *bridge = dev->bus->self;
|
||||
int mps, p_mps;
|
||||
|
||||
if (!bridge)
|
||||
return;
|
||||
|
||||
mps = pcie_get_mps(dev);
|
||||
p_mps = pcie_get_mps(bridge);
|
||||
|
||||
if (mps != p_mps)
|
||||
dev_warn(&dev->dev, "Max Payload Size %d, but upstream %s set to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n",
|
||||
mps, pci_name(bridge), p_mps);
|
||||
}
|
||||
|
||||
static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
|
||||
{
|
||||
int mps, orig_mps;
|
||||
@@ -1819,10 +1843,9 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
|
||||
if (!pci_is_pcie(dev))
|
||||
return 0;
|
||||
|
||||
if (pcie_bus_config == PCIE_BUS_TUNE_OFF) {
|
||||
pcie_bus_detect_mps(dev);
|
||||
if (pcie_bus_config == PCIE_BUS_TUNE_OFF ||
|
||||
pcie_bus_config == PCIE_BUS_DEFAULT)
|
||||
return 0;
|
||||
}
|
||||
|
||||
mps = 128 << *(u8 *)data;
|
||||
orig_mps = pcie_get_mps(dev);
|
||||
@@ -2101,8 +2124,9 @@ void pci_bus_release_busn_res(struct pci_bus *b)
|
||||
res, ret ? "can not be" : "is");
|
||||
}
|
||||
|
||||
struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
|
||||
struct pci_ops *ops, void *sysdata, struct list_head *resources)
|
||||
struct pci_bus *pci_scan_root_bus_msi(struct device *parent, int bus,
|
||||
struct pci_ops *ops, void *sysdata,
|
||||
struct list_head *resources, struct msi_controller *msi)
|
||||
{
|
||||
struct resource_entry *window;
|
||||
bool found = false;
|
||||
@@ -2119,6 +2143,8 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
|
||||
if (!b)
|
||||
return NULL;
|
||||
|
||||
b->msi = msi;
|
||||
|
||||
if (!found) {
|
||||
dev_info(&b->dev,
|
||||
"No busn resource found for root bus, will use [bus %02x-ff]\n",
|
||||
@@ -2133,6 +2159,13 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
|
||||
struct pci_ops *ops, void *sysdata, struct list_head *resources)
|
||||
{
|
||||
return pci_scan_root_bus_msi(parent, bus, ops, sysdata, resources,
|
||||
NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_scan_root_bus);
|
||||
|
||||
struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops,
|
||||
|
@@ -1570,6 +1570,18 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB3
|
||||
|
||||
#endif
|
||||
|
||||
static void quirk_jmicron_async_suspend(struct pci_dev *dev)
|
||||
{
|
||||
if (dev->multifunction) {
|
||||
device_disable_async_suspend(&dev->dev);
|
||||
dev_info(&dev->dev, "async suspend disabled to avoid multi-function power-on ordering issue\n");
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE, 8, quirk_jmicron_async_suspend);
|
||||
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0, quirk_jmicron_async_suspend);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_JMICRON, 0x2362, quirk_jmicron_async_suspend);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_JMICRON, 0x236f, quirk_jmicron_async_suspend);
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
static void quirk_alder_ioapic(struct pci_dev *pdev)
|
||||
{
|
||||
@@ -2879,7 +2891,8 @@ static void quirk_intel_mc_errata(struct pci_dev *dev)
|
||||
int err;
|
||||
u16 rcc;
|
||||
|
||||
if (pcie_bus_config == PCIE_BUS_TUNE_OFF)
|
||||
if (pcie_bus_config == PCIE_BUS_TUNE_OFF ||
|
||||
pcie_bus_config == PCIE_BUS_DEFAULT)
|
||||
return;
|
||||
|
||||
/* Intel errata specifies bits to change but does not say what they are.
|
||||
|
Reference in New Issue
Block a user