xref: /linux/drivers/pci/bus.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
17328c8f4SBjorn Helgaas // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * From setup-res.c, by:
41da177e4SLinus Torvalds  *	Dave Rusling (david.rusling@reo.mts.dec.com)
51da177e4SLinus Torvalds  *	David Mosberger (davidm@cs.arizona.edu)
61da177e4SLinus Torvalds  *	David Miller (davem@redhat.com)
71da177e4SLinus Torvalds  *	Ivan Kokshaysky (ink@jurassic.park.msu.ru)
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds #include <linux/module.h>
101da177e4SLinus Torvalds #include <linux/kernel.h>
111da177e4SLinus Torvalds #include <linux/pci.h>
121da177e4SLinus Torvalds #include <linux/errno.h>
131da177e4SLinus Torvalds #include <linux/ioport.h>
141a8c251cSVladimir Oltean #include <linux/of.h>
158fb18619SBartosz Golaszewski #include <linux/of_platform.h>
161da177e4SLinus Torvalds #include <linux/proc_fs.h>
175a0e3ad6STejun Heo #include <linux/slab.h>
181da177e4SLinus Torvalds 
191da177e4SLinus Torvalds #include "pci.h"
201da177e4SLinus Torvalds 
pci_add_resource_offset(struct list_head * resources,struct resource * res,resource_size_t offset)210efd5aabSBjorn Helgaas void pci_add_resource_offset(struct list_head *resources, struct resource *res,
220efd5aabSBjorn Helgaas 			     resource_size_t offset)
2345ca9e97SBjorn Helgaas {
2414d76b68SJiang Liu 	struct resource_entry *entry;
2545ca9e97SBjorn Helgaas 
2614d76b68SJiang Liu 	entry = resource_list_create_entry(res, 0);
2714d76b68SJiang Liu 	if (!entry) {
2825da8dbaSMohan Kumar 		pr_err("PCI: can't add host bridge window %pR\n", res);
2945ca9e97SBjorn Helgaas 		return;
3045ca9e97SBjorn Helgaas 	}
3145ca9e97SBjorn Helgaas 
3214d76b68SJiang Liu 	entry->offset = offset;
3314d76b68SJiang Liu 	resource_list_add_tail(entry, resources);
340efd5aabSBjorn Helgaas }
350efd5aabSBjorn Helgaas EXPORT_SYMBOL(pci_add_resource_offset);
360efd5aabSBjorn Helgaas 
pci_add_resource(struct list_head * resources,struct resource * res)370efd5aabSBjorn Helgaas void pci_add_resource(struct list_head *resources, struct resource *res)
380efd5aabSBjorn Helgaas {
390efd5aabSBjorn Helgaas 	pci_add_resource_offset(resources, res, 0);
4045ca9e97SBjorn Helgaas }
4145ca9e97SBjorn Helgaas EXPORT_SYMBOL(pci_add_resource);
4245ca9e97SBjorn Helgaas 
pci_free_resource_list(struct list_head * resources)4345ca9e97SBjorn Helgaas void pci_free_resource_list(struct list_head *resources)
4445ca9e97SBjorn Helgaas {
4514d76b68SJiang Liu 	resource_list_free(resources);
4645ca9e97SBjorn Helgaas }
4745ca9e97SBjorn Helgaas EXPORT_SYMBOL(pci_free_resource_list);
4845ca9e97SBjorn Helgaas 
pci_bus_add_resource(struct pci_bus * bus,struct resource * res,unsigned int flags)492fe2abf8SBjorn Helgaas void pci_bus_add_resource(struct pci_bus *bus, struct resource *res,
502fe2abf8SBjorn Helgaas 			  unsigned int flags)
512fe2abf8SBjorn Helgaas {
522fe2abf8SBjorn Helgaas 	struct pci_bus_resource *bus_res;
532fe2abf8SBjorn Helgaas 
542fe2abf8SBjorn Helgaas 	bus_res = kzalloc(sizeof(struct pci_bus_resource), GFP_KERNEL);
552fe2abf8SBjorn Helgaas 	if (!bus_res) {
562fe2abf8SBjorn Helgaas 		dev_err(&bus->dev, "can't add %pR resource\n", res);
572fe2abf8SBjorn Helgaas 		return;
582fe2abf8SBjorn Helgaas 	}
592fe2abf8SBjorn Helgaas 
602fe2abf8SBjorn Helgaas 	bus_res->res = res;
612fe2abf8SBjorn Helgaas 	bus_res->flags = flags;
622fe2abf8SBjorn Helgaas 	list_add_tail(&bus_res->list, &bus->resources);
632fe2abf8SBjorn Helgaas }
642fe2abf8SBjorn Helgaas 
pci_bus_resource_n(const struct pci_bus * bus,int n)652fe2abf8SBjorn Helgaas struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n)
662fe2abf8SBjorn Helgaas {
672fe2abf8SBjorn Helgaas 	struct pci_bus_resource *bus_res;
682fe2abf8SBjorn Helgaas 
692fe2abf8SBjorn Helgaas 	if (n < PCI_BRIDGE_RESOURCE_NUM)
702fe2abf8SBjorn Helgaas 		return bus->resource[n];
712fe2abf8SBjorn Helgaas 
722fe2abf8SBjorn Helgaas 	n -= PCI_BRIDGE_RESOURCE_NUM;
732fe2abf8SBjorn Helgaas 	list_for_each_entry(bus_res, &bus->resources, list) {
742fe2abf8SBjorn Helgaas 		if (n-- == 0)
752fe2abf8SBjorn Helgaas 			return bus_res->res;
762fe2abf8SBjorn Helgaas 	}
772fe2abf8SBjorn Helgaas 	return NULL;
782fe2abf8SBjorn Helgaas }
792fe2abf8SBjorn Helgaas EXPORT_SYMBOL_GPL(pci_bus_resource_n);
802fe2abf8SBjorn Helgaas 
pci_bus_remove_resource(struct pci_bus * bus,struct resource * res)81ab909509SNiklas Schnelle void pci_bus_remove_resource(struct pci_bus *bus, struct resource *res)
82ab909509SNiklas Schnelle {
83ab909509SNiklas Schnelle 	struct pci_bus_resource *bus_res, *tmp;
84ab909509SNiklas Schnelle 	int i;
85ab909509SNiklas Schnelle 
86ab909509SNiklas Schnelle 	for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) {
87ab909509SNiklas Schnelle 		if (bus->resource[i] == res) {
88ab909509SNiklas Schnelle 			bus->resource[i] = NULL;
89ab909509SNiklas Schnelle 			return;
90ab909509SNiklas Schnelle 		}
91ab909509SNiklas Schnelle 	}
92ab909509SNiklas Schnelle 
93ab909509SNiklas Schnelle 	list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) {
94ab909509SNiklas Schnelle 		if (bus_res->res == res) {
95ab909509SNiklas Schnelle 			list_del(&bus_res->list);
96ab909509SNiklas Schnelle 			kfree(bus_res);
97ab909509SNiklas Schnelle 			return;
98ab909509SNiklas Schnelle 		}
99ab909509SNiklas Schnelle 	}
100ab909509SNiklas Schnelle }
101ab909509SNiklas Schnelle 
pci_bus_remove_resources(struct pci_bus * bus)1022fe2abf8SBjorn Helgaas void pci_bus_remove_resources(struct pci_bus *bus)
1032fe2abf8SBjorn Helgaas {
1042fe2abf8SBjorn Helgaas 	int i;
105817a2685SYinghai Lu 	struct pci_bus_resource *bus_res, *tmp;
1062fe2abf8SBjorn Helgaas 
1072fe2abf8SBjorn Helgaas 	for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
1087736a05aSStephen Hemminger 		bus->resource[i] = NULL;
1092fe2abf8SBjorn Helgaas 
110817a2685SYinghai Lu 	list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) {
111817a2685SYinghai Lu 		list_del(&bus_res->list);
112817a2685SYinghai Lu 		kfree(bus_res);
113817a2685SYinghai Lu 	}
1142fe2abf8SBjorn Helgaas }
1152fe2abf8SBjorn Helgaas 
devm_request_pci_bus_resources(struct device * dev,struct list_head * resources)116950334bcSBjorn Helgaas int devm_request_pci_bus_resources(struct device *dev,
117950334bcSBjorn Helgaas 				   struct list_head *resources)
118950334bcSBjorn Helgaas {
119950334bcSBjorn Helgaas 	struct resource_entry *win;
120950334bcSBjorn Helgaas 	struct resource *parent, *res;
121950334bcSBjorn Helgaas 	int err;
122950334bcSBjorn Helgaas 
123950334bcSBjorn Helgaas 	resource_list_for_each_entry(win, resources) {
124950334bcSBjorn Helgaas 		res = win->res;
125950334bcSBjorn Helgaas 		switch (resource_type(res)) {
126950334bcSBjorn Helgaas 		case IORESOURCE_IO:
127950334bcSBjorn Helgaas 			parent = &ioport_resource;
128950334bcSBjorn Helgaas 			break;
129950334bcSBjorn Helgaas 		case IORESOURCE_MEM:
130950334bcSBjorn Helgaas 			parent = &iomem_resource;
131950334bcSBjorn Helgaas 			break;
132950334bcSBjorn Helgaas 		default:
133950334bcSBjorn Helgaas 			continue;
134950334bcSBjorn Helgaas 		}
135950334bcSBjorn Helgaas 
136950334bcSBjorn Helgaas 		err = devm_request_resource(dev, parent, res);
137950334bcSBjorn Helgaas 		if (err)
138950334bcSBjorn Helgaas 			return err;
139950334bcSBjorn Helgaas 	}
140950334bcSBjorn Helgaas 
141950334bcSBjorn Helgaas 	return 0;
142950334bcSBjorn Helgaas }
143950334bcSBjorn Helgaas EXPORT_SYMBOL_GPL(devm_request_pci_bus_resources);
144950334bcSBjorn Helgaas 
145f75b99d5SYinghai Lu static struct pci_bus_region pci_32_bit = {0, 0xffffffffULL};
1468e639079SChristoph Hellwig #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
147f75b99d5SYinghai Lu static struct pci_bus_region pci_64_bit = {0,
1483a9ad0b4SYinghai Lu 				(pci_bus_addr_t) 0xffffffffffffffffULL};
1493a9ad0b4SYinghai Lu static struct pci_bus_region pci_high = {(pci_bus_addr_t) 0x100000000ULL,
1503a9ad0b4SYinghai Lu 				(pci_bus_addr_t) 0xffffffffffffffffULL};
151f75b99d5SYinghai Lu #endif
152f75b99d5SYinghai Lu 
153f75b99d5SYinghai Lu /*
154f75b99d5SYinghai Lu  * @res contains CPU addresses.  Clip it so the corresponding bus addresses
155f75b99d5SYinghai Lu  * on @bus are entirely within @region.  This is used to control the bus
156f75b99d5SYinghai Lu  * addresses of resources we allocate, e.g., we may need a resource that
157f75b99d5SYinghai Lu  * can be mapped by a 32-bit BAR.
1581da177e4SLinus Torvalds  */
pci_clip_resource_to_region(struct pci_bus * bus,struct resource * res,struct pci_bus_region * region)159f75b99d5SYinghai Lu static void pci_clip_resource_to_region(struct pci_bus *bus,
160f75b99d5SYinghai Lu 					struct resource *res,
161f75b99d5SYinghai Lu 					struct pci_bus_region *region)
162f75b99d5SYinghai Lu {
163f75b99d5SYinghai Lu 	struct pci_bus_region r;
164f75b99d5SYinghai Lu 
165f75b99d5SYinghai Lu 	pcibios_resource_to_bus(bus, &r, res);
166f75b99d5SYinghai Lu 	if (r.start < region->start)
167f75b99d5SYinghai Lu 		r.start = region->start;
168f75b99d5SYinghai Lu 	if (r.end > region->end)
169f75b99d5SYinghai Lu 		r.end = region->end;
170f75b99d5SYinghai Lu 
171f75b99d5SYinghai Lu 	if (r.end < r.start)
172f75b99d5SYinghai Lu 		res->end = res->start - 1;
173f75b99d5SYinghai Lu 	else
174f75b99d5SYinghai Lu 		pcibios_bus_to_resource(bus, res, &r);
175f75b99d5SYinghai Lu }
176f75b99d5SYinghai Lu 
pci_bus_alloc_from_region(struct pci_bus * bus,struct resource * res,resource_size_t size,resource_size_t align,resource_size_t min,unsigned long type_mask,resource_alignf alignf,void * alignf_data,struct pci_bus_region * region)177f75b99d5SYinghai Lu static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
178e31dd6e4SGreg Kroah-Hartman 		resource_size_t size, resource_size_t align,
179664c2848SBjorn Helgaas 		resource_size_t min, unsigned long type_mask,
180*4eed3dd7SIlpo Järvinen 		resource_alignf alignf,
181f75b99d5SYinghai Lu 		void *alignf_data,
182f75b99d5SYinghai Lu 		struct pci_bus_region *region)
1831da177e4SLinus Torvalds {
184f75b99d5SYinghai Lu 	struct resource *r, avail;
185f75b99d5SYinghai Lu 	resource_size_t max;
18602992064SAndy Shevchenko 	int ret;
1871da177e4SLinus Torvalds 
188aa11fc58SBjorn Helgaas 	type_mask |= IORESOURCE_TYPE_BITS;
1891da177e4SLinus Torvalds 
19002992064SAndy Shevchenko 	pci_bus_for_each_resource(bus, r) {
1913460baa6SChristoph Biedl 		resource_size_t min_used = min;
1923460baa6SChristoph Biedl 
1936db45b76SBjorn Helgaas 		if (!r)
1946db45b76SBjorn Helgaas 			continue;
1956db45b76SBjorn Helgaas 
1961da177e4SLinus Torvalds 		/* type_mask must match */
1971da177e4SLinus Torvalds 		if ((res->flags ^ r->flags) & type_mask)
1981da177e4SLinus Torvalds 			continue;
1991da177e4SLinus Torvalds 
2001da177e4SLinus Torvalds 		/* We cannot allocate a non-prefetching resource
2011da177e4SLinus Torvalds 		   from a pre-fetching area */
2021da177e4SLinus Torvalds 		if ((r->flags & IORESOURCE_PREFETCH) &&
2031da177e4SLinus Torvalds 		    !(res->flags & IORESOURCE_PREFETCH))
2041da177e4SLinus Torvalds 			continue;
2051da177e4SLinus Torvalds 
206f75b99d5SYinghai Lu 		avail = *r;
207f75b99d5SYinghai Lu 		pci_clip_resource_to_region(bus, &avail, region);
208f75b99d5SYinghai Lu 
209f75b99d5SYinghai Lu 		/*
210f75b99d5SYinghai Lu 		 * "min" is typically PCIBIOS_MIN_IO or PCIBIOS_MIN_MEM to
211f75b99d5SYinghai Lu 		 * protect badly documented motherboard resources, but if
212f75b99d5SYinghai Lu 		 * this is an already-configured bridge window, its start
213f75b99d5SYinghai Lu 		 * overrides "min".
214f75b99d5SYinghai Lu 		 */
215f75b99d5SYinghai Lu 		if (avail.start)
2163460baa6SChristoph Biedl 			min_used = avail.start;
217f75b99d5SYinghai Lu 
218f75b99d5SYinghai Lu 		max = avail.end;
219f75b99d5SYinghai Lu 
2205c5fb3c3SBjorn Helgaas 		/* Don't bother if available space isn't large enough */
2215c5fb3c3SBjorn Helgaas 		if (size > max - min_used + 1)
2225c5fb3c3SBjorn Helgaas 			continue;
2235c5fb3c3SBjorn Helgaas 
2241da177e4SLinus Torvalds 		/* Ok, try it out.. */
2253460baa6SChristoph Biedl 		ret = allocate_resource(r, res, size, min_used, max,
226f75b99d5SYinghai Lu 					align, alignf, alignf_data);
2271da177e4SLinus Torvalds 		if (ret == 0)
228f75b99d5SYinghai Lu 			return 0;
2291da177e4SLinus Torvalds 	}
230f75b99d5SYinghai Lu 	return -ENOMEM;
231f75b99d5SYinghai Lu }
232f75b99d5SYinghai Lu 
2331da177e4SLinus Torvalds /**
2341da177e4SLinus Torvalds  * pci_bus_alloc_resource - allocate a resource from a parent bus
2351da177e4SLinus Torvalds  * @bus: PCI bus
2361da177e4SLinus Torvalds  * @res: resource to allocate
2371da177e4SLinus Torvalds  * @size: size of resource to allocate
2381da177e4SLinus Torvalds  * @align: alignment of resource to allocate
2391da177e4SLinus Torvalds  * @min: minimum /proc/iomem address to allocate
2401da177e4SLinus Torvalds  * @type_mask: IORESOURCE_* type flags
2411da177e4SLinus Torvalds  * @alignf: resource alignment function
2421da177e4SLinus Torvalds  * @alignf_data: data argument for resource alignment function
2431da177e4SLinus Torvalds  *
2441da177e4SLinus Torvalds  * Given the PCI bus a device resides on, the size, minimum address,
2451da177e4SLinus Torvalds  * alignment and type, try to find an acceptable resource allocation
2461da177e4SLinus Torvalds  * for a specific device resource.
2471da177e4SLinus Torvalds  */
pci_bus_alloc_resource(struct pci_bus * bus,struct resource * res,resource_size_t size,resource_size_t align,resource_size_t min,unsigned long type_mask,resource_alignf alignf,void * alignf_data)248d56dbf5bSYinghai Lu int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
2491da177e4SLinus Torvalds 		resource_size_t size, resource_size_t align,
250664c2848SBjorn Helgaas 		resource_size_t min, unsigned long type_mask,
251*4eed3dd7SIlpo Järvinen 		resource_alignf alignf,
2521da177e4SLinus Torvalds 		void *alignf_data)
2531da177e4SLinus Torvalds {
2548e639079SChristoph Hellwig #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
255d56dbf5bSYinghai Lu 	int rc;
256d56dbf5bSYinghai Lu 
257d56dbf5bSYinghai Lu 	if (res->flags & IORESOURCE_MEM_64) {
258d56dbf5bSYinghai Lu 		rc = pci_bus_alloc_from_region(bus, res, size, align, min,
259d56dbf5bSYinghai Lu 					       type_mask, alignf, alignf_data,
260d56dbf5bSYinghai Lu 					       &pci_high);
261d56dbf5bSYinghai Lu 		if (rc == 0)
262d56dbf5bSYinghai Lu 			return 0;
263d56dbf5bSYinghai Lu 
264f75b99d5SYinghai Lu 		return pci_bus_alloc_from_region(bus, res, size, align, min,
265f75b99d5SYinghai Lu 						 type_mask, alignf, alignf_data,
266f75b99d5SYinghai Lu 						 &pci_64_bit);
267d56dbf5bSYinghai Lu 	}
268f75b99d5SYinghai Lu #endif
2691da177e4SLinus Torvalds 
270f75b99d5SYinghai Lu 	return pci_bus_alloc_from_region(bus, res, size, align, min,
271f75b99d5SYinghai Lu 					 type_mask, alignf, alignf_data,
272f75b99d5SYinghai Lu 					 &pci_32_bit);
2731da177e4SLinus Torvalds }
274b7fe9434SRyan Desfosses EXPORT_SYMBOL(pci_bus_alloc_resource);
2751da177e4SLinus Torvalds 
2760f7e7aeeSYinghai Lu /*
2770f7e7aeeSYinghai Lu  * The @idx resource of @dev should be a PCI-PCI bridge window.  If this
2780f7e7aeeSYinghai Lu  * resource fits inside a window of an upstream bridge, do nothing.  If it
2790f7e7aeeSYinghai Lu  * overlaps an upstream window but extends outside it, clip the resource so
2800f7e7aeeSYinghai Lu  * it fits completely inside.
2810f7e7aeeSYinghai Lu  */
pci_bus_clip_resource(struct pci_dev * dev,int idx)2820f7e7aeeSYinghai Lu bool pci_bus_clip_resource(struct pci_dev *dev, int idx)
2830f7e7aeeSYinghai Lu {
2840f7e7aeeSYinghai Lu 	struct pci_bus *bus = dev->bus;
2850f7e7aeeSYinghai Lu 	struct resource *res = &dev->resource[idx];
2860f7e7aeeSYinghai Lu 	struct resource orig_res = *res;
2870f7e7aeeSYinghai Lu 	struct resource *r;
2880f7e7aeeSYinghai Lu 
28902992064SAndy Shevchenko 	pci_bus_for_each_resource(bus, r) {
2900f7e7aeeSYinghai Lu 		resource_size_t start, end;
2910f7e7aeeSYinghai Lu 
2920f7e7aeeSYinghai Lu 		if (!r)
2930f7e7aeeSYinghai Lu 			continue;
2940f7e7aeeSYinghai Lu 
2950f7e7aeeSYinghai Lu 		if (resource_type(res) != resource_type(r))
2960f7e7aeeSYinghai Lu 			continue;
2970f7e7aeeSYinghai Lu 
2980f7e7aeeSYinghai Lu 		start = max(r->start, res->start);
2990f7e7aeeSYinghai Lu 		end = min(r->end, res->end);
3000f7e7aeeSYinghai Lu 
3010f7e7aeeSYinghai Lu 		if (start > end)
3020f7e7aeeSYinghai Lu 			continue;	/* no overlap */
3030f7e7aeeSYinghai Lu 
3040f7e7aeeSYinghai Lu 		if (res->start == start && res->end == end)
3050f7e7aeeSYinghai Lu 			return false;	/* no change */
3060f7e7aeeSYinghai Lu 
3070f7e7aeeSYinghai Lu 		res->start = start;
3080f7e7aeeSYinghai Lu 		res->end = end;
309b838b39eSBjorn Helgaas 		res->flags &= ~IORESOURCE_UNSET;
310b838b39eSBjorn Helgaas 		orig_res.flags &= ~IORESOURCE_UNSET;
31134c6b710SMohan Kumar 		pci_info(dev, "%pR clipped to %pR\n", &orig_res, res);
3120f7e7aeeSYinghai Lu 
3130f7e7aeeSYinghai Lu 		return true;
3140f7e7aeeSYinghai Lu 	}
3150f7e7aeeSYinghai Lu 
3160f7e7aeeSYinghai Lu 	return false;
3170f7e7aeeSYinghai Lu }
3180f7e7aeeSYinghai Lu 
pcibios_resource_survey_bus(struct pci_bus * bus)3193c449ed0SYinghai Lu void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
3203c449ed0SYinghai Lu 
pcibios_bus_add_device(struct pci_dev * pdev)3217b77061fSWei Yang void __weak pcibios_bus_add_device(struct pci_dev *pdev) { }
3227b77061fSWei Yang 
3231da177e4SLinus Torvalds /**
3244f535093SYinghai Lu  * pci_bus_add_device - start driver for a single device
3251da177e4SLinus Torvalds  * @dev: device to add
3261da177e4SLinus Torvalds  *
3274f535093SYinghai Lu  * This adds add sysfs entries and start device drivers
3281da177e4SLinus Torvalds  */
pci_bus_add_device(struct pci_dev * dev)329c893d133SYijing Wang void pci_bus_add_device(struct pci_dev *dev)
3301da177e4SLinus Torvalds {
3311a8c251cSVladimir Oltean 	struct device_node *dn = dev->dev.of_node;
332b19441afSGreg Kroah-Hartman 	int retval;
333735bff10SMyron Stowe 
3344f535093SYinghai Lu 	/*
3354f535093SYinghai Lu 	 * Can not put in pci_device_add yet because resources
3364f535093SYinghai Lu 	 * are not assigned yet for some devices.
3374f535093SYinghai Lu 	 */
3387b77061fSWei Yang 	pcibios_bus_add_device(dev);
339e253aaf0SYinghai Lu 	pci_fixup_device(pci_fixup_final, dev);
340407d1a51SLizhi Hou 	if (pci_is_bridge(dev))
341407d1a51SLizhi Hou 		of_pci_make_dev_node(dev);
3424f535093SYinghai Lu 	pci_create_sysfs_dev_files(dev);
343ef37702eSYinghai Lu 	pci_proc_attach_device(dev);
3441ed276a7SLukas Wunner 	pci_bridge_d3_update(dev);
3451da177e4SLinus Torvalds 
3461a8c251cSVladimir Oltean 	dev->match_driver = !dn || of_device_is_available(dn);
34758d9a38fSYinghai Lu 	retval = device_attach(&dev->dev);
3482194bc7cSRajat Jain 	if (retval < 0 && retval != -EPROBE_DEFER)
3497506dc79SFrederick Lawler 		pci_warn(dev, "device attach failed (%d)\n", retval);
35058d9a38fSYinghai Lu 
35144bda4b7SHari Vyas 	pci_dev_assign_added(dev, true);
3528fb18619SBartosz Golaszewski 
35324777bacSManivannan Sadhasivam 	if (dev_of_node(&dev->dev) && pci_is_bridge(dev)) {
35424777bacSManivannan Sadhasivam 		retval = of_platform_populate(dev_of_node(&dev->dev), NULL, NULL,
3558fb18619SBartosz Golaszewski 					      &dev->dev);
3568fb18619SBartosz Golaszewski 		if (retval)
3578fb18619SBartosz Golaszewski 			pci_err(dev, "failed to populate child OF nodes (%d)\n",
3588fb18619SBartosz Golaszewski 				retval);
3598fb18619SBartosz Golaszewski 	}
3601da177e4SLinus Torvalds }
361b7fe9434SRyan Desfosses EXPORT_SYMBOL_GPL(pci_bus_add_device);
3621da177e4SLinus Torvalds 
3631da177e4SLinus Torvalds /**
3644f535093SYinghai Lu  * pci_bus_add_devices - start driver for PCI devices
3651da177e4SLinus Torvalds  * @bus: bus to check for new devices
3661da177e4SLinus Torvalds  *
3674f535093SYinghai Lu  * Start driver for PCI devices and add some sysfs entries.
3681da177e4SLinus Torvalds  */
pci_bus_add_devices(const struct pci_bus * bus)369c48f1670Sakpm@linux-foundation.org void pci_bus_add_devices(const struct pci_bus *bus)
3701da177e4SLinus Torvalds {
3711da177e4SLinus Torvalds 	struct pci_dev *dev;
3723fa16fdbSYu Zhao 	struct pci_bus *child;
3731da177e4SLinus Torvalds 
3741da177e4SLinus Torvalds 	list_for_each_entry(dev, &bus->devices, bus_list) {
3758a1bc901SGreg Kroah-Hartman 		/* Skip already-added devices */
37644bda4b7SHari Vyas 		if (pci_dev_is_added(dev))
3771da177e4SLinus Torvalds 			continue;
378c893d133SYijing Wang 		pci_bus_add_device(dev);
3791da177e4SLinus Torvalds 	}
3801da177e4SLinus Torvalds 
3811da177e4SLinus Torvalds 	list_for_each_entry(dev, &bus->devices, bus_list) {
3821e398eaeSLukas Wunner 		/* Skip if device attach failed */
38344bda4b7SHari Vyas 		if (!pci_dev_is_added(dev))
3841e398eaeSLukas Wunner 			continue;
3853fa16fdbSYu Zhao 		child = dev->subordinate;
386981cf9eaSJiang Liu 		if (child)
3873fa16fdbSYu Zhao 			pci_bus_add_devices(child);
3881da177e4SLinus Torvalds 	}
3891da177e4SLinus Torvalds }
390b7fe9434SRyan Desfosses EXPORT_SYMBOL(pci_bus_add_devices);
3911da177e4SLinus Torvalds 
__pci_walk_bus(struct pci_bus * top,int (* cb)(struct pci_dev *,void *),void * userdata,bool locked)3921e560864SJohan Hovold static void __pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
3931e560864SJohan Hovold 			   void *userdata, bool locked)
394cecf4864SPaul Mackerras {
395cecf4864SPaul Mackerras 	struct pci_dev *dev;
396cecf4864SPaul Mackerras 	struct pci_bus *bus;
397cecf4864SPaul Mackerras 	struct list_head *next;
39870298c6eSZhang, Yanmin 	int retval;
399cecf4864SPaul Mackerras 
400cecf4864SPaul Mackerras 	bus = top;
4011e560864SJohan Hovold 	if (!locked)
402d71374daSZhang Yanmin 		down_read(&pci_bus_sem);
403cecf4864SPaul Mackerras 	next = top->devices.next;
404cecf4864SPaul Mackerras 	for (;;) {
405cecf4864SPaul Mackerras 		if (next == &bus->devices) {
406cecf4864SPaul Mackerras 			/* end of this bus, go up or finish */
407cecf4864SPaul Mackerras 			if (bus == top)
408cecf4864SPaul Mackerras 				break;
409cecf4864SPaul Mackerras 			next = bus->self->bus_list.next;
410cecf4864SPaul Mackerras 			bus = bus->self->bus;
411cecf4864SPaul Mackerras 			continue;
412cecf4864SPaul Mackerras 		}
413cecf4864SPaul Mackerras 		dev = list_entry(next, struct pci_dev, bus_list);
414cecf4864SPaul Mackerras 		if (dev->subordinate) {
415cecf4864SPaul Mackerras 			/* this is a pci-pci bridge, do its devices next */
416cecf4864SPaul Mackerras 			next = dev->subordinate->devices.next;
417cecf4864SPaul Mackerras 			bus = dev->subordinate;
418cecf4864SPaul Mackerras 		} else
419cecf4864SPaul Mackerras 			next = dev->bus_list.next;
420cecf4864SPaul Mackerras 
42170298c6eSZhang, Yanmin 		retval = cb(dev, userdata);
42270298c6eSZhang, Yanmin 		if (retval)
42370298c6eSZhang, Yanmin 			break;
424cecf4864SPaul Mackerras 	}
4251e560864SJohan Hovold 	if (!locked)
426d71374daSZhang Yanmin 		up_read(&pci_bus_sem);
427cecf4864SPaul Mackerras }
4281e560864SJohan Hovold 
4291e560864SJohan Hovold /**
4301e560864SJohan Hovold  *  pci_walk_bus - walk devices on/under bus, calling callback.
4311e560864SJohan Hovold  *  @top: bus whose devices should be walked
4321e560864SJohan Hovold  *  @cb: callback to be called for each device found
4331e560864SJohan Hovold  *  @userdata: arbitrary pointer to be passed to callback
4341e560864SJohan Hovold  *
4351e560864SJohan Hovold  *  Walk the given bus, including any bridged devices
4361e560864SJohan Hovold  *  on buses under this bus.  Call the provided callback
4371e560864SJohan Hovold  *  on each device found.
4381e560864SJohan Hovold  *
4391e560864SJohan Hovold  *  We check the return of @cb each time. If it returns anything
4401e560864SJohan Hovold  *  other than 0, we break out.
4411e560864SJohan Hovold  */
pci_walk_bus(struct pci_bus * top,int (* cb)(struct pci_dev *,void *),void * userdata)4421e560864SJohan Hovold void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), void *userdata)
4431e560864SJohan Hovold {
4441e560864SJohan Hovold 	__pci_walk_bus(top, cb, userdata, false);
4451e560864SJohan Hovold }
4467c94def8SKonrad Rzeszutek Wilk EXPORT_SYMBOL_GPL(pci_walk_bus);
447cecf4864SPaul Mackerras 
pci_walk_bus_locked(struct pci_bus * top,int (* cb)(struct pci_dev *,void *),void * userdata)4481e560864SJohan Hovold void pci_walk_bus_locked(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), void *userdata)
4491e560864SJohan Hovold {
4501e560864SJohan Hovold 	lockdep_assert_held(&pci_bus_sem);
4511e560864SJohan Hovold 
4521e560864SJohan Hovold 	__pci_walk_bus(top, cb, userdata, true);
4531e560864SJohan Hovold }
4541e560864SJohan Hovold EXPORT_SYMBOL_GPL(pci_walk_bus_locked);
4551e560864SJohan Hovold 
pci_bus_get(struct pci_bus * bus)456fe830ef6SJiang Liu struct pci_bus *pci_bus_get(struct pci_bus *bus)
457fe830ef6SJiang Liu {
458fe830ef6SJiang Liu 	if (bus)
459fe830ef6SJiang Liu 		get_device(&bus->dev);
460fe830ef6SJiang Liu 	return bus;
461fe830ef6SJiang Liu }
462fe830ef6SJiang Liu 
pci_bus_put(struct pci_bus * bus)463fe830ef6SJiang Liu void pci_bus_put(struct pci_bus *bus)
464fe830ef6SJiang Liu {
465fe830ef6SJiang Liu 	if (bus)
466fe830ef6SJiang Liu 		put_device(&bus->dev);
467fe830ef6SJiang Liu }
468