Commit 75acfecaa031c0e1bc412cee4fe58ba49ff3406c

Authored by Kumar Gala
Committed by Greg Kroah-Hartman
1 parent ea28502d5d

[PATCH] PCI: Add pci_assign_resource_fixed -- allow fixed address assignments

PCI: Add pci_assign_resource_fixed -- allow fixed address assignments

On some embedded systems the PCI address for hotplug devices are not only
known a priori but are required to be at a given PCI address for other
master in the system to be able to access.

An example of such a system would be an FPGA which is setup from user space
after the system has booted.  The FPGA may be access by DSPs in the system
and those DSPs expect the FPGA at a fixed PCI address.

Added pci_assign_resource_fixed() as a way to allow assignment of the PCI
devices's BARs at fixed PCI addresses.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 2 changed files with 41 additions and 0 deletions Side-by-side Diff

drivers/pci/setup-res.c
... ... @@ -155,6 +155,46 @@
155 155 return ret;
156 156 }
157 157  
  158 +#ifdef CONFIG_EMBEDDED
  159 +int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
  160 +{
  161 + struct pci_bus *bus = dev->bus;
  162 + struct resource *res = dev->resource + resno;
  163 + unsigned int type_mask;
  164 + int i, ret = -EBUSY;
  165 +
  166 + type_mask = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH;
  167 +
  168 + for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
  169 + struct resource *r = bus->resource[i];
  170 + if (!r)
  171 + continue;
  172 +
  173 + /* type_mask must match */
  174 + if ((res->flags ^ r->flags) & type_mask)
  175 + continue;
  176 +
  177 + ret = request_resource(r, res);
  178 +
  179 + if (ret == 0)
  180 + break;
  181 + }
  182 +
  183 + if (ret) {
  184 + printk(KERN_ERR "PCI: Failed to allocate %s resource "
  185 + "#%d:%llx@%llx for %s\n",
  186 + res->flags & IORESOURCE_IO ? "I/O" : "mem",
  187 + resno, (unsigned long long)(res->end - res->start + 1),
  188 + (unsigned long long)res->start, pci_name(dev));
  189 + } else if (resno < PCI_BRIDGE_RESOURCES) {
  190 + pci_update_resource(dev, res, resno);
  191 + }
  192 +
  193 + return ret;
  194 +}
  195 +EXPORT_SYMBOL_GPL(pci_assign_resource_fixed);
  196 +#endif
  197 +
158 198 /* Sort resources by alignment */
159 199 void __devinit
160 200 pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
... ... @@ -496,6 +496,7 @@
496 496 int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask);
497 497 void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
498 498 int pci_assign_resource(struct pci_dev *dev, int i);
  499 +int pci_assign_resource_fixed(struct pci_dev *dev, int i);
499 500 void pci_restore_bars(struct pci_dev *dev);
500 501  
501 502 /* ROM control related routines */