linux/drivers/pci/bus.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * From setup-res.c, by:
   4 *      Dave Rusling (david.rusling@reo.mts.dec.com)
   5 *      David Mosberger (davidm@cs.arizona.edu)
   6 *      David Miller (davem@redhat.com)
   7 *      Ivan Kokshaysky (ink@jurassic.park.msu.ru)
   8 */
   9#include <linux/module.h>
  10#include <linux/kernel.h>
  11#include <linux/pci.h>
  12#include <linux/errno.h>
  13#include <linux/ioport.h>
  14#include <linux/proc_fs.h>
  15#include <linux/slab.h>
  16
  17#include "pci.h"
  18
  19void pci_add_resource_offset(struct list_head *resources, struct resource *res,
  20                             resource_size_t offset)
  21{
  22        struct resource_entry *entry;
  23
  24        entry = resource_list_create_entry(res, 0);
  25        if (!entry) {
  26                printk(KERN_ERR "PCI: can't add host bridge window %pR\n", res);
  27                return;
  28        }
  29
  30        entry->offset = offset;
  31        resource_list_add_tail(entry, resources);
  32}
  33EXPORT_SYMBOL(pci_add_resource_offset);
  34
  35void pci_add_resource(struct list_head *resources, struct resource *res)
  36{
  37        pci_add_resource_offset(resources, res, 0);
  38}
  39EXPORT_SYMBOL(pci_add_resource);
  40
  41void pci_free_resource_list(struct list_head *resources)
  42{
  43        resource_list_free(resources);
  44}
  45EXPORT_SYMBOL(pci_free_resource_list);
  46
  47void pci_bus_add_resource(struct pci_bus *bus, struct resource *res,
  48                          unsigned int flags)
  49{
  50        struct pci_bus_resource *bus_res;
  51
  52        bus_res = kzalloc(sizeof(struct pci_bus_resource), GFP_KERNEL);
  53        if (!bus_res) {
  54                dev_err(&bus->dev, "can't add %pR resource\n", res);
  55                return;
  56        }
  57
  58        bus_res->res = res;
  59        bus_res->flags = flags;
  60        list_add_tail(&bus_res->list, &bus->resources);
  61}
  62
  63struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n)
  64{
  65        struct pci_bus_resource *bus_res;
  66
  67        if (n < PCI_BRIDGE_RESOURCE_NUM)
  68                return bus->resource[n];
  69
  70        n -= PCI_BRIDGE_RESOURCE_NUM;
  71        list_for_each_entry(bus_res, &bus->resources, list) {
  72                if (n-- == 0)
  73                        return bus_res->res;
  74        }
  75        return NULL;
  76}
  77EXPORT_SYMBOL_GPL(pci_bus_resource_n);
  78
  79void pci_bus_remove_resources(struct pci_bus *bus)
  80{
  81        int i;
  82        struct pci_bus_resource *bus_res, *tmp;
  83
  84        for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
  85                bus->resource[i] = NULL;
  86
  87        list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) {
  88                list_del(&bus_res->list);
  89                kfree(bus_res);
  90        }
  91}
  92
  93int devm_request_pci_bus_resources(struct device *dev,
  94                                   struct list_head *resources)
  95{
  96        struct resource_entry *win;
  97        struct resource *parent, *res;
  98        int err;
  99
 100        resource_list_for_each_entry(win, resources) {
 101                res = win->res;
 102                switch (resource_type(res)) {
 103                case IORESOURCE_IO:
 104                        parent = &ioport_resource;
 105                        break;
 106                case IORESOURCE_MEM:
 107                        parent = &iomem_resource;
 108                        break;
 109                default:
 110                        continue;
 111                }
 112
 113                err = devm_request_resource(dev, parent, res);
 114                if (err)
 115                        return err;
 116        }
 117
 118        return 0;
 119}
 120EXPORT_SYMBOL_GPL(devm_request_pci_bus_resources);
 121
 122static struct pci_bus_region pci_32_bit = {0, 0xffffffffULL};
 123#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
 124static struct pci_bus_region pci_64_bit = {0,
 125                                (pci_bus_addr_t) 0xffffffffffffffffULL};
 126static struct pci_bus_region pci_high = {(pci_bus_addr_t) 0x100000000ULL,
 127                                (pci_bus_addr_t) 0xffffffffffffffffULL};
 128#endif
 129
 130/*
 131 * @res contains CPU addresses.  Clip it so the corresponding bus addresses
 132 * on @bus are entirely within @region.  This is used to control the bus
 133 * addresses of resources we allocate, e.g., we may need a resource that
 134 * can be mapped by a 32-bit BAR.
 135 */
 136static void pci_clip_resource_to_region(struct pci_bus *bus,
 137                                        struct resource *res,
 138                                        struct pci_bus_region *region)
 139{
 140        struct pci_bus_region r;
 141
 142        pcibios_resource_to_bus(bus, &r, res);
 143        if (r.start < region->start)
 144                r.start = region->start;
 145        if (r.end > region->end)
 146                r.end = region->end;
 147
 148        if (r.end < r.start)
 149                res->end = res->start - 1;
 150        else
 151                pcibios_bus_to_resource(bus, res, &r);
 152}
 153
 154static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
 155                resource_size_t size, resource_size_t align,
 156                resource_size_t min, unsigned long type_mask,
 157                resource_size_t (*alignf)(void *,
 158                                          const struct resource *,
 159                                          resource_size_t,
 160                                          resource_size_t),
 161                void *alignf_data,
 162                struct pci_bus_region *region)
 163{
 164        int i, ret;
 165        struct resource *r, avail;
 166        resource_size_t max;
 167
 168        type_mask |= IORESOURCE_TYPE_BITS;
 169
 170        pci_bus_for_each_resource(bus, r, i) {
 171                resource_size_t min_used = min;
 172
 173                if (!r)
 174                        continue;
 175
 176                /* type_mask must match */
 177                if ((res->flags ^ r->flags) & type_mask)
 178                        continue;
 179
 180                /* We cannot allocate a non-prefetching resource
 181                   from a pre-fetching area */
 182                if ((r->flags & IORESOURCE_PREFETCH) &&
 183                    !(res->flags & IORESOURCE_PREFETCH))
 184                        continue;
 185
 186                avail = *r;
 187                pci_clip_resource_to_region(bus, &avail, region);
 188
 189                /*
 190                 * "min" is typically PCIBIOS_MIN_IO or PCIBIOS_MIN_MEM to
 191                 * protect badly documented motherboard resources, but if
 192                 * this is an already-configured bridge window, its start
 193                 * overrides "min".
 194                 */
 195                if (avail.start)
 196                        min_used = avail.start;
 197
 198                max = avail.end;
 199
 200                /* Ok, try it out.. */
 201                ret = allocate_resource(r, res, size, min_used, max,
 202                                        align, alignf, alignf_data);
 203                if (ret == 0)
 204                        return 0;
 205        }
 206        return -ENOMEM;
 207}
 208
 209/**
 210 * pci_bus_alloc_resource - allocate a resource from a parent bus
 211 * @bus: PCI bus
 212 * @res: resource to allocate
 213 * @size: size of resource to allocate
 214 * @align: alignment of resource to allocate
 215 * @min: minimum /proc/iomem address to allocate
 216 * @type_mask: IORESOURCE_* type flags
 217 * @alignf: resource alignment function
 218 * @alignf_data: data argument for resource alignment function
 219 *
 220 * Given the PCI bus a device resides on, the size, minimum address,
 221 * alignment and type, try to find an acceptable resource allocation
 222 * for a specific device resource.
 223 */
 224int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
 225                resource_size_t size, resource_size_t align,
 226                resource_size_t min, unsigned long type_mask,
 227                resource_size_t (*alignf)(void *,
 228                                          const struct resource *,
 229                                          resource_size_t,
 230                                          resource_size_t),
 231                void *alignf_data)
 232{
 233#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
 234        int rc;
 235
 236        if (res->flags & IORESOURCE_MEM_64) {
 237                rc = pci_bus_alloc_from_region(bus, res, size, align, min,
 238                                               type_mask, alignf, alignf_data,
 239                                               &pci_high);
 240                if (rc == 0)
 241                        return 0;
 242
 243                return pci_bus_alloc_from_region(bus, res, size, align, min,
 244                                                 type_mask, alignf, alignf_data,
 245                                                 &pci_64_bit);
 246        }
 247#endif
 248
 249        return pci_bus_alloc_from_region(bus, res, size, align, min,
 250                                         type_mask, alignf, alignf_data,
 251                                         &pci_32_bit);
 252}
 253EXPORT_SYMBOL(pci_bus_alloc_resource);
 254
 255/*
 256 * The @idx resource of @dev should be a PCI-PCI bridge window.  If this
 257 * resource fits inside a window of an upstream bridge, do nothing.  If it
 258 * overlaps an upstream window but extends outside it, clip the resource so
 259 * it fits completely inside.
 260 */
 261bool pci_bus_clip_resource(struct pci_dev *dev, int idx)
 262{
 263        struct pci_bus *bus = dev->bus;
 264        struct resource *res = &dev->resource[idx];
 265        struct resource orig_res = *res;
 266        struct resource *r;
 267        int i;
 268
 269        pci_bus_for_each_resource(bus, r, i) {
 270                resource_size_t start, end;
 271
 272                if (!r)
 273                        continue;
 274
 275                if (resource_type(res) != resource_type(r))
 276                        continue;
 277
 278                start = max(r->start, res->start);
 279                end = min(r->end, res->end);
 280
 281                if (start > end)
 282                        continue;       /* no overlap */
 283
 284                if (res->start == start && res->end == end)
 285                        return false;   /* no change */
 286
 287                res->start = start;
 288                res->end = end;
 289                res->flags &= ~IORESOURCE_UNSET;
 290                orig_res.flags &= ~IORESOURCE_UNSET;
 291                pci_printk(KERN_DEBUG, dev, "%pR clipped to %pR\n",
 292                                 &orig_res, res);
 293
 294                return true;
 295        }
 296
 297        return false;
 298}
 299
 300void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
 301
 302void __weak pcibios_bus_add_device(struct pci_dev *pdev) { }
 303
 304/**
 305 * pci_bus_add_device - start driver for a single device
 306 * @dev: device to add
 307 *
 308 * This adds add sysfs entries and start device drivers
 309 */
 310void pci_bus_add_device(struct pci_dev *dev)
 311{
 312        int retval;
 313
 314        /*
 315         * Can not put in pci_device_add yet because resources
 316         * are not assigned yet for some devices.
 317         */
 318        pcibios_bus_add_device(dev);
 319        pci_fixup_device(pci_fixup_final, dev);
 320        pci_create_sysfs_dev_files(dev);
 321        pci_proc_attach_device(dev);
 322        pci_bridge_d3_update(dev);
 323
 324        dev->match_driver = true;
 325        retval = device_attach(&dev->dev);
 326        if (retval < 0 && retval != -EPROBE_DEFER) {
 327                pci_warn(dev, "device attach failed (%d)\n", retval);
 328                pci_proc_detach_device(dev);
 329                pci_remove_sysfs_dev_files(dev);
 330                return;
 331        }
 332
 333        pci_dev_assign_added(dev, true);
 334}
 335EXPORT_SYMBOL_GPL(pci_bus_add_device);
 336
 337/**
 338 * pci_bus_add_devices - start driver for PCI devices
 339 * @bus: bus to check for new devices
 340 *
 341 * Start driver for PCI devices and add some sysfs entries.
 342 */
 343void pci_bus_add_devices(const struct pci_bus *bus)
 344{
 345        struct pci_dev *dev;
 346        struct pci_bus *child;
 347
 348        list_for_each_entry(dev, &bus->devices, bus_list) {
 349                /* Skip already-added devices */
 350                if (pci_dev_is_added(dev))
 351                        continue;
 352                pci_bus_add_device(dev);
 353        }
 354
 355        list_for_each_entry(dev, &bus->devices, bus_list) {
 356                /* Skip if device attach failed */
 357                if (!pci_dev_is_added(dev))
 358                        continue;
 359                child = dev->subordinate;
 360                if (child)
 361                        pci_bus_add_devices(child);
 362        }
 363}
 364EXPORT_SYMBOL(pci_bus_add_devices);
 365
 366/** pci_walk_bus - walk devices on/under bus, calling callback.
 367 *  @top      bus whose devices should be walked
 368 *  @cb       callback to be called for each device found
 369 *  @userdata arbitrary pointer to be passed to callback.
 370 *
 371 *  Walk the given bus, including any bridged devices
 372 *  on buses under this bus.  Call the provided callback
 373 *  on each device found.
 374 *
 375 *  We check the return of @cb each time. If it returns anything
 376 *  other than 0, we break out.
 377 *
 378 */
 379void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
 380                  void *userdata)
 381{
 382        struct pci_dev *dev;
 383        struct pci_bus *bus;
 384        struct list_head *next;
 385        int retval;
 386
 387        bus = top;
 388        down_read(&pci_bus_sem);
 389        next = top->devices.next;
 390        for (;;) {
 391                if (next == &bus->devices) {
 392                        /* end of this bus, go up or finish */
 393                        if (bus == top)
 394                                break;
 395                        next = bus->self->bus_list.next;
 396                        bus = bus->self->bus;
 397                        continue;
 398                }
 399                dev = list_entry(next, struct pci_dev, bus_list);
 400                if (dev->subordinate) {
 401                        /* this is a pci-pci bridge, do its devices next */
 402                        next = dev->subordinate->devices.next;
 403                        bus = dev->subordinate;
 404                } else
 405                        next = dev->bus_list.next;
 406
 407                retval = cb(dev, userdata);
 408                if (retval)
 409                        break;
 410        }
 411        up_read(&pci_bus_sem);
 412}
 413EXPORT_SYMBOL_GPL(pci_walk_bus);
 414
 415struct pci_bus *pci_bus_get(struct pci_bus *bus)
 416{
 417        if (bus)
 418                get_device(&bus->dev);
 419        return bus;
 420}
 421EXPORT_SYMBOL(pci_bus_get);
 422
 423void pci_bus_put(struct pci_bus *bus)
 424{
 425        if (bus)
 426                put_device(&bus->dev);
 427}
 428EXPORT_SYMBOL(pci_bus_put);
 429