Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 98d9f30c authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt
Browse files

pci/of: Match PCI devices to OF nodes dynamically



powerpc has two different ways of matching PCI devices to their
corresponding OF node (if any) for historical reasons. The ppc64 one
does a scan looking for matching bus/dev/fn, while the ppc32 one does a
scan looking only for matching dev/fn on each level in order to be
agnostic to busses being renumbered (which Linux does on some
platforms).

This removes both and instead moves the matching code to the PCI core
itself. It's the most logical place to do it: when a pci_dev is created,
we know the parent and thus can do a single level scan for the matching
device_node (if any).

The benefit is that all archs now get the matching for free. There's one
hook the arch might want to provide to match a PHB bus to its device
node. A default weak implementation is provided that looks for the
parent device device node, but it's not entirely reliable on powerpc for
various reasons so powerpc provides its own.

Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: default avatarMichal Simek <monstr@monstr.eu>
Acked-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 1fa7b6a2
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -105,19 +105,19 @@ struct pci_controller {
};

#ifdef CONFIG_PCI
static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
{
	return bus->sysdata;
	return dev->dev.of_node;
}

static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
{
	struct pci_controller *host;
	return bus->dev.of_node;
}

	if (bus->self)
		return pci_device_to_OF_node(bus->self);
	host = pci_bus_to_host(bus);
	return host ? host->dn : NULL;
static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
{
	return bus->sysdata;
}

static inline int isa_vaddr_is_ioport(void __iomem *address)
+0 −15
Original line number Diff line number Diff line
@@ -29,21 +29,6 @@
extern int early_uartlite_console(void);
extern int early_uart16550_console(void);

#ifdef CONFIG_PCI
/*
 * PCI <-> OF matching functions
 * (XXX should these be here?)
 */
struct pci_bus;
struct pci_dev;
extern int pci_device_from_OF_node(struct device_node *node,
					u8 *bus, u8 *devfn);
extern struct device_node *pci_busdev_to_OF_node(struct pci_bus *bus,
							int devfn);
extern struct device_node *pci_device_to_OF_node(struct pci_dev *dev);
extern void pci_create_OF_bus_map(void);
#endif

/*
 * OF address retreival & translation
 */
+7 −33
Original line number Diff line number Diff line
@@ -210,38 +210,6 @@ static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus)
	return np;
}

/*
 * Scans the OF tree for a device node matching a PCI device
 */
struct device_node *
pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
{
	struct device_node *parent, *np;

	pr_debug("pci_busdev_to_OF_node(%d,0x%x)\n", bus->number, devfn);
	parent = scan_OF_for_pci_bus(bus);
	if (parent == NULL)
		return NULL;
	pr_debug(" parent is %s\n", parent ? parent->full_name : "<NULL>");
	np = scan_OF_for_pci_dev(parent, devfn);
	of_node_put(parent);
	pr_debug(" result is %s\n", np ? np->full_name : "<NULL>");

	/* XXX most callers don't release the returned node
	 * mostly because ppc64 doesn't increase the refcount,
	 * we need to fix that.
	 */
	return np;
}
EXPORT_SYMBOL(pci_busdev_to_OF_node);

struct device_node*
pci_device_to_OF_node(struct pci_dev *dev)
{
	return pci_busdev_to_OF_node(dev->bus, dev->devfn);
}
EXPORT_SYMBOL(pci_device_to_OF_node);

static int
find_OF_pci_device_filter(struct device_node *node, void *data)
{
@@ -315,6 +283,13 @@ pci_create_OF_bus_map(void)
	}
}

struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
{
	struct pci_controller *hose = bus->sysdata;

	return of_node_get(hose->dn);
}

static void __devinit pcibios_scan_phb(struct pci_controller *hose)
{
	struct pci_bus *bus;
@@ -332,7 +307,6 @@ static void __devinit pcibios_scan_phb(struct pci_controller *hose)
		       hose->global_number);
		return;
	}
	bus.dev->of_node = of_node_get(node);
	bus->secondary = hose->first_busno;
	hose->bus = bus;

+11 −24
Original line number Diff line number Diff line
@@ -169,18 +169,22 @@ static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
	return bus->sysdata;
}

#ifndef CONFIG_PPC64
static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
{
	return dev->dev.of_node;
}

static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
{
	struct pci_controller *host;

	if (bus->self)
		return pci_device_to_OF_node(bus->self);
	host = pci_bus_to_host(bus);
	return host ? host->dn : NULL;
	return bus->dev.of_node;
}

#ifndef CONFIG_PPC64

extern int pci_device_from_OF_node(struct device_node *node,
				   u8 *bus, u8 *devfn);
extern void pci_create_OF_bus_map(void);

static inline int isa_vaddr_is_ioport(void __iomem *address)
{
	/* No specific ISA handling on ppc32 at this stage, it
@@ -223,17 +227,8 @@ struct pci_dn {
/* Get the pointer to a device_node's pci_dn */
#define PCI_DN(dn)	((struct pci_dn *) (dn)->data)

extern struct device_node *fetch_dev_dn(struct pci_dev *dev);
extern void * update_dn_pci_info(struct device_node *dn, void *data);

/* Get a device_node from a pci_dev.  This code must be fast except
 * in the case where the sysdata is incorrect and needs to be fixed
 * up (this will only happen once). */
static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
{
	return dev->dev.of_node ? dev->dev.of_node : fetch_dev_dn(dev);
}

static inline int pci_device_from_OF_node(struct device_node *np,
					  u8 *bus, u8 *devfn)
{
@@ -244,14 +239,6 @@ static inline int pci_device_from_OF_node(struct device_node *np,
	return 0;
}

static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
{
	if (bus->self)
		return pci_device_to_OF_node(bus->self);
	else
		return bus->dev.of_node; /* Must be root bus (PHB) */
}

/** Find the bus corresponding to the indicated device node */
extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);

+1 −2
Original line number Diff line number Diff line
@@ -179,8 +179,7 @@ extern int remove_phb_dynamic(struct pci_controller *phb);
extern struct pci_dev *of_create_pci_dev(struct device_node *node,
					struct pci_bus *bus, int devfn);

extern void of_scan_pci_bridge(struct device_node *node,
				struct pci_dev *dev);
extern void of_scan_pci_bridge(struct pci_dev *dev);

extern void of_scan_bus(struct device_node *node, struct pci_bus *bus);
extern void of_rescan_bus(struct device_node *node, struct pci_bus *bus);
Loading