Commit 379f604c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull PCI fixes from Bjorn Helgaas:

 - Track apple Root Ports explicitly and look up the driver data from
   the struct device instead of using dev->driver_data, which is used by
   pci_host_common_init() for the generic host bridge pointer (Marc
   Zyngier)

 - Set dev->driver_data before pci_host_common_init() calls
   gen_pci_init() because some drivers need it to set up ECAM mappings;
   this fixes a regression on MicroChip MPFS Icicle (Geert Uytterhoeven)

 - Revert the now-unnecessary use of ECAM pci_config_window.priv to
   store a copy of dev->driver_data (Marc Zyngier)

* tag 'pci-v6.16-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci:
  Revert "PCI: ecam: Allow cfg->priv to be pre-populated from the root port device"
  PCI: host-generic: Set driver_data before calling gen_pci_init()
  PCI: apple: Add tracking of probed root ports
parents 3c2fe279 ba74278c
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -64,13 +64,13 @@ int pci_host_common_init(struct platform_device *pdev,

	of_pci_check_probe_only();

	platform_set_drvdata(pdev, bridge);

	/* Parse and map our Configuration Space windows */
	cfg = gen_pci_init(dev, bridge, ops);
	if (IS_ERR(cfg))
		return PTR_ERR(cfg);

	platform_set_drvdata(pdev, bridge);

	bridge->sysdata = cfg;
	bridge->ops = (struct pci_ops *)&ops->pci_ops;
	bridge->enable_device = ops->enable_device;
+49 −4
Original line number Diff line number Diff line
@@ -187,6 +187,7 @@ struct apple_pcie {
	const struct hw_info	*hw;
	unsigned long		*bitmap;
	struct list_head	ports;
	struct list_head	entry;
	struct completion	event;
	struct irq_fwspec	fwspec;
	u32			nvecs;
@@ -205,6 +206,9 @@ struct apple_pcie_port {
	int			idx;
};

static LIST_HEAD(pcie_list);
static DEFINE_MUTEX(pcie_list_lock);

static void rmw_set(u32 set, void __iomem *addr)
{
	writel_relaxed(readl_relaxed(addr) | set, addr);
@@ -720,13 +724,45 @@ static int apple_msi_init(struct apple_pcie *pcie)
	return 0;
}

static void apple_pcie_register(struct apple_pcie *pcie)
{
	guard(mutex)(&pcie_list_lock);

	list_add_tail(&pcie->entry, &pcie_list);
}

static void apple_pcie_unregister(struct apple_pcie *pcie)
{
	guard(mutex)(&pcie_list_lock);

	list_del(&pcie->entry);
}

static struct apple_pcie *apple_pcie_lookup(struct device *dev)
{
	struct apple_pcie *pcie;

	guard(mutex)(&pcie_list_lock);

	list_for_each_entry(pcie, &pcie_list, entry) {
		if (pcie->dev == dev)
			return pcie;
	}

	return NULL;
}

static struct apple_pcie_port *apple_pcie_get_port(struct pci_dev *pdev)
{
	struct pci_config_window *cfg = pdev->sysdata;
	struct apple_pcie *pcie = cfg->priv;
	struct apple_pcie *pcie;
	struct pci_dev *port_pdev;
	struct apple_pcie_port *port;

	pcie = apple_pcie_lookup(cfg->parent);
	if (WARN_ON(!pcie))
		return NULL;

	/* Find the root port this device is on */
	port_pdev = pcie_find_root_port(pdev);

@@ -806,10 +842,14 @@ static void apple_pcie_disable_device(struct pci_host_bridge *bridge, struct pci

static int apple_pcie_init(struct pci_config_window *cfg)
{
	struct apple_pcie *pcie = cfg->priv;
	struct device *dev = cfg->parent;
	struct apple_pcie *pcie;
	int ret;

	pcie = apple_pcie_lookup(dev);
	if (WARN_ON(!pcie))
		return -ENOENT;

	for_each_available_child_of_node_scoped(dev->of_node, of_port) {
		ret = apple_pcie_setup_port(pcie, of_port);
		if (ret) {
@@ -852,13 +892,18 @@ static int apple_pcie_probe(struct platform_device *pdev)

	mutex_init(&pcie->lock);
	INIT_LIST_HEAD(&pcie->ports);
	dev_set_drvdata(dev, pcie);

	ret = apple_msi_init(pcie);
	if (ret)
		return ret;

	return pci_host_common_init(pdev, &apple_pcie_cfg_ecam_ops);
	apple_pcie_register(pcie);

	ret = pci_host_common_init(pdev, &apple_pcie_cfg_ecam_ops);
	if (ret)
		apple_pcie_unregister(pcie);

	return ret;
}

static const struct of_device_id apple_pcie_of_match[] = {
+0 −2
Original line number Diff line number Diff line
@@ -84,8 +84,6 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
			goto err_exit_iomap;
	}

	cfg->priv = dev_get_drvdata(dev);

	if (ops->init) {
		err = ops->init(cfg);
		if (err)