Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * From setup-res.c, by:
0004  *  Dave Rusling (david.rusling@reo.mts.dec.com)
0005  *  David Mosberger (davidm@cs.arizona.edu)
0006  *  David Miller (davem@redhat.com)
0007  *  Ivan Kokshaysky (ink@jurassic.park.msu.ru)
0008  */
0009 #include <linux/module.h>
0010 #include <linux/kernel.h>
0011 #include <linux/pci.h>
0012 #include <linux/errno.h>
0013 #include <linux/ioport.h>
0014 #include <linux/proc_fs.h>
0015 #include <linux/slab.h>
0016 
0017 #include "pci.h"
0018 
0019 void pci_add_resource_offset(struct list_head *resources, struct resource *res,
0020                  resource_size_t offset)
0021 {
0022     struct resource_entry *entry;
0023 
0024     entry = resource_list_create_entry(res, 0);
0025     if (!entry) {
0026         pr_err("PCI: can't add host bridge window %pR\n", res);
0027         return;
0028     }
0029 
0030     entry->offset = offset;
0031     resource_list_add_tail(entry, resources);
0032 }
0033 EXPORT_SYMBOL(pci_add_resource_offset);
0034 
0035 void pci_add_resource(struct list_head *resources, struct resource *res)
0036 {
0037     pci_add_resource_offset(resources, res, 0);
0038 }
0039 EXPORT_SYMBOL(pci_add_resource);
0040 
0041 void pci_free_resource_list(struct list_head *resources)
0042 {
0043     resource_list_free(resources);
0044 }
0045 EXPORT_SYMBOL(pci_free_resource_list);
0046 
0047 void pci_bus_add_resource(struct pci_bus *bus, struct resource *res,
0048               unsigned int flags)
0049 {
0050     struct pci_bus_resource *bus_res;
0051 
0052     bus_res = kzalloc(sizeof(struct pci_bus_resource), GFP_KERNEL);
0053     if (!bus_res) {
0054         dev_err(&bus->dev, "can't add %pR resource\n", res);
0055         return;
0056     }
0057 
0058     bus_res->res = res;
0059     bus_res->flags = flags;
0060     list_add_tail(&bus_res->list, &bus->resources);
0061 }
0062 
0063 struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n)
0064 {
0065     struct pci_bus_resource *bus_res;
0066 
0067     if (n < PCI_BRIDGE_RESOURCE_NUM)
0068         return bus->resource[n];
0069 
0070     n -= PCI_BRIDGE_RESOURCE_NUM;
0071     list_for_each_entry(bus_res, &bus->resources, list) {
0072         if (n-- == 0)
0073             return bus_res->res;
0074     }
0075     return NULL;
0076 }
0077 EXPORT_SYMBOL_GPL(pci_bus_resource_n);
0078 
0079 void pci_bus_remove_resources(struct pci_bus *bus)
0080 {
0081     int i;
0082     struct pci_bus_resource *bus_res, *tmp;
0083 
0084     for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
0085         bus->resource[i] = NULL;
0086 
0087     list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) {
0088         list_del(&bus_res->list);
0089         kfree(bus_res);
0090     }
0091 }
0092 
0093 int devm_request_pci_bus_resources(struct device *dev,
0094                    struct list_head *resources)
0095 {
0096     struct resource_entry *win;
0097     struct resource *parent, *res;
0098     int err;
0099 
0100     resource_list_for_each_entry(win, resources) {
0101         res = win->res;
0102         switch (resource_type(res)) {
0103         case IORESOURCE_IO:
0104             parent = &ioport_resource;
0105             break;
0106         case IORESOURCE_MEM:
0107             parent = &iomem_resource;
0108             break;
0109         default:
0110             continue;
0111         }
0112 
0113         err = devm_request_resource(dev, parent, res);
0114         if (err)
0115             return err;
0116     }
0117 
0118     return 0;
0119 }
0120 EXPORT_SYMBOL_GPL(devm_request_pci_bus_resources);
0121 
0122 static struct pci_bus_region pci_32_bit = {0, 0xffffffffULL};
0123 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
0124 static struct pci_bus_region pci_64_bit = {0,
0125                 (pci_bus_addr_t) 0xffffffffffffffffULL};
0126 static struct pci_bus_region pci_high = {(pci_bus_addr_t) 0x100000000ULL,
0127                 (pci_bus_addr_t) 0xffffffffffffffffULL};
0128 #endif
0129 
0130 /*
0131  * @res contains CPU addresses.  Clip it so the corresponding bus addresses
0132  * on @bus are entirely within @region.  This is used to control the bus
0133  * addresses of resources we allocate, e.g., we may need a resource that
0134  * can be mapped by a 32-bit BAR.
0135  */
0136 static void pci_clip_resource_to_region(struct pci_bus *bus,
0137                     struct resource *res,
0138                     struct pci_bus_region *region)
0139 {
0140     struct pci_bus_region r;
0141 
0142     pcibios_resource_to_bus(bus, &r, res);
0143     if (r.start < region->start)
0144         r.start = region->start;
0145     if (r.end > region->end)
0146         r.end = region->end;
0147 
0148     if (r.end < r.start)
0149         res->end = res->start - 1;
0150     else
0151         pcibios_bus_to_resource(bus, res, &r);
0152 }
0153 
0154 static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
0155         resource_size_t size, resource_size_t align,
0156         resource_size_t min, unsigned long type_mask,
0157         resource_size_t (*alignf)(void *,
0158                       const struct resource *,
0159                       resource_size_t,
0160                       resource_size_t),
0161         void *alignf_data,
0162         struct pci_bus_region *region)
0163 {
0164     int i, ret;
0165     struct resource *r, avail;
0166     resource_size_t max;
0167 
0168     type_mask |= IORESOURCE_TYPE_BITS;
0169 
0170     pci_bus_for_each_resource(bus, r, i) {
0171         resource_size_t min_used = min;
0172 
0173         if (!r)
0174             continue;
0175 
0176         /* type_mask must match */
0177         if ((res->flags ^ r->flags) & type_mask)
0178             continue;
0179 
0180         /* We cannot allocate a non-prefetching resource
0181            from a pre-fetching area */
0182         if ((r->flags & IORESOURCE_PREFETCH) &&
0183             !(res->flags & IORESOURCE_PREFETCH))
0184             continue;
0185 
0186         avail = *r;
0187         pci_clip_resource_to_region(bus, &avail, region);
0188 
0189         /*
0190          * "min" is typically PCIBIOS_MIN_IO or PCIBIOS_MIN_MEM to
0191          * protect badly documented motherboard resources, but if
0192          * this is an already-configured bridge window, its start
0193          * overrides "min".
0194          */
0195         if (avail.start)
0196             min_used = avail.start;
0197 
0198         max = avail.end;
0199 
0200         /* Ok, try it out.. */
0201         ret = allocate_resource(r, res, size, min_used, max,
0202                     align, alignf, alignf_data);
0203         if (ret == 0)
0204             return 0;
0205     }
0206     return -ENOMEM;
0207 }
0208 
0209 /**
0210  * pci_bus_alloc_resource - allocate a resource from a parent bus
0211  * @bus: PCI bus
0212  * @res: resource to allocate
0213  * @size: size of resource to allocate
0214  * @align: alignment of resource to allocate
0215  * @min: minimum /proc/iomem address to allocate
0216  * @type_mask: IORESOURCE_* type flags
0217  * @alignf: resource alignment function
0218  * @alignf_data: data argument for resource alignment function
0219  *
0220  * Given the PCI bus a device resides on, the size, minimum address,
0221  * alignment and type, try to find an acceptable resource allocation
0222  * for a specific device resource.
0223  */
0224 int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
0225         resource_size_t size, resource_size_t align,
0226         resource_size_t min, unsigned long type_mask,
0227         resource_size_t (*alignf)(void *,
0228                       const struct resource *,
0229                       resource_size_t,
0230                       resource_size_t),
0231         void *alignf_data)
0232 {
0233 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
0234     int rc;
0235 
0236     if (res->flags & IORESOURCE_MEM_64) {
0237         rc = pci_bus_alloc_from_region(bus, res, size, align, min,
0238                            type_mask, alignf, alignf_data,
0239                            &pci_high);
0240         if (rc == 0)
0241             return 0;
0242 
0243         return pci_bus_alloc_from_region(bus, res, size, align, min,
0244                          type_mask, alignf, alignf_data,
0245                          &pci_64_bit);
0246     }
0247 #endif
0248 
0249     return pci_bus_alloc_from_region(bus, res, size, align, min,
0250                      type_mask, alignf, alignf_data,
0251                      &pci_32_bit);
0252 }
0253 EXPORT_SYMBOL(pci_bus_alloc_resource);
0254 
0255 /*
0256  * The @idx resource of @dev should be a PCI-PCI bridge window.  If this
0257  * resource fits inside a window of an upstream bridge, do nothing.  If it
0258  * overlaps an upstream window but extends outside it, clip the resource so
0259  * it fits completely inside.
0260  */
0261 bool pci_bus_clip_resource(struct pci_dev *dev, int idx)
0262 {
0263     struct pci_bus *bus = dev->bus;
0264     struct resource *res = &dev->resource[idx];
0265     struct resource orig_res = *res;
0266     struct resource *r;
0267     int i;
0268 
0269     pci_bus_for_each_resource(bus, r, i) {
0270         resource_size_t start, end;
0271 
0272         if (!r)
0273             continue;
0274 
0275         if (resource_type(res) != resource_type(r))
0276             continue;
0277 
0278         start = max(r->start, res->start);
0279         end = min(r->end, res->end);
0280 
0281         if (start > end)
0282             continue;   /* no overlap */
0283 
0284         if (res->start == start && res->end == end)
0285             return false;   /* no change */
0286 
0287         res->start = start;
0288         res->end = end;
0289         res->flags &= ~IORESOURCE_UNSET;
0290         orig_res.flags &= ~IORESOURCE_UNSET;
0291         pci_info(dev, "%pR clipped to %pR\n", &orig_res, res);
0292 
0293         return true;
0294     }
0295 
0296     return false;
0297 }
0298 
0299 void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
0300 
0301 void __weak pcibios_bus_add_device(struct pci_dev *pdev) { }
0302 
0303 /**
0304  * pci_bus_add_device - start driver for a single device
0305  * @dev: device to add
0306  *
0307  * This adds add sysfs entries and start device drivers
0308  */
0309 void pci_bus_add_device(struct pci_dev *dev)
0310 {
0311     int retval;
0312 
0313     /*
0314      * Can not put in pci_device_add yet because resources
0315      * are not assigned yet for some devices.
0316      */
0317     pcibios_bus_add_device(dev);
0318     pci_fixup_device(pci_fixup_final, dev);
0319     pci_create_sysfs_dev_files(dev);
0320     pci_proc_attach_device(dev);
0321     pci_bridge_d3_update(dev);
0322 
0323     dev->match_driver = true;
0324     retval = device_attach(&dev->dev);
0325     if (retval < 0 && retval != -EPROBE_DEFER)
0326         pci_warn(dev, "device attach failed (%d)\n", retval);
0327 
0328     pci_dev_assign_added(dev, true);
0329 }
0330 EXPORT_SYMBOL_GPL(pci_bus_add_device);
0331 
0332 /**
0333  * pci_bus_add_devices - start driver for PCI devices
0334  * @bus: bus to check for new devices
0335  *
0336  * Start driver for PCI devices and add some sysfs entries.
0337  */
0338 void pci_bus_add_devices(const struct pci_bus *bus)
0339 {
0340     struct pci_dev *dev;
0341     struct pci_bus *child;
0342 
0343     list_for_each_entry(dev, &bus->devices, bus_list) {
0344         /* Skip already-added devices */
0345         if (pci_dev_is_added(dev))
0346             continue;
0347         pci_bus_add_device(dev);
0348     }
0349 
0350     list_for_each_entry(dev, &bus->devices, bus_list) {
0351         /* Skip if device attach failed */
0352         if (!pci_dev_is_added(dev))
0353             continue;
0354         child = dev->subordinate;
0355         if (child)
0356             pci_bus_add_devices(child);
0357     }
0358 }
0359 EXPORT_SYMBOL(pci_bus_add_devices);
0360 
0361 /** pci_walk_bus - walk devices on/under bus, calling callback.
0362  *  @top      bus whose devices should be walked
0363  *  @cb       callback to be called for each device found
0364  *  @userdata arbitrary pointer to be passed to callback.
0365  *
0366  *  Walk the given bus, including any bridged devices
0367  *  on buses under this bus.  Call the provided callback
0368  *  on each device found.
0369  *
0370  *  We check the return of @cb each time. If it returns anything
0371  *  other than 0, we break out.
0372  *
0373  */
0374 void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
0375           void *userdata)
0376 {
0377     struct pci_dev *dev;
0378     struct pci_bus *bus;
0379     struct list_head *next;
0380     int retval;
0381 
0382     bus = top;
0383     down_read(&pci_bus_sem);
0384     next = top->devices.next;
0385     for (;;) {
0386         if (next == &bus->devices) {
0387             /* end of this bus, go up or finish */
0388             if (bus == top)
0389                 break;
0390             next = bus->self->bus_list.next;
0391             bus = bus->self->bus;
0392             continue;
0393         }
0394         dev = list_entry(next, struct pci_dev, bus_list);
0395         if (dev->subordinate) {
0396             /* this is a pci-pci bridge, do its devices next */
0397             next = dev->subordinate->devices.next;
0398             bus = dev->subordinate;
0399         } else
0400             next = dev->bus_list.next;
0401 
0402         retval = cb(dev, userdata);
0403         if (retval)
0404             break;
0405     }
0406     up_read(&pci_bus_sem);
0407 }
0408 EXPORT_SYMBOL_GPL(pci_walk_bus);
0409 
0410 struct pci_bus *pci_bus_get(struct pci_bus *bus)
0411 {
0412     if (bus)
0413         get_device(&bus->dev);
0414     return bus;
0415 }
0416 
0417 void pci_bus_put(struct pci_bus *bus)
0418 {
0419     if (bus)
0420         put_device(&bus->dev);
0421 }