2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* drivers/pci/setup-bus.c
|
|
|
|
*
|
|
|
|
* Extruded from code written by
|
|
|
|
* Dave Rusling (david.rusling@reo.mts.dec.com)
|
|
|
|
* David Mosberger (davidm@cs.arizona.edu)
|
|
|
|
* David Miller (davem@redhat.com)
|
|
|
|
*
|
|
|
|
* Support routines for initializing a PCI subsystem.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
|
|
|
|
* PCI-PCI bridges cleanup, sorted resource allocation.
|
|
|
|
* Feb 2002, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
|
|
|
|
* Converted to allocation in 3 passes, which gives
|
|
|
|
* tighter packing. Prefetchable range support.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/pci.h>
|
|
|
|
#include <linux/errno.h>
|
|
|
|
#include <linux/ioport.h>
|
|
|
|
#include <linux/cache.h>
|
|
|
|
#include <linux/slab.h>
|
2016-08-17 08:00:34 +00:00
|
|
|
#include <linux/acpi.h>
|
2009-08-28 20:00:06 +00:00
|
|
|
#include "pci.h"
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-02-24 03:18:59 +00:00
|
|
|
unsigned int pci_flags;
|
2012-02-23 21:29:23 +00:00
|
|
|
|
2012-01-21 10:08:27 +00:00
|
|
|
struct pci_dev_resource {
|
|
|
|
struct list_head list;
|
2012-01-21 10:08:26 +00:00
|
|
|
struct resource *res;
|
|
|
|
struct pci_dev *dev;
|
2010-01-22 09:02:21 +00:00
|
|
|
resource_size_t start;
|
|
|
|
resource_size_t end;
|
2011-02-15 01:43:20 +00:00
|
|
|
resource_size_t add_size;
|
2011-07-25 20:08:39 +00:00
|
|
|
resource_size_t min_align;
|
2010-01-22 09:02:21 +00:00
|
|
|
unsigned long flags;
|
|
|
|
};
|
|
|
|
|
2012-01-21 10:08:30 +00:00
|
|
|
static void free_list(struct list_head *head)
|
|
|
|
{
|
|
|
|
struct pci_dev_resource *dev_res, *tmp;
|
|
|
|
|
|
|
|
list_for_each_entry_safe(dev_res, tmp, head, list) {
|
|
|
|
list_del(&dev_res->list);
|
|
|
|
kfree(dev_res);
|
|
|
|
}
|
|
|
|
}
|
2011-02-15 01:43:18 +00:00
|
|
|
|
2011-02-15 01:43:20 +00:00
|
|
|
/**
|
|
|
|
* add_to_list() - add a new resource tracker to the list
|
|
|
|
* @head: Head of the list
|
|
|
|
* @dev: device corresponding to which the resource
|
|
|
|
* belongs
|
|
|
|
* @res: The resource to be tracked
|
|
|
|
* @add_size: additional size to be optionally added
|
|
|
|
* to the resource
|
|
|
|
*/
|
2012-01-21 10:08:27 +00:00
|
|
|
static int add_to_list(struct list_head *head,
|
2011-02-15 01:43:20 +00:00
|
|
|
struct pci_dev *dev, struct resource *res,
|
2011-07-25 20:08:39 +00:00
|
|
|
resource_size_t add_size, resource_size_t min_align)
|
2010-01-22 09:02:21 +00:00
|
|
|
{
|
2012-01-21 10:08:28 +00:00
|
|
|
struct pci_dev_resource *tmp;
|
2010-01-22 09:02:21 +00:00
|
|
|
|
2012-01-21 10:08:27 +00:00
|
|
|
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
|
2010-01-22 09:02:21 +00:00
|
|
|
if (!tmp) {
|
2014-04-19 00:13:49 +00:00
|
|
|
pr_warn("add_to_list: kmalloc() failed!\n");
|
2012-01-21 10:08:18 +00:00
|
|
|
return -ENOMEM;
|
2010-01-22 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tmp->res = res;
|
|
|
|
tmp->dev = dev;
|
|
|
|
tmp->start = res->start;
|
|
|
|
tmp->end = res->end;
|
|
|
|
tmp->flags = res->flags;
|
2011-02-15 01:43:20 +00:00
|
|
|
tmp->add_size = add_size;
|
2011-07-25 20:08:39 +00:00
|
|
|
tmp->min_align = min_align;
|
2012-01-21 10:08:27 +00:00
|
|
|
|
|
|
|
list_add(&tmp->list, head);
|
2012-01-21 10:08:18 +00:00
|
|
|
|
|
|
|
return 0;
|
2010-01-22 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2012-01-21 10:08:29 +00:00
|
|
|
static void remove_from_list(struct list_head *head,
|
2012-01-21 10:08:20 +00:00
|
|
|
struct resource *res)
|
|
|
|
{
|
2012-01-21 10:08:29 +00:00
|
|
|
struct pci_dev_resource *dev_res, *tmp;
|
2012-01-21 10:08:20 +00:00
|
|
|
|
2012-01-21 10:08:29 +00:00
|
|
|
list_for_each_entry_safe(dev_res, tmp, head, list) {
|
|
|
|
if (dev_res->res == res) {
|
|
|
|
list_del(&dev_res->list);
|
|
|
|
kfree(dev_res);
|
2012-01-21 10:08:27 +00:00
|
|
|
break;
|
2012-01-21 10:08:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-25 08:23:51 +00:00
|
|
|
static struct pci_dev_resource *res_to_dev_res(struct list_head *head,
|
|
|
|
struct resource *res)
|
2012-01-21 10:08:19 +00:00
|
|
|
{
|
2012-01-21 10:08:29 +00:00
|
|
|
struct pci_dev_resource *dev_res;
|
2012-01-21 10:08:27 +00:00
|
|
|
|
2012-01-21 10:08:29 +00:00
|
|
|
list_for_each_entry(dev_res, head, list) {
|
2016-12-29 17:27:52 +00:00
|
|
|
if (dev_res->res == res)
|
2015-03-25 08:23:51 +00:00
|
|
|
return dev_res;
|
2012-01-21 10:08:20 +00:00
|
|
|
}
|
2012-01-21 10:08:19 +00:00
|
|
|
|
2015-03-25 08:23:51 +00:00
|
|
|
return NULL;
|
2012-01-21 10:08:19 +00:00
|
|
|
}
|
|
|
|
|
2015-03-25 08:23:51 +00:00
|
|
|
static resource_size_t get_res_add_size(struct list_head *head,
|
|
|
|
struct resource *res)
|
|
|
|
{
|
|
|
|
struct pci_dev_resource *dev_res;
|
|
|
|
|
|
|
|
dev_res = res_to_dev_res(head, res);
|
|
|
|
return dev_res ? dev_res->add_size : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static resource_size_t get_res_add_align(struct list_head *head,
|
|
|
|
struct resource *res)
|
|
|
|
{
|
|
|
|
struct pci_dev_resource *dev_res;
|
|
|
|
|
|
|
|
dev_res = res_to_dev_res(head, res);
|
|
|
|
return dev_res ? dev_res->min_align : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-21 10:08:25 +00:00
|
|
|
/* Sort resources by alignment */
|
2012-01-21 10:08:27 +00:00
|
|
|
static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)
|
2012-01-21 10:08:25 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
|
|
|
|
struct resource *r;
|
2012-01-21 10:08:27 +00:00
|
|
|
struct pci_dev_resource *dev_res, *tmp;
|
2012-01-21 10:08:25 +00:00
|
|
|
resource_size_t r_align;
|
2012-01-21 10:08:27 +00:00
|
|
|
struct list_head *n;
|
2012-01-21 10:08:25 +00:00
|
|
|
|
|
|
|
r = &dev->resource[i];
|
|
|
|
|
|
|
|
if (r->flags & IORESOURCE_PCI_FIXED)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!(r->flags) || r->parent)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
r_align = pci_resource_alignment(dev, r);
|
|
|
|
if (!r_align) {
|
|
|
|
dev_warn(&dev->dev, "BAR %d: %pR has bogus alignment\n",
|
|
|
|
i, r);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-01-21 10:08:27 +00:00
|
|
|
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
|
|
|
|
if (!tmp)
|
2014-04-19 00:13:50 +00:00
|
|
|
panic("pdev_sort_resources(): kmalloc() failed!\n");
|
2012-01-21 10:08:27 +00:00
|
|
|
tmp->res = r;
|
|
|
|
tmp->dev = dev;
|
|
|
|
|
|
|
|
/* fallback is smallest one or list is empty*/
|
|
|
|
n = head;
|
|
|
|
list_for_each_entry(dev_res, head, list) {
|
|
|
|
resource_size_t align;
|
|
|
|
|
|
|
|
align = pci_resource_alignment(dev_res->dev,
|
|
|
|
dev_res->res);
|
2012-01-21 10:08:25 +00:00
|
|
|
|
|
|
|
if (r_align > align) {
|
2012-01-21 10:08:27 +00:00
|
|
|
n = &dev_res->list;
|
2012-01-21 10:08:25 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-01-21 10:08:27 +00:00
|
|
|
/* Insert it just before n*/
|
|
|
|
list_add_tail(&tmp->list, n);
|
2012-01-21 10:08:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-22 09:02:25 +00:00
|
|
|
static void __dev_sort_resources(struct pci_dev *dev,
|
2012-01-21 10:08:27 +00:00
|
|
|
struct list_head *head)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2010-01-22 09:02:25 +00:00
|
|
|
u16 class = dev->class >> 8;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2010-01-22 09:02:25 +00:00
|
|
|
/* Don't touch classless devices or host bridges or ioapics. */
|
|
|
|
if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST)
|
|
|
|
return;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2010-01-22 09:02:25 +00:00
|
|
|
/* Don't touch ioapic devices already enabled by firmware */
|
|
|
|
if (class == PCI_CLASS_SYSTEM_PIC) {
|
|
|
|
u16 command;
|
|
|
|
pci_read_config_word(dev, PCI_COMMAND, &command);
|
|
|
|
if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY))
|
|
|
|
return;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2010-01-22 09:02:25 +00:00
|
|
|
pdev_sort_resources(dev, head);
|
|
|
|
}
|
2006-09-12 17:21:44 +00:00
|
|
|
|
2011-02-15 01:43:19 +00:00
|
|
|
static inline void reset_resource(struct resource *res)
|
|
|
|
{
|
|
|
|
res->start = 0;
|
|
|
|
res->end = 0;
|
|
|
|
res->flags = 0;
|
|
|
|
}
|
|
|
|
|
2011-02-15 01:43:20 +00:00
|
|
|
/**
|
2011-07-25 20:08:42 +00:00
|
|
|
* reassign_resources_sorted() - satisfy any additional resource requests
|
2011-02-15 01:43:20 +00:00
|
|
|
*
|
2011-07-25 20:08:42 +00:00
|
|
|
* @realloc_head : head of the list tracking requests requiring additional
|
2011-02-15 01:43:20 +00:00
|
|
|
* resources
|
|
|
|
* @head : head of the list tracking requests with allocated
|
|
|
|
* resources
|
|
|
|
*
|
2011-07-25 20:08:42 +00:00
|
|
|
* Walk through each element of the realloc_head and try to procure
|
2011-02-15 01:43:20 +00:00
|
|
|
* additional resources for the element, provided the element
|
|
|
|
* is in the head list.
|
|
|
|
*/
|
2012-01-21 10:08:27 +00:00
|
|
|
static void reassign_resources_sorted(struct list_head *realloc_head,
|
|
|
|
struct list_head *head)
|
2010-01-22 09:02:25 +00:00
|
|
|
{
|
|
|
|
struct resource *res;
|
2012-01-21 10:08:29 +00:00
|
|
|
struct pci_dev_resource *add_res, *tmp;
|
2012-01-21 10:08:27 +00:00
|
|
|
struct pci_dev_resource *dev_res;
|
2015-03-25 08:23:51 +00:00
|
|
|
resource_size_t add_size, align;
|
2010-01-22 09:02:25 +00:00
|
|
|
int idx;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-01-21 10:08:29 +00:00
|
|
|
list_for_each_entry_safe(add_res, tmp, realloc_head, list) {
|
2012-01-21 10:08:27 +00:00
|
|
|
bool found_match = false;
|
|
|
|
|
2012-01-21 10:08:29 +00:00
|
|
|
res = add_res->res;
|
2011-02-15 01:43:20 +00:00
|
|
|
/* skip resource that has been reset */
|
|
|
|
if (!res->flags)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* skip this resource if not found in head list */
|
2012-01-21 10:08:27 +00:00
|
|
|
list_for_each_entry(dev_res, head, list) {
|
|
|
|
if (dev_res->res == res) {
|
|
|
|
found_match = true;
|
|
|
|
break;
|
|
|
|
}
|
2011-02-15 01:43:20 +00:00
|
|
|
}
|
2012-01-21 10:08:27 +00:00
|
|
|
if (!found_match)/* just skip */
|
|
|
|
continue;
|
2011-02-15 01:43:20 +00:00
|
|
|
|
2012-01-21 10:08:29 +00:00
|
|
|
idx = res - &add_res->dev->resource[0];
|
|
|
|
add_size = add_res->add_size;
|
2015-03-25 08:23:51 +00:00
|
|
|
align = add_res->min_align;
|
2011-07-25 20:08:39 +00:00
|
|
|
if (!resource_size(res)) {
|
2015-03-25 08:23:51 +00:00
|
|
|
res->start = align;
|
2011-07-25 20:08:39 +00:00
|
|
|
res->end = res->start + add_size - 1;
|
2012-01-21 10:08:29 +00:00
|
|
|
if (pci_assign_resource(add_res->dev, idx))
|
2011-02-15 01:43:20 +00:00
|
|
|
reset_resource(res);
|
2011-07-25 20:08:39 +00:00
|
|
|
} else {
|
2012-01-21 10:08:29 +00:00
|
|
|
res->flags |= add_res->flags &
|
2012-01-21 10:08:27 +00:00
|
|
|
(IORESOURCE_STARTALIGN|IORESOURCE_SIZEALIGN);
|
2012-01-21 10:08:29 +00:00
|
|
|
if (pci_reassign_resource(add_res->dev, idx,
|
2012-01-21 10:08:27 +00:00
|
|
|
add_size, align))
|
2012-01-21 10:08:29 +00:00
|
|
|
dev_printk(KERN_DEBUG, &add_res->dev->dev,
|
2012-01-21 10:08:31 +00:00
|
|
|
"failed to add %llx res[%d]=%pR\n",
|
|
|
|
(unsigned long long)add_size,
|
|
|
|
idx, res);
|
2011-02-15 01:43:20 +00:00
|
|
|
}
|
|
|
|
out:
|
2012-01-21 10:08:29 +00:00
|
|
|
list_del(&add_res->list);
|
|
|
|
kfree(add_res);
|
2011-02-15 01:43:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* assign_requested_resources_sorted() - satisfy resource requests
|
|
|
|
*
|
|
|
|
* @head : head of the list tracking requests for resources
|
2012-06-15 13:15:49 +00:00
|
|
|
* @fail_head : head of the list tracking requests that could
|
2011-02-15 01:43:20 +00:00
|
|
|
* not be allocated
|
|
|
|
*
|
|
|
|
* Satisfy resource requests of each element in the list. Add
|
|
|
|
* requests that could not satisfied to the failed_list.
|
|
|
|
*/
|
2012-01-21 10:08:27 +00:00
|
|
|
static void assign_requested_resources_sorted(struct list_head *head,
|
|
|
|
struct list_head *fail_head)
|
2011-02-15 01:43:20 +00:00
|
|
|
{
|
|
|
|
struct resource *res;
|
2012-01-21 10:08:27 +00:00
|
|
|
struct pci_dev_resource *dev_res;
|
2011-02-15 01:43:20 +00:00
|
|
|
int idx;
|
2010-02-28 23:49:39 +00:00
|
|
|
|
2012-01-21 10:08:27 +00:00
|
|
|
list_for_each_entry(dev_res, head, list) {
|
|
|
|
res = dev_res->res;
|
|
|
|
idx = res - &dev_res->dev->resource[0];
|
|
|
|
if (resource_size(res) &&
|
|
|
|
pci_assign_resource(dev_res->dev, idx)) {
|
2013-01-21 21:20:43 +00:00
|
|
|
if (fail_head) {
|
2010-02-28 23:49:39 +00:00
|
|
|
/*
|
|
|
|
* if the failed res is for ROM BAR, and it will
|
|
|
|
* be enabled later, don't add it to the list
|
|
|
|
*/
|
|
|
|
if (!((idx == PCI_ROM_RESOURCE) &&
|
|
|
|
(!(res->flags & IORESOURCE_ROM_ENABLE))))
|
2012-01-21 10:08:32 +00:00
|
|
|
add_to_list(fail_head,
|
|
|
|
dev_res->dev, res,
|
2013-11-14 18:28:18 +00:00
|
|
|
0 /* don't care */,
|
|
|
|
0 /* don't care */);
|
2010-02-28 23:49:39 +00:00
|
|
|
}
|
2011-02-15 01:43:19 +00:00
|
|
|
reset_resource(res);
|
2005-04-28 07:25:50 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-25 13:31:38 +00:00
|
|
|
static unsigned long pci_fail_res_type_mask(struct list_head *fail_head)
|
|
|
|
{
|
|
|
|
struct pci_dev_resource *fail_res;
|
|
|
|
unsigned long mask = 0;
|
|
|
|
|
|
|
|
/* check failed type */
|
|
|
|
list_for_each_entry(fail_res, fail_head, list)
|
|
|
|
mask |= fail_res->flags;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* one pref failed resource will set IORESOURCE_MEM,
|
|
|
|
* as we can allocate pref in non-pref range.
|
|
|
|
* Will release all assigned non-pref sibling resources
|
|
|
|
* according to that bit.
|
|
|
|
*/
|
|
|
|
return mask & (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool pci_need_to_release(unsigned long mask, struct resource *res)
|
|
|
|
{
|
|
|
|
if (res->flags & IORESOURCE_IO)
|
|
|
|
return !!(mask & IORESOURCE_IO);
|
|
|
|
|
|
|
|
/* check pref at first */
|
|
|
|
if (res->flags & IORESOURCE_PREFETCH) {
|
|
|
|
if (mask & IORESOURCE_PREFETCH)
|
|
|
|
return true;
|
|
|
|
/* count pref if its parent is non-pref */
|
|
|
|
else if ((mask & IORESOURCE_MEM) &&
|
|
|
|
!(res->parent->flags & IORESOURCE_PREFETCH))
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res->flags & IORESOURCE_MEM)
|
|
|
|
return !!(mask & IORESOURCE_MEM);
|
|
|
|
|
|
|
|
return false; /* should not get here */
|
|
|
|
}
|
|
|
|
|
2012-01-21 10:08:27 +00:00
|
|
|
static void __assign_resources_sorted(struct list_head *head,
|
|
|
|
struct list_head *realloc_head,
|
|
|
|
struct list_head *fail_head)
|
2011-02-15 01:43:20 +00:00
|
|
|
{
|
2012-01-21 10:08:20 +00:00
|
|
|
/*
|
|
|
|
* Should not assign requested resources at first.
|
|
|
|
* they could be adjacent, so later reassign can not reallocate
|
|
|
|
* them one by one in parent resource window.
|
2012-07-23 13:39:51 +00:00
|
|
|
* Try to assign requested + add_size at beginning
|
2012-01-21 10:08:20 +00:00
|
|
|
* if could do that, could get out early.
|
|
|
|
* if could not do that, we still try to assign requested at first,
|
|
|
|
* then try to reassign add_size for some resources.
|
2013-07-25 13:31:38 +00:00
|
|
|
*
|
|
|
|
* Separate three resource type checking if we need to release
|
|
|
|
* assigned resource after requested + add_size try.
|
|
|
|
* 1. if there is io port assign fail, will release assigned
|
|
|
|
* io port.
|
|
|
|
* 2. if there is pref mmio assign fail, release assigned
|
|
|
|
* pref mmio.
|
|
|
|
* if assigned pref mmio's parent is non-pref mmio and there
|
|
|
|
* is non-pref mmio assign fail, will release that assigned
|
|
|
|
* pref mmio.
|
|
|
|
* 3. if there is non-pref mmio assign fail or pref mmio
|
|
|
|
* assigned fail, will release assigned non-pref mmio.
|
2012-01-21 10:08:20 +00:00
|
|
|
*/
|
2012-01-21 10:08:27 +00:00
|
|
|
LIST_HEAD(save_head);
|
|
|
|
LIST_HEAD(local_fail_head);
|
2012-01-21 10:08:29 +00:00
|
|
|
struct pci_dev_resource *save_res;
|
2015-03-25 08:23:51 +00:00
|
|
|
struct pci_dev_resource *dev_res, *tmp_res, *dev_res2;
|
2013-07-25 13:31:38 +00:00
|
|
|
unsigned long fail_type;
|
2015-03-25 08:23:51 +00:00
|
|
|
resource_size_t add_align, align;
|
2012-01-21 10:08:20 +00:00
|
|
|
|
|
|
|
/* Check if optional add_size is there */
|
2012-01-21 10:08:27 +00:00
|
|
|
if (!realloc_head || list_empty(realloc_head))
|
2012-01-21 10:08:20 +00:00
|
|
|
goto requested_and_reassign;
|
|
|
|
|
|
|
|
/* Save original start, end, flags etc at first */
|
2012-01-21 10:08:27 +00:00
|
|
|
list_for_each_entry(dev_res, head, list) {
|
|
|
|
if (add_to_list(&save_head, dev_res->dev, dev_res->res, 0, 0)) {
|
2012-01-21 10:08:30 +00:00
|
|
|
free_list(&save_head);
|
2012-01-21 10:08:20 +00:00
|
|
|
goto requested_and_reassign;
|
|
|
|
}
|
2012-01-21 10:08:27 +00:00
|
|
|
}
|
2012-01-21 10:08:20 +00:00
|
|
|
|
|
|
|
/* Update res in head list with add_size in realloc_head list */
|
2015-03-25 08:23:51 +00:00
|
|
|
list_for_each_entry_safe(dev_res, tmp_res, head, list) {
|
2012-01-21 10:08:27 +00:00
|
|
|
dev_res->res->end += get_res_add_size(realloc_head,
|
|
|
|
dev_res->res);
|
2012-01-21 10:08:20 +00:00
|
|
|
|
2015-03-25 08:23:51 +00:00
|
|
|
/*
|
|
|
|
* There are two kinds of additional resources in the list:
|
|
|
|
* 1. bridge resource -- IORESOURCE_STARTALIGN
|
|
|
|
* 2. SR-IOV resource -- IORESOURCE_SIZEALIGN
|
|
|
|
* Here just fix the additional alignment for bridge
|
|
|
|
*/
|
|
|
|
if (!(dev_res->res->flags & IORESOURCE_STARTALIGN))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
add_align = get_res_add_align(realloc_head, dev_res->res);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The "head" list is sorted by the alignment to make sure
|
|
|
|
* resources with bigger alignment will be assigned first.
|
|
|
|
* After we change the alignment of a dev_res in "head" list,
|
|
|
|
* we need to reorder the list by alignment to make it
|
|
|
|
* consistent.
|
|
|
|
*/
|
|
|
|
if (add_align > dev_res->res->start) {
|
2015-05-29 05:40:00 +00:00
|
|
|
resource_size_t r_size = resource_size(dev_res->res);
|
|
|
|
|
2015-03-25 08:23:51 +00:00
|
|
|
dev_res->res->start = add_align;
|
2015-05-29 05:40:00 +00:00
|
|
|
dev_res->res->end = add_align + r_size - 1;
|
2015-03-25 08:23:51 +00:00
|
|
|
|
|
|
|
list_for_each_entry(dev_res2, head, list) {
|
|
|
|
align = pci_resource_alignment(dev_res2->dev,
|
|
|
|
dev_res2->res);
|
2015-05-19 06:24:17 +00:00
|
|
|
if (add_align > align) {
|
2015-03-25 08:23:51 +00:00
|
|
|
list_move_tail(&dev_res->list,
|
|
|
|
&dev_res2->list);
|
2015-05-19 06:24:17 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-03-25 08:23:51 +00:00
|
|
|
}
|
2015-12-27 21:21:11 +00:00
|
|
|
}
|
2015-03-25 08:23:51 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-01-21 10:08:20 +00:00
|
|
|
/* Try updated head list with add_size added */
|
|
|
|
assign_requested_resources_sorted(head, &local_fail_head);
|
|
|
|
|
|
|
|
/* all assigned with add_size ? */
|
2012-01-21 10:08:27 +00:00
|
|
|
if (list_empty(&local_fail_head)) {
|
2012-01-21 10:08:20 +00:00
|
|
|
/* Remove head list from realloc_head list */
|
2012-01-21 10:08:27 +00:00
|
|
|
list_for_each_entry(dev_res, head, list)
|
|
|
|
remove_from_list(realloc_head, dev_res->res);
|
2012-01-21 10:08:30 +00:00
|
|
|
free_list(&save_head);
|
|
|
|
free_list(head);
|
2012-01-21 10:08:20 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-07-25 13:31:38 +00:00
|
|
|
/* check failed type */
|
|
|
|
fail_type = pci_fail_res_type_mask(&local_fail_head);
|
|
|
|
/* remove not need to be released assigned res from head list etc */
|
|
|
|
list_for_each_entry_safe(dev_res, tmp_res, head, list)
|
|
|
|
if (dev_res->res->parent &&
|
|
|
|
!pci_need_to_release(fail_type, dev_res->res)) {
|
|
|
|
/* remove it from realloc_head list */
|
|
|
|
remove_from_list(realloc_head, dev_res->res);
|
|
|
|
remove_from_list(&save_head, dev_res->res);
|
|
|
|
list_del(&dev_res->list);
|
|
|
|
kfree(dev_res);
|
|
|
|
}
|
|
|
|
|
2012-01-21 10:08:30 +00:00
|
|
|
free_list(&local_fail_head);
|
2012-01-21 10:08:20 +00:00
|
|
|
/* Release assigned resource */
|
2012-01-21 10:08:27 +00:00
|
|
|
list_for_each_entry(dev_res, head, list)
|
|
|
|
if (dev_res->res->parent)
|
|
|
|
release_resource(dev_res->res);
|
2012-01-21 10:08:20 +00:00
|
|
|
/* Restore start/end/flags from saved list */
|
2012-01-21 10:08:29 +00:00
|
|
|
list_for_each_entry(save_res, &save_head, list) {
|
|
|
|
struct resource *res = save_res->res;
|
2012-01-21 10:08:20 +00:00
|
|
|
|
2012-01-21 10:08:29 +00:00
|
|
|
res->start = save_res->start;
|
|
|
|
res->end = save_res->end;
|
|
|
|
res->flags = save_res->flags;
|
2012-01-21 10:08:20 +00:00
|
|
|
}
|
2012-01-21 10:08:30 +00:00
|
|
|
free_list(&save_head);
|
2012-01-21 10:08:20 +00:00
|
|
|
|
|
|
|
requested_and_reassign:
|
2011-02-15 01:43:20 +00:00
|
|
|
/* Satisfy the must-have resource requests */
|
|
|
|
assign_requested_resources_sorted(head, fail_head);
|
|
|
|
|
2011-07-25 20:08:41 +00:00
|
|
|
/* Try to satisfy any additional optional resource
|
2011-02-15 01:43:20 +00:00
|
|
|
requests */
|
2011-07-25 20:08:42 +00:00
|
|
|
if (realloc_head)
|
|
|
|
reassign_resources_sorted(realloc_head, head);
|
2012-01-21 10:08:30 +00:00
|
|
|
free_list(head);
|
2011-02-15 01:43:20 +00:00
|
|
|
}
|
|
|
|
|
2010-01-22 09:02:25 +00:00
|
|
|
static void pdev_assign_resources_sorted(struct pci_dev *dev,
|
2012-01-21 10:08:27 +00:00
|
|
|
struct list_head *add_head,
|
|
|
|
struct list_head *fail_head)
|
2010-01-22 09:02:25 +00:00
|
|
|
{
|
2012-01-21 10:08:27 +00:00
|
|
|
LIST_HEAD(head);
|
2010-01-22 09:02:25 +00:00
|
|
|
|
|
|
|
__dev_sort_resources(dev, &head);
|
2012-01-21 10:08:21 +00:00
|
|
|
__assign_resources_sorted(&head, add_head, fail_head);
|
2010-01-22 09:02:25 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pbus_assign_resources_sorted(const struct pci_bus *bus,
|
2012-01-21 10:08:27 +00:00
|
|
|
struct list_head *realloc_head,
|
|
|
|
struct list_head *fail_head)
|
2010-01-22 09:02:25 +00:00
|
|
|
{
|
|
|
|
struct pci_dev *dev;
|
2012-01-21 10:08:27 +00:00
|
|
|
LIST_HEAD(head);
|
2010-01-22 09:02:25 +00:00
|
|
|
|
|
|
|
list_for_each_entry(dev, &bus->devices, bus_list)
|
|
|
|
__dev_sort_resources(dev, &head);
|
|
|
|
|
2011-07-25 20:08:42 +00:00
|
|
|
__assign_resources_sorted(&head, realloc_head, fail_head);
|
2010-01-22 09:02:25 +00:00
|
|
|
}
|
|
|
|
|
2005-09-09 20:03:23 +00:00
|
|
|
void pci_setup_cardbus(struct pci_bus *bus)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
struct pci_dev *bridge = bus->self;
|
2009-10-27 19:26:47 +00:00
|
|
|
struct resource *res;
|
2005-04-16 22:20:36 +00:00
|
|
|
struct pci_bus_region region;
|
|
|
|
|
2012-05-18 01:51:11 +00:00
|
|
|
dev_info(&bridge->dev, "CardBus bridge to %pR\n",
|
|
|
|
&bus->busn_res);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-10-27 19:26:47 +00:00
|
|
|
res = bus->resource[0];
|
PCI: Convert pcibios_resource_to_bus() to take a pci_bus, not a pci_dev
These interfaces:
pcibios_resource_to_bus(struct pci_dev *dev, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_dev *dev, *resource, *bus_region)
took a pci_dev, but they really depend only on the pci_bus. And we want to
use them in resource allocation paths where we have the bus but not a
device, so this patch converts them to take the pci_bus instead of the
pci_dev:
pcibios_resource_to_bus(struct pci_bus *bus, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_bus *bus, *resource, *bus_region)
In fact, with standard PCI-PCI bridges, they only depend on the host
bridge, because that's the only place address translation occurs, but
we aren't going that far yet.
[bhelgaas: changelog]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2013-12-10 06:54:40 +00:00
|
|
|
pcibios_resource_to_bus(bridge->bus, ®ion, res);
|
2009-10-27 19:26:47 +00:00
|
|
|
if (res->flags & IORESOURCE_IO) {
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* The IO resource is allocated a range twice as large as it
|
|
|
|
* would normally need. This allows us to set both IO regs.
|
|
|
|
*/
|
2009-10-27 19:26:47 +00:00
|
|
|
dev_info(&bridge->dev, " bridge window %pR\n", res);
|
2005-04-16 22:20:36 +00:00
|
|
|
pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
|
|
|
|
region.start);
|
|
|
|
pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
|
|
|
|
region.end);
|
|
|
|
}
|
|
|
|
|
2009-10-27 19:26:47 +00:00
|
|
|
res = bus->resource[1];
|
PCI: Convert pcibios_resource_to_bus() to take a pci_bus, not a pci_dev
These interfaces:
pcibios_resource_to_bus(struct pci_dev *dev, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_dev *dev, *resource, *bus_region)
took a pci_dev, but they really depend only on the pci_bus. And we want to
use them in resource allocation paths where we have the bus but not a
device, so this patch converts them to take the pci_bus instead of the
pci_dev:
pcibios_resource_to_bus(struct pci_bus *bus, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_bus *bus, *resource, *bus_region)
In fact, with standard PCI-PCI bridges, they only depend on the host
bridge, because that's the only place address translation occurs, but
we aren't going that far yet.
[bhelgaas: changelog]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2013-12-10 06:54:40 +00:00
|
|
|
pcibios_resource_to_bus(bridge->bus, ®ion, res);
|
2009-10-27 19:26:47 +00:00
|
|
|
if (res->flags & IORESOURCE_IO) {
|
|
|
|
dev_info(&bridge->dev, " bridge window %pR\n", res);
|
2005-04-16 22:20:36 +00:00
|
|
|
pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
|
|
|
|
region.start);
|
|
|
|
pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1,
|
|
|
|
region.end);
|
|
|
|
}
|
|
|
|
|
2009-10-27 19:26:47 +00:00
|
|
|
res = bus->resource[2];
|
PCI: Convert pcibios_resource_to_bus() to take a pci_bus, not a pci_dev
These interfaces:
pcibios_resource_to_bus(struct pci_dev *dev, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_dev *dev, *resource, *bus_region)
took a pci_dev, but they really depend only on the pci_bus. And we want to
use them in resource allocation paths where we have the bus but not a
device, so this patch converts them to take the pci_bus instead of the
pci_dev:
pcibios_resource_to_bus(struct pci_bus *bus, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_bus *bus, *resource, *bus_region)
In fact, with standard PCI-PCI bridges, they only depend on the host
bridge, because that's the only place address translation occurs, but
we aren't going that far yet.
[bhelgaas: changelog]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2013-12-10 06:54:40 +00:00
|
|
|
pcibios_resource_to_bus(bridge->bus, ®ion, res);
|
2009-10-27 19:26:47 +00:00
|
|
|
if (res->flags & IORESOURCE_MEM) {
|
|
|
|
dev_info(&bridge->dev, " bridge window %pR\n", res);
|
2005-04-16 22:20:36 +00:00
|
|
|
pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
|
|
|
|
region.start);
|
|
|
|
pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0,
|
|
|
|
region.end);
|
|
|
|
}
|
|
|
|
|
2009-10-27 19:26:47 +00:00
|
|
|
res = bus->resource[3];
|
PCI: Convert pcibios_resource_to_bus() to take a pci_bus, not a pci_dev
These interfaces:
pcibios_resource_to_bus(struct pci_dev *dev, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_dev *dev, *resource, *bus_region)
took a pci_dev, but they really depend only on the pci_bus. And we want to
use them in resource allocation paths where we have the bus but not a
device, so this patch converts them to take the pci_bus instead of the
pci_dev:
pcibios_resource_to_bus(struct pci_bus *bus, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_bus *bus, *resource, *bus_region)
In fact, with standard PCI-PCI bridges, they only depend on the host
bridge, because that's the only place address translation occurs, but
we aren't going that far yet.
[bhelgaas: changelog]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2013-12-10 06:54:40 +00:00
|
|
|
pcibios_resource_to_bus(bridge->bus, ®ion, res);
|
2009-10-27 19:26:47 +00:00
|
|
|
if (res->flags & IORESOURCE_MEM) {
|
|
|
|
dev_info(&bridge->dev, " bridge window %pR\n", res);
|
2005-04-16 22:20:36 +00:00
|
|
|
pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
|
|
|
|
region.start);
|
|
|
|
pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1,
|
|
|
|
region.end);
|
|
|
|
}
|
|
|
|
}
|
2005-09-09 20:03:23 +00:00
|
|
|
EXPORT_SYMBOL(pci_setup_cardbus);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* Initialize bridges with base/limit values we have collected.
|
|
|
|
PCI-to-PCI Bridge Architecture Specification rev. 1.1 (1998)
|
|
|
|
requires that if there is no I/O ports or memory behind the
|
|
|
|
bridge, corresponding range must be turned off by writing base
|
|
|
|
value greater than limit to the bridge's base/limit registers.
|
|
|
|
|
|
|
|
Note: care must be taken when updating I/O base/limit registers
|
|
|
|
of bridges which support 32-bit I/O. This update requires two
|
|
|
|
config space writes, so it's quite possible that an I/O window of
|
|
|
|
the bridge will have some undesirable address (e.g. 0) after the
|
|
|
|
first write. Ditto 64-bit prefetchable MMIO. */
|
2015-01-15 16:22:31 +00:00
|
|
|
static void pci_setup_bridge_io(struct pci_dev *bridge)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2009-10-27 19:26:47 +00:00
|
|
|
struct resource *res;
|
2005-04-16 22:20:36 +00:00
|
|
|
struct pci_bus_region region;
|
2012-07-09 19:38:57 +00:00
|
|
|
unsigned long io_mask;
|
|
|
|
u8 io_base_lo, io_limit_lo;
|
2013-11-28 00:24:50 +00:00
|
|
|
u16 l;
|
|
|
|
u32 io_upper16;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-07-09 19:38:57 +00:00
|
|
|
io_mask = PCI_IO_RANGE_MASK;
|
|
|
|
if (bridge->io_window_1k)
|
|
|
|
io_mask = PCI_IO_1K_RANGE_MASK;
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Set up the top and bottom of the PCI I/O segment for this bus. */
|
2015-01-15 16:22:31 +00:00
|
|
|
res = &bridge->resource[PCI_BRIDGE_RESOURCES + 0];
|
PCI: Convert pcibios_resource_to_bus() to take a pci_bus, not a pci_dev
These interfaces:
pcibios_resource_to_bus(struct pci_dev *dev, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_dev *dev, *resource, *bus_region)
took a pci_dev, but they really depend only on the pci_bus. And we want to
use them in resource allocation paths where we have the bus but not a
device, so this patch converts them to take the pci_bus instead of the
pci_dev:
pcibios_resource_to_bus(struct pci_bus *bus, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_bus *bus, *resource, *bus_region)
In fact, with standard PCI-PCI bridges, they only depend on the host
bridge, because that's the only place address translation occurs, but
we aren't going that far yet.
[bhelgaas: changelog]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2013-12-10 06:54:40 +00:00
|
|
|
pcibios_resource_to_bus(bridge->bus, ®ion, res);
|
2009-10-27 19:26:47 +00:00
|
|
|
if (res->flags & IORESOURCE_IO) {
|
2013-11-28 00:24:50 +00:00
|
|
|
pci_read_config_word(bridge, PCI_IO_BASE, &l);
|
2012-07-09 19:38:57 +00:00
|
|
|
io_base_lo = (region.start >> 8) & io_mask;
|
|
|
|
io_limit_lo = (region.end >> 8) & io_mask;
|
2013-11-28 00:24:50 +00:00
|
|
|
l = ((u16) io_limit_lo << 8) | io_base_lo;
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Set up upper 16 bits of I/O base/limit. */
|
|
|
|
io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
|
2009-10-27 19:26:47 +00:00
|
|
|
dev_info(&bridge->dev, " bridge window %pR\n", res);
|
2009-12-22 23:02:21 +00:00
|
|
|
} else {
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Clear upper 16 bits of I/O base/limit. */
|
|
|
|
io_upper16 = 0;
|
|
|
|
l = 0x00f0;
|
|
|
|
}
|
|
|
|
/* Temporarily disable the I/O range before updating PCI_IO_BASE. */
|
|
|
|
pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
|
|
|
|
/* Update lower 16 bits of I/O base/limit. */
|
2013-11-28 00:24:50 +00:00
|
|
|
pci_write_config_word(bridge, PCI_IO_BASE, l);
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Update upper 16 bits of I/O base/limit. */
|
|
|
|
pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16);
|
2009-12-22 23:02:21 +00:00
|
|
|
}
|
|
|
|
|
2015-01-15 16:22:31 +00:00
|
|
|
static void pci_setup_bridge_mmio(struct pci_dev *bridge)
|
2009-12-22 23:02:21 +00:00
|
|
|
{
|
|
|
|
struct resource *res;
|
|
|
|
struct pci_bus_region region;
|
|
|
|
u32 l;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-12-22 23:02:21 +00:00
|
|
|
/* Set up the top and bottom of the PCI Memory segment for this bus. */
|
2015-01-15 16:22:31 +00:00
|
|
|
res = &bridge->resource[PCI_BRIDGE_RESOURCES + 1];
|
PCI: Convert pcibios_resource_to_bus() to take a pci_bus, not a pci_dev
These interfaces:
pcibios_resource_to_bus(struct pci_dev *dev, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_dev *dev, *resource, *bus_region)
took a pci_dev, but they really depend only on the pci_bus. And we want to
use them in resource allocation paths where we have the bus but not a
device, so this patch converts them to take the pci_bus instead of the
pci_dev:
pcibios_resource_to_bus(struct pci_bus *bus, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_bus *bus, *resource, *bus_region)
In fact, with standard PCI-PCI bridges, they only depend on the host
bridge, because that's the only place address translation occurs, but
we aren't going that far yet.
[bhelgaas: changelog]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2013-12-10 06:54:40 +00:00
|
|
|
pcibios_resource_to_bus(bridge->bus, ®ion, res);
|
2009-10-27 19:26:47 +00:00
|
|
|
if (res->flags & IORESOURCE_MEM) {
|
2005-04-16 22:20:36 +00:00
|
|
|
l = (region.start >> 16) & 0xfff0;
|
|
|
|
l |= region.end & 0xfff00000;
|
2009-10-27 19:26:47 +00:00
|
|
|
dev_info(&bridge->dev, " bridge window %pR\n", res);
|
2009-12-22 23:02:21 +00:00
|
|
|
} else {
|
2005-04-16 22:20:36 +00:00
|
|
|
l = 0x0000fff0;
|
|
|
|
}
|
|
|
|
pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
|
2009-12-22 23:02:21 +00:00
|
|
|
}
|
|
|
|
|
2015-01-15 16:22:31 +00:00
|
|
|
static void pci_setup_bridge_mmio_pref(struct pci_dev *bridge)
|
2009-12-22 23:02:21 +00:00
|
|
|
{
|
|
|
|
struct resource *res;
|
|
|
|
struct pci_bus_region region;
|
|
|
|
u32 l, bu, lu;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* Clear out the upper 32 bits of PREF limit.
|
|
|
|
If PCI_PREF_BASE_UPPER32 was non-zero, this temporarily
|
|
|
|
disables PREF range, which is ok. */
|
|
|
|
pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
|
|
|
|
|
|
|
|
/* Set up PREF base/limit. */
|
2007-12-10 06:32:15 +00:00
|
|
|
bu = lu = 0;
|
2015-01-15 16:22:31 +00:00
|
|
|
res = &bridge->resource[PCI_BRIDGE_RESOURCES + 2];
|
PCI: Convert pcibios_resource_to_bus() to take a pci_bus, not a pci_dev
These interfaces:
pcibios_resource_to_bus(struct pci_dev *dev, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_dev *dev, *resource, *bus_region)
took a pci_dev, but they really depend only on the pci_bus. And we want to
use them in resource allocation paths where we have the bus but not a
device, so this patch converts them to take the pci_bus instead of the
pci_dev:
pcibios_resource_to_bus(struct pci_bus *bus, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_bus *bus, *resource, *bus_region)
In fact, with standard PCI-PCI bridges, they only depend on the host
bridge, because that's the only place address translation occurs, but
we aren't going that far yet.
[bhelgaas: changelog]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2013-12-10 06:54:40 +00:00
|
|
|
pcibios_resource_to_bus(bridge->bus, ®ion, res);
|
2009-10-27 19:26:47 +00:00
|
|
|
if (res->flags & IORESOURCE_PREFETCH) {
|
2005-04-16 22:20:36 +00:00
|
|
|
l = (region.start >> 16) & 0xfff0;
|
|
|
|
l |= region.end & 0xfff00000;
|
2009-10-27 19:26:47 +00:00
|
|
|
if (res->flags & IORESOURCE_MEM_64) {
|
2009-04-24 03:48:32 +00:00
|
|
|
bu = upper_32_bits(region.start);
|
|
|
|
lu = upper_32_bits(region.end);
|
|
|
|
}
|
2009-10-27 19:26:47 +00:00
|
|
|
dev_info(&bridge->dev, " bridge window %pR\n", res);
|
2009-12-22 23:02:21 +00:00
|
|
|
} else {
|
2005-04-16 22:20:36 +00:00
|
|
|
l = 0x0000fff0;
|
|
|
|
}
|
|
|
|
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
|
|
|
|
|
2009-11-30 21:51:44 +00:00
|
|
|
/* Set the upper 32 bits of PREF base & limit. */
|
|
|
|
pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
|
|
|
|
pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
|
2009-12-22 23:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type)
|
|
|
|
{
|
|
|
|
struct pci_dev *bridge = bus->self;
|
|
|
|
|
2012-05-18 01:51:11 +00:00
|
|
|
dev_info(&bridge->dev, "PCI bridge to %pR\n",
|
|
|
|
&bus->busn_res);
|
2009-12-22 23:02:21 +00:00
|
|
|
|
|
|
|
if (type & IORESOURCE_IO)
|
2015-01-15 16:22:31 +00:00
|
|
|
pci_setup_bridge_io(bridge);
|
2009-12-22 23:02:21 +00:00
|
|
|
|
|
|
|
if (type & IORESOURCE_MEM)
|
2015-01-15 16:22:31 +00:00
|
|
|
pci_setup_bridge_mmio(bridge);
|
2009-12-22 23:02:21 +00:00
|
|
|
|
|
|
|
if (type & IORESOURCE_PREFETCH)
|
2015-01-15 16:22:31 +00:00
|
|
|
pci_setup_bridge_mmio_pref(bridge);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
|
|
|
|
}
|
|
|
|
|
2016-05-20 06:41:25 +00:00
|
|
|
void __weak pcibios_setup_bridge(struct pci_bus *bus, unsigned long type)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-09-11 17:08:38 +00:00
|
|
|
void pci_setup_bridge(struct pci_bus *bus)
|
2009-12-22 23:02:21 +00:00
|
|
|
{
|
|
|
|
unsigned long type = IORESOURCE_IO | IORESOURCE_MEM |
|
|
|
|
IORESOURCE_PREFETCH;
|
|
|
|
|
2016-05-20 06:41:25 +00:00
|
|
|
pcibios_setup_bridge(bus, type);
|
2009-12-22 23:02:21 +00:00
|
|
|
__pci_setup_bridge(bus, type);
|
|
|
|
}
|
|
|
|
|
PCI: Add pci_claim_bridge_resource() to clip window if necessary
Add pci_claim_bridge_resource() to claim a PCI-PCI bridge window. This is
like regular pci_claim_resource(), except that if we fail to claim the
window, we check to see if we can reduce the size of the window and try
again.
This is for scenarios like this:
pci_bus 0000:00: root bus resource [mem 0xc0000000-0xffffffff]
pci 0000:00:01.0: bridge window [mem 0xbdf00000-0xddefffff 64bit pref]
pci 0000:01:00.0: reg 0x10: [mem 0xc0000000-0xcfffffff pref]
The 00:01.0 window is illegal: it starts before the host bridge window, so
we have to assume the [0xbdf00000-0xbfffffff] region is inaccessible. We
can make it legal by clipping it to [mem 0xc0000000-0xddefffff 64bit pref].
Previously we discarded the 00:01.0 window and tried to reassign that part
of the hierarchy from scratch. That is a problem because Linux doesn't
always assign things optimally. For example, in this case, BIOS put the
01:00.0 device in a prefetchable window below 4GB, but after 5b28541552ef,
Linux puts the prefetchable window above 4GB where the 32-bit 01:00.0
device can't use it.
Clipping the 00:01.0 window is less intrusive than completely reassigning
things and is sufficient to let us use most of the BIOS configuration. Of
course, it's possible that devices below 00:01.0 will no longer fit. If
that's the case, we'll have to reassign things. But that's a separate
problem.
[bhelgaas: changelog, split into separate patch]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=85491
Reported-by: Marek Kordik <kordikmarek@gmail.com>
Fixes: 5b28541552ef ("PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources")
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
CC: stable@vger.kernel.org # v3.16+
2015-01-15 22:21:49 +00:00
|
|
|
|
|
|
|
int pci_claim_bridge_resource(struct pci_dev *bridge, int i)
|
|
|
|
{
|
|
|
|
if (i < PCI_BRIDGE_RESOURCES || i > PCI_BRIDGE_RESOURCE_END)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (pci_claim_resource(bridge, i) == 0)
|
|
|
|
return 0; /* claimed the window */
|
|
|
|
|
|
|
|
if ((bridge->class >> 8) != PCI_CLASS_BRIDGE_PCI)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!pci_bus_clip_resource(bridge, i))
|
|
|
|
return -EINVAL; /* clipping didn't change anything */
|
|
|
|
|
|
|
|
switch (i - PCI_BRIDGE_RESOURCES) {
|
|
|
|
case 0:
|
|
|
|
pci_setup_bridge_io(bridge);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
pci_setup_bridge_mmio(bridge);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
pci_setup_bridge_mmio_pref(bridge);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pci_claim_resource(bridge, i) == 0)
|
|
|
|
return 0; /* claimed a smaller window */
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Check whether the bridge supports optional I/O and
|
|
|
|
prefetchable memory ranges. If not, the respective
|
|
|
|
base/limit registers must be read-only and read as 0. */
|
2007-03-27 05:53:30 +00:00
|
|
|
static void pci_bridge_check_ranges(struct pci_bus *bus)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
u16 io;
|
|
|
|
u32 pmem;
|
|
|
|
struct pci_dev *bridge = bus->self;
|
|
|
|
struct resource *b_res;
|
|
|
|
|
|
|
|
b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
|
|
|
|
b_res[1].flags |= IORESOURCE_MEM;
|
|
|
|
|
|
|
|
pci_read_config_word(bridge, PCI_IO_BASE, &io);
|
|
|
|
if (!io) {
|
PCI: Prevent bus conflicts while checking for bridge apertures
pci_bridge_check_ranges() determines whether the bridge supports an I/O
aperture and a prefetchable memory aperture.
Previously, if the I/O aperture was unsupported, disabled, or configured at
[io 0x0000-0x0fff], we wrote 0xf0 to PCI_IO_BASE and PCI_IO_LIMIT, which,
if the bridge supports it, enables the I/O aperture at [io 0xf000-0xffff].
The enabled aperture may conflict with other devices in the system.
Similarly, we wrote 0xfff0 to PCI_PREF_MEMORY_BASE and
PCI_PREF_MEMORY_LIMIT, which enables the prefetchable memory aperture at
[mem 0xfff00000-0xffffffff], and that may also conflict with other devices.
All we need to know is whether the base and limit registers are writable,
so we can use values that leave the apertures disabled, e.g., PCI_IO_BASE =
0xf0, PCI_IO_LIMIT = 0xe0, PCI_PREF_MEMORY_BASE = 0xfff0,
PCI_PREF_MEMORY_LIMIT = 0xffe0.
Writing non-zero values to both the base and limit registers means we
detect whether either or both are writable, as we did before.
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Based-on-patch-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2013-11-27 22:31:07 +00:00
|
|
|
pci_write_config_word(bridge, PCI_IO_BASE, 0xe0f0);
|
2005-04-16 22:20:36 +00:00
|
|
|
pci_read_config_word(bridge, PCI_IO_BASE, &io);
|
2013-11-14 18:28:18 +00:00
|
|
|
pci_write_config_word(bridge, PCI_IO_BASE, 0x0);
|
|
|
|
}
|
|
|
|
if (io)
|
2005-04-16 22:20:36 +00:00
|
|
|
b_res[0].flags |= IORESOURCE_IO;
|
PCI: Prevent bus conflicts while checking for bridge apertures
pci_bridge_check_ranges() determines whether the bridge supports an I/O
aperture and a prefetchable memory aperture.
Previously, if the I/O aperture was unsupported, disabled, or configured at
[io 0x0000-0x0fff], we wrote 0xf0 to PCI_IO_BASE and PCI_IO_LIMIT, which,
if the bridge supports it, enables the I/O aperture at [io 0xf000-0xffff].
The enabled aperture may conflict with other devices in the system.
Similarly, we wrote 0xfff0 to PCI_PREF_MEMORY_BASE and
PCI_PREF_MEMORY_LIMIT, which enables the prefetchable memory aperture at
[mem 0xfff00000-0xffffffff], and that may also conflict with other devices.
All we need to know is whether the base and limit registers are writable,
so we can use values that leave the apertures disabled, e.g., PCI_IO_BASE =
0xf0, PCI_IO_LIMIT = 0xe0, PCI_PREF_MEMORY_BASE = 0xfff0,
PCI_PREF_MEMORY_LIMIT = 0xffe0.
Writing non-zero values to both the base and limit registers means we
detect whether either or both are writable, as we did before.
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Based-on-patch-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2013-11-27 22:31:07 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* DECchip 21050 pass 2 errata: the bridge may miss an address
|
|
|
|
disconnect boundary by one PCI data phase.
|
|
|
|
Workaround: do not use prefetching on this device. */
|
|
|
|
if (bridge->vendor == PCI_VENDOR_ID_DEC && bridge->device == 0x0001)
|
|
|
|
return;
|
PCI: Prevent bus conflicts while checking for bridge apertures
pci_bridge_check_ranges() determines whether the bridge supports an I/O
aperture and a prefetchable memory aperture.
Previously, if the I/O aperture was unsupported, disabled, or configured at
[io 0x0000-0x0fff], we wrote 0xf0 to PCI_IO_BASE and PCI_IO_LIMIT, which,
if the bridge supports it, enables the I/O aperture at [io 0xf000-0xffff].
The enabled aperture may conflict with other devices in the system.
Similarly, we wrote 0xfff0 to PCI_PREF_MEMORY_BASE and
PCI_PREF_MEMORY_LIMIT, which enables the prefetchable memory aperture at
[mem 0xfff00000-0xffffffff], and that may also conflict with other devices.
All we need to know is whether the base and limit registers are writable,
so we can use values that leave the apertures disabled, e.g., PCI_IO_BASE =
0xf0, PCI_IO_LIMIT = 0xe0, PCI_PREF_MEMORY_BASE = 0xfff0,
PCI_PREF_MEMORY_LIMIT = 0xffe0.
Writing non-zero values to both the base and limit registers means we
detect whether either or both are writable, as we did before.
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Based-on-patch-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2013-11-27 22:31:07 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
|
|
|
|
if (!pmem) {
|
|
|
|
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE,
|
PCI: Prevent bus conflicts while checking for bridge apertures
pci_bridge_check_ranges() determines whether the bridge supports an I/O
aperture and a prefetchable memory aperture.
Previously, if the I/O aperture was unsupported, disabled, or configured at
[io 0x0000-0x0fff], we wrote 0xf0 to PCI_IO_BASE and PCI_IO_LIMIT, which,
if the bridge supports it, enables the I/O aperture at [io 0xf000-0xffff].
The enabled aperture may conflict with other devices in the system.
Similarly, we wrote 0xfff0 to PCI_PREF_MEMORY_BASE and
PCI_PREF_MEMORY_LIMIT, which enables the prefetchable memory aperture at
[mem 0xfff00000-0xffffffff], and that may also conflict with other devices.
All we need to know is whether the base and limit registers are writable,
so we can use values that leave the apertures disabled, e.g., PCI_IO_BASE =
0xf0, PCI_IO_LIMIT = 0xe0, PCI_PREF_MEMORY_BASE = 0xfff0,
PCI_PREF_MEMORY_LIMIT = 0xffe0.
Writing non-zero values to both the base and limit registers means we
detect whether either or both are writable, as we did before.
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Based-on-patch-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2013-11-27 22:31:07 +00:00
|
|
|
0xffe0fff0);
|
2005-04-16 22:20:36 +00:00
|
|
|
pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
|
|
|
|
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0);
|
|
|
|
}
|
2009-04-24 03:48:32 +00:00
|
|
|
if (pmem) {
|
2005-04-16 22:20:36 +00:00
|
|
|
b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
|
2010-01-22 09:02:28 +00:00
|
|
|
if ((pmem & PCI_PREF_RANGE_TYPE_MASK) ==
|
|
|
|
PCI_PREF_RANGE_TYPE_64) {
|
2009-04-24 03:48:32 +00:00
|
|
|
b_res[2].flags |= IORESOURCE_MEM_64;
|
2010-01-22 09:02:28 +00:00
|
|
|
b_res[2].flags |= PCI_PREF_RANGE_TYPE_64;
|
|
|
|
}
|
2009-04-24 03:48:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* double check if bridge does support 64 bit pref */
|
|
|
|
if (b_res[2].flags & IORESOURCE_MEM_64) {
|
|
|
|
u32 mem_base_hi, tmp;
|
|
|
|
pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32,
|
|
|
|
&mem_base_hi);
|
|
|
|
pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32,
|
|
|
|
0xffffffff);
|
|
|
|
pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &tmp);
|
|
|
|
if (!tmp)
|
|
|
|
b_res[2].flags &= ~IORESOURCE_MEM_64;
|
|
|
|
pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32,
|
|
|
|
mem_base_hi);
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Helper function for sizing routines: find first available
|
|
|
|
bus resource of a given type. Note: we intentionally skip
|
|
|
|
the bus resources which have already been assigned (that is,
|
|
|
|
have non-NULL parent resource). */
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
static struct resource *find_free_bus_resource(struct pci_bus *bus,
|
|
|
|
unsigned long type_mask, unsigned long type)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct resource *r;
|
|
|
|
|
2010-02-23 17:24:31 +00:00
|
|
|
pci_bus_for_each_resource(bus, r, i) {
|
2005-06-15 14:59:27 +00:00
|
|
|
if (r == &ioport_resource || r == &iomem_resource)
|
|
|
|
continue;
|
2009-10-27 16:39:18 +00:00
|
|
|
if (r && (r->flags & type_mask) == type && !r->parent)
|
|
|
|
return r;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-02-15 01:43:17 +00:00
|
|
|
static resource_size_t calculate_iosize(resource_size_t size,
|
|
|
|
resource_size_t min_size,
|
|
|
|
resource_size_t size1,
|
|
|
|
resource_size_t old_size,
|
|
|
|
resource_size_t align)
|
|
|
|
{
|
|
|
|
if (size < min_size)
|
|
|
|
size = min_size;
|
2014-04-19 00:13:49 +00:00
|
|
|
if (old_size == 1)
|
2011-02-15 01:43:17 +00:00
|
|
|
old_size = 0;
|
|
|
|
/* To be fixed in 2.5: we should have sort of HAVE_ISA
|
|
|
|
flag in the struct pci_bus. */
|
|
|
|
#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
|
|
|
|
size = (size & 0xff) + ((size & ~0xffUL) << 2);
|
|
|
|
#endif
|
|
|
|
size = ALIGN(size + size1, align);
|
|
|
|
if (size < old_size)
|
|
|
|
size = old_size;
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
static resource_size_t calculate_memsize(resource_size_t size,
|
|
|
|
resource_size_t min_size,
|
|
|
|
resource_size_t size1,
|
|
|
|
resource_size_t old_size,
|
|
|
|
resource_size_t align)
|
|
|
|
{
|
|
|
|
if (size < min_size)
|
|
|
|
size = min_size;
|
2014-04-19 00:13:49 +00:00
|
|
|
if (old_size == 1)
|
2011-02-15 01:43:17 +00:00
|
|
|
old_size = 0;
|
|
|
|
if (size < old_size)
|
|
|
|
size = old_size;
|
|
|
|
size = ALIGN(size + size1, align);
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2012-09-11 22:59:45 +00:00
|
|
|
resource_size_t __weak pcibios_window_alignment(struct pci_bus *bus,
|
|
|
|
unsigned long type)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define PCI_P2P_DEFAULT_MEM_ALIGN 0x100000 /* 1MiB */
|
|
|
|
#define PCI_P2P_DEFAULT_IO_ALIGN 0x1000 /* 4KiB */
|
|
|
|
#define PCI_P2P_DEFAULT_IO_ALIGN_1K 0x400 /* 1KiB */
|
|
|
|
|
|
|
|
static resource_size_t window_alignment(struct pci_bus *bus,
|
|
|
|
unsigned long type)
|
|
|
|
{
|
|
|
|
resource_size_t align = 1, arch_align;
|
|
|
|
|
|
|
|
if (type & IORESOURCE_MEM)
|
|
|
|
align = PCI_P2P_DEFAULT_MEM_ALIGN;
|
|
|
|
else if (type & IORESOURCE_IO) {
|
|
|
|
/*
|
|
|
|
* Per spec, I/O windows are 4K-aligned, but some
|
|
|
|
* bridges have an extension to support 1K alignment.
|
|
|
|
*/
|
|
|
|
if (bus->self->io_window_1k)
|
|
|
|
align = PCI_P2P_DEFAULT_IO_ALIGN_1K;
|
|
|
|
else
|
|
|
|
align = PCI_P2P_DEFAULT_IO_ALIGN;
|
|
|
|
}
|
|
|
|
|
|
|
|
arch_align = pcibios_window_alignment(bus, type);
|
|
|
|
return max(align, arch_align);
|
|
|
|
}
|
|
|
|
|
2011-02-15 01:43:20 +00:00
|
|
|
/**
|
|
|
|
* pbus_size_io() - size the io window of a given bus
|
|
|
|
*
|
|
|
|
* @bus : the bus
|
|
|
|
* @min_size : the minimum io window that must to be allocated
|
|
|
|
* @add_size : additional optional io window
|
2011-07-25 20:08:42 +00:00
|
|
|
* @realloc_head : track the additional io window on this list
|
2011-02-15 01:43:20 +00:00
|
|
|
*
|
|
|
|
* Sizing the IO windows of the PCI-PCI bridge is trivial,
|
2012-07-10 01:55:29 +00:00
|
|
|
* since these windows have 1K or 4K granularity and the IO ranges
|
2011-02-15 01:43:20 +00:00
|
|
|
* of non-bridge PCI devices are limited to 256 bytes.
|
|
|
|
* We must be careful with the ISA aliasing though.
|
|
|
|
*/
|
|
|
|
static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
2012-01-21 10:08:27 +00:00
|
|
|
resource_size_t add_size, struct list_head *realloc_head)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
struct pci_dev *dev;
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO,
|
|
|
|
IORESOURCE_IO);
|
2013-08-02 09:31:05 +00:00
|
|
|
resource_size_t size = 0, size0 = 0, size1 = 0;
|
2011-07-25 20:08:38 +00:00
|
|
|
resource_size_t children_add_size = 0;
|
2013-08-05 22:15:10 +00:00
|
|
|
resource_size_t min_align, align;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (!b_res)
|
2013-11-14 18:28:18 +00:00
|
|
|
return;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2013-08-05 22:15:10 +00:00
|
|
|
min_align = window_alignment(bus, IORESOURCE_IO);
|
2005-04-16 22:20:36 +00:00
|
|
|
list_for_each_entry(dev, &bus->devices, bus_list) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
|
|
|
|
struct resource *r = &dev->resource[i];
|
|
|
|
unsigned long r_size;
|
|
|
|
|
|
|
|
if (r->parent || !(r->flags & IORESOURCE_IO))
|
|
|
|
continue;
|
2008-10-13 11:24:28 +00:00
|
|
|
r_size = resource_size(r);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (r_size < 0x400)
|
|
|
|
/* Might be re-aligned for ISA */
|
|
|
|
size += r_size;
|
|
|
|
else
|
|
|
|
size1 += r_size;
|
2011-07-25 20:08:38 +00:00
|
|
|
|
2012-07-10 01:55:29 +00:00
|
|
|
align = pci_resource_alignment(dev, r);
|
|
|
|
if (align > min_align)
|
|
|
|
min_align = align;
|
|
|
|
|
2011-07-25 20:08:42 +00:00
|
|
|
if (realloc_head)
|
|
|
|
children_add_size += get_res_add_size(realloc_head, r);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
2012-07-10 01:55:29 +00:00
|
|
|
|
2011-02-15 01:43:20 +00:00
|
|
|
size0 = calculate_iosize(size, min_size, size1,
|
2012-07-10 01:55:29 +00:00
|
|
|
resource_size(b_res), min_align);
|
2011-07-25 20:08:38 +00:00
|
|
|
if (children_add_size > add_size)
|
|
|
|
add_size = children_add_size;
|
2011-07-25 20:08:42 +00:00
|
|
|
size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
|
2012-01-21 10:08:17 +00:00
|
|
|
calculate_iosize(size, min_size, add_size + size1,
|
2012-07-10 01:55:29 +00:00
|
|
|
resource_size(b_res), min_align);
|
2011-02-15 01:43:20 +00:00
|
|
|
if (!size0 && !size1) {
|
2009-11-04 17:32:57 +00:00
|
|
|
if (b_res->start || b_res->end)
|
2014-04-19 00:13:50 +00:00
|
|
|
dev_info(&bus->self->dev, "disabling bridge window %pR to %pR (unused)\n",
|
|
|
|
b_res, &bus->busn_res);
|
2005-04-16 22:20:36 +00:00
|
|
|
b_res->flags = 0;
|
|
|
|
return;
|
|
|
|
}
|
2012-07-10 01:55:29 +00:00
|
|
|
|
|
|
|
b_res->start = min_align;
|
2011-02-15 01:43:20 +00:00
|
|
|
b_res->end = b_res->start + size0 - 1;
|
PCI: clean up resource alignment management
Done per Linus' request and suggestions. Linus has explained that
better than I'll be able to explain:
On Thu, Mar 27, 2008 at 10:12:10AM -0700, Linus Torvalds wrote:
> Actually, before we go any further, there might be a less intrusive
> alternative: add just a couple of flags to the resource flags field (we
> still have something like 8 unused bits on 32-bit), and use those to
> implement a generic "resource_alignment()" routine.
>
> Two flags would do it:
>
> - IORESOURCE_SIZEALIGN: size indicates alignment (regular PCI device
> resources)
>
> - IORESOURCE_STARTALIGN: start field is alignment (PCI bus resources
> during probing)
>
> and then the case of both flags zero (or both bits set) would actually be
> "invalid", and we would also clear the IORESOURCE_STARTALIGN flag when we
> actually allocate the resource (so that we don't use the "start" field as
> alignment incorrectly when it no longer indicates alignment).
>
> That wouldn't be totally generic, but it would have the nice property of
> automatically at least add sanity checking for that whole "res->start has
> the odd meaning of 'alignment' during probing" and remove the need for a
> new field, and it would allow us to have a generic "resource_alignment()"
> routine that just gets a resource pointer.
Besides, I removed IORESOURCE_BUS_HAS_VGA flag which was unused for ages.
Signed-off-by: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Gary Hade <garyhade@us.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2008-03-30 15:50:14 +00:00
|
|
|
b_res->flags |= IORESOURCE_STARTALIGN;
|
2012-01-21 10:08:31 +00:00
|
|
|
if (size1 > size0 && realloc_head) {
|
2012-07-10 01:55:29 +00:00
|
|
|
add_to_list(realloc_head, bus->self, b_res, size1-size0,
|
|
|
|
min_align);
|
2014-04-19 00:13:50 +00:00
|
|
|
dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window %pR to %pR add_size %llx\n",
|
|
|
|
b_res, &bus->busn_res,
|
|
|
|
(unsigned long long)size1-size0);
|
2012-01-21 10:08:31 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2012-09-11 22:59:46 +00:00
|
|
|
static inline resource_size_t calculate_mem_align(resource_size_t *aligns,
|
|
|
|
int max_order)
|
|
|
|
{
|
|
|
|
resource_size_t align = 0;
|
|
|
|
resource_size_t min_align = 0;
|
|
|
|
int order;
|
|
|
|
|
|
|
|
for (order = 0; order <= max_order; order++) {
|
|
|
|
resource_size_t align1 = 1;
|
|
|
|
|
|
|
|
align1 <<= (order + 20);
|
|
|
|
|
|
|
|
if (!align)
|
|
|
|
min_align = align1;
|
|
|
|
else if (ALIGN(align + min_align, min_align) < align1)
|
|
|
|
min_align = align1 >> 1;
|
|
|
|
align += aligns[order];
|
|
|
|
}
|
|
|
|
|
|
|
|
return min_align;
|
|
|
|
}
|
|
|
|
|
2011-02-15 01:43:20 +00:00
|
|
|
/**
|
|
|
|
* pbus_size_mem() - size the memory window of a given bus
|
|
|
|
*
|
|
|
|
* @bus : the bus
|
2013-08-02 09:31:04 +00:00
|
|
|
* @mask: mask the resource flag, then compare it with type
|
|
|
|
* @type: the type of free resource from bridge
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
* @type2: second match type
|
|
|
|
* @type3: third match type
|
2011-02-15 01:43:20 +00:00
|
|
|
* @min_size : the minimum memory window that must to be allocated
|
|
|
|
* @add_size : additional optional memory window
|
2011-07-25 20:08:42 +00:00
|
|
|
* @realloc_head : track the additional memory window on this list
|
2011-02-15 01:43:20 +00:00
|
|
|
*
|
|
|
|
* Calculate the size of the bus and minimal alignment which
|
|
|
|
* guarantees that all child resources fit in this size.
|
2014-05-20 00:28:37 +00:00
|
|
|
*
|
|
|
|
* Returns -ENOSPC if there's no available bus resource of the desired type.
|
|
|
|
* Otherwise, sets the bus resource start/end to indicate the required
|
|
|
|
* size, adds things to realloc_head (if supplied), and returns 0.
|
2011-02-15 01:43:20 +00:00
|
|
|
*/
|
2009-09-09 21:09:24 +00:00
|
|
|
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
unsigned long type, unsigned long type2,
|
|
|
|
unsigned long type3,
|
|
|
|
resource_size_t min_size, resource_size_t add_size,
|
|
|
|
struct list_head *realloc_head)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
struct pci_dev *dev;
|
2011-02-15 01:43:20 +00:00
|
|
|
resource_size_t min_align, align, size, size0, size1;
|
2014-07-03 20:46:17 +00:00
|
|
|
resource_size_t aligns[18]; /* Alignments from 1Mb to 128Gb */
|
2005-04-16 22:20:36 +00:00
|
|
|
int order, max_order;
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
struct resource *b_res = find_free_bus_resource(bus,
|
|
|
|
mask | IORESOURCE_PREFETCH, type);
|
2011-07-25 20:08:38 +00:00
|
|
|
resource_size_t children_add_size = 0;
|
2015-03-25 08:23:51 +00:00
|
|
|
resource_size_t children_add_align = 0;
|
|
|
|
resource_size_t add_align = 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (!b_res)
|
2014-05-20 00:28:37 +00:00
|
|
|
return -ENOSPC;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
memset(aligns, 0, sizeof(aligns));
|
|
|
|
max_order = 0;
|
|
|
|
size = 0;
|
|
|
|
|
|
|
|
list_for_each_entry(dev, &bus->devices, bus_list) {
|
|
|
|
int i;
|
2009-04-24 03:48:32 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
|
|
|
|
struct resource *r = &dev->resource[i];
|
2007-12-10 06:32:15 +00:00
|
|
|
resource_size_t r_size;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2015-10-29 22:35:39 +00:00
|
|
|
if (r->parent || (r->flags & IORESOURCE_PCI_FIXED) ||
|
|
|
|
((r->flags & mask) != type &&
|
|
|
|
(r->flags & mask) != type2 &&
|
|
|
|
(r->flags & mask) != type3))
|
2005-04-16 22:20:36 +00:00
|
|
|
continue;
|
2008-10-13 11:24:28 +00:00
|
|
|
r_size = resource_size(r);
|
2011-07-25 20:08:40 +00:00
|
|
|
#ifdef CONFIG_PCI_IOV
|
|
|
|
/* put SRIOV requested res to the optional list */
|
2011-07-25 20:08:42 +00:00
|
|
|
if (realloc_head && i >= PCI_IOV_RESOURCES &&
|
2011-07-25 20:08:40 +00:00
|
|
|
i <= PCI_IOV_RESOURCE_END) {
|
2015-03-25 08:23:51 +00:00
|
|
|
add_align = max(pci_resource_alignment(dev, r), add_align);
|
2011-07-25 20:08:40 +00:00
|
|
|
r->end = r->start - 1;
|
2013-11-14 18:28:18 +00:00
|
|
|
add_to_list(realloc_head, dev, r, r_size, 0/* don't care */);
|
2011-07-25 20:08:40 +00:00
|
|
|
children_add_size += r_size;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
2014-05-19 13:03:14 +00:00
|
|
|
/*
|
|
|
|
* aligns[0] is for 1MB (since bridge memory
|
|
|
|
* windows are always at least 1MB aligned), so
|
|
|
|
* keep "order" from being negative for smaller
|
|
|
|
* resources.
|
|
|
|
*/
|
2009-08-28 20:00:06 +00:00
|
|
|
align = pci_resource_alignment(dev, r);
|
2005-04-16 22:20:36 +00:00
|
|
|
order = __ffs(align) - 20;
|
2014-05-19 13:03:14 +00:00
|
|
|
if (order < 0)
|
|
|
|
order = 0;
|
|
|
|
if (order >= ARRAY_SIZE(aligns)) {
|
2014-04-19 00:13:50 +00:00
|
|
|
dev_warn(&dev->dev, "disabling BAR %d: %pR (bad alignment %#llx)\n",
|
|
|
|
i, r, (unsigned long long) align);
|
2005-04-16 22:20:36 +00:00
|
|
|
r->flags = 0;
|
|
|
|
continue;
|
|
|
|
}
|
2017-04-10 11:58:11 +00:00
|
|
|
size += max(r_size, align);
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Exclude ranges with size > align from
|
|
|
|
calculation of the alignment. */
|
2017-04-10 11:58:11 +00:00
|
|
|
if (r_size <= align)
|
2005-04-16 22:20:36 +00:00
|
|
|
aligns[order] += align;
|
|
|
|
if (order > max_order)
|
|
|
|
max_order = order;
|
2011-07-25 20:08:38 +00:00
|
|
|
|
2015-03-25 08:23:51 +00:00
|
|
|
if (realloc_head) {
|
2011-07-25 20:08:42 +00:00
|
|
|
children_add_size += get_res_add_size(realloc_head, r);
|
2015-03-25 08:23:51 +00:00
|
|
|
children_add_align = get_res_add_align(realloc_head, r);
|
|
|
|
add_align = max(add_align, children_add_align);
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
2012-09-11 22:59:46 +00:00
|
|
|
|
2012-09-11 22:59:46 +00:00
|
|
|
min_align = calculate_mem_align(aligns, max_order);
|
2013-09-06 01:45:58 +00:00
|
|
|
min_align = max(min_align, window_alignment(bus, b_res->flags));
|
2011-04-11 17:53:11 +00:00
|
|
|
size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
|
2015-03-25 08:23:51 +00:00
|
|
|
add_align = max(min_align, add_align);
|
2011-07-25 20:08:38 +00:00
|
|
|
if (children_add_size > add_size)
|
|
|
|
add_size = children_add_size;
|
2011-07-25 20:08:42 +00:00
|
|
|
size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
|
2012-01-21 10:08:17 +00:00
|
|
|
calculate_memsize(size, min_size, add_size,
|
2015-03-25 08:23:51 +00:00
|
|
|
resource_size(b_res), add_align);
|
2011-02-15 01:43:20 +00:00
|
|
|
if (!size0 && !size1) {
|
2009-11-04 17:32:57 +00:00
|
|
|
if (b_res->start || b_res->end)
|
2014-04-19 00:13:50 +00:00
|
|
|
dev_info(&bus->self->dev, "disabling bridge window %pR to %pR (unused)\n",
|
|
|
|
b_res, &bus->busn_res);
|
2005-04-16 22:20:36 +00:00
|
|
|
b_res->flags = 0;
|
2014-05-20 00:28:37 +00:00
|
|
|
return 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
b_res->start = min_align;
|
2011-02-15 01:43:20 +00:00
|
|
|
b_res->end = size0 + min_align - 1;
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
b_res->flags |= IORESOURCE_STARTALIGN;
|
2012-01-21 10:08:31 +00:00
|
|
|
if (size1 > size0 && realloc_head) {
|
2015-03-25 08:23:51 +00:00
|
|
|
add_to_list(realloc_head, bus->self, b_res, size1-size0, add_align);
|
|
|
|
dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window %pR to %pR add_size %llx add_align %llx\n",
|
2014-04-19 00:13:50 +00:00
|
|
|
b_res, &bus->busn_res,
|
2015-03-25 08:23:51 +00:00
|
|
|
(unsigned long long) (size1 - size0),
|
|
|
|
(unsigned long long) add_align);
|
2012-01-21 10:08:31 +00:00
|
|
|
}
|
2014-05-20 00:28:37 +00:00
|
|
|
return 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2011-07-25 20:08:41 +00:00
|
|
|
unsigned long pci_cardbus_resource_alignment(struct resource *res)
|
|
|
|
{
|
|
|
|
if (res->flags & IORESOURCE_IO)
|
|
|
|
return pci_cardbus_io_size;
|
|
|
|
if (res->flags & IORESOURCE_MEM)
|
|
|
|
return pci_cardbus_mem_size;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pci_bus_size_cardbus(struct pci_bus *bus,
|
2012-01-21 10:08:27 +00:00
|
|
|
struct list_head *realloc_head)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
struct pci_dev *bridge = bus->self;
|
|
|
|
struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
|
2012-02-10 23:33:47 +00:00
|
|
|
resource_size_t b_res_3_size = pci_cardbus_mem_size * 2;
|
2005-04-16 22:20:36 +00:00
|
|
|
u16 ctrl;
|
|
|
|
|
2012-02-10 23:33:48 +00:00
|
|
|
if (b_res[0].parent)
|
|
|
|
goto handle_b_res_1;
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Reserve some resources for CardBus. We reserve
|
|
|
|
* a fixed amount of bus space for CardBus bridges.
|
|
|
|
*/
|
2012-02-10 23:33:47 +00:00
|
|
|
b_res[0].start = pci_cardbus_io_size;
|
|
|
|
b_res[0].end = b_res[0].start + pci_cardbus_io_size - 1;
|
|
|
|
b_res[0].flags |= IORESOURCE_IO | IORESOURCE_STARTALIGN;
|
|
|
|
if (realloc_head) {
|
|
|
|
b_res[0].end -= pci_cardbus_io_size;
|
|
|
|
add_to_list(realloc_head, bridge, b_res, pci_cardbus_io_size,
|
|
|
|
pci_cardbus_io_size);
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-02-10 23:33:48 +00:00
|
|
|
handle_b_res_1:
|
|
|
|
if (b_res[1].parent)
|
|
|
|
goto handle_b_res_2;
|
2012-02-10 23:33:47 +00:00
|
|
|
b_res[1].start = pci_cardbus_io_size;
|
|
|
|
b_res[1].end = b_res[1].start + pci_cardbus_io_size - 1;
|
|
|
|
b_res[1].flags |= IORESOURCE_IO | IORESOURCE_STARTALIGN;
|
|
|
|
if (realloc_head) {
|
|
|
|
b_res[1].end -= pci_cardbus_io_size;
|
|
|
|
add_to_list(realloc_head, bridge, b_res+1, pci_cardbus_io_size,
|
|
|
|
pci_cardbus_io_size);
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-02-10 23:33:48 +00:00
|
|
|
handle_b_res_2:
|
2012-02-10 23:33:46 +00:00
|
|
|
/* MEM1 must not be pref mmio */
|
|
|
|
pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
|
|
|
|
if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM1) {
|
|
|
|
ctrl &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM1;
|
|
|
|
pci_write_config_word(bridge, PCI_CB_BRIDGE_CONTROL, ctrl);
|
|
|
|
pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Check whether prefetchable memory is supported
|
|
|
|
* by this bridge.
|
|
|
|
*/
|
|
|
|
pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
|
|
|
|
if (!(ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0)) {
|
|
|
|
ctrl |= PCI_CB_BRIDGE_CTL_PREFETCH_MEM0;
|
|
|
|
pci_write_config_word(bridge, PCI_CB_BRIDGE_CONTROL, ctrl);
|
|
|
|
pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
|
|
|
|
}
|
|
|
|
|
2012-02-10 23:33:48 +00:00
|
|
|
if (b_res[2].parent)
|
|
|
|
goto handle_b_res_3;
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* If we have prefetchable memory support, allocate
|
|
|
|
* two regions. Otherwise, allocate one region of
|
|
|
|
* twice the size.
|
|
|
|
*/
|
|
|
|
if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
|
2012-02-10 23:33:47 +00:00
|
|
|
b_res[2].start = pci_cardbus_mem_size;
|
|
|
|
b_res[2].end = b_res[2].start + pci_cardbus_mem_size - 1;
|
|
|
|
b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH |
|
|
|
|
IORESOURCE_STARTALIGN;
|
|
|
|
if (realloc_head) {
|
|
|
|
b_res[2].end -= pci_cardbus_mem_size;
|
|
|
|
add_to_list(realloc_head, bridge, b_res+2,
|
|
|
|
pci_cardbus_mem_size, pci_cardbus_mem_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reduce that to half */
|
|
|
|
b_res_3_size = pci_cardbus_mem_size;
|
|
|
|
}
|
|
|
|
|
2012-02-10 23:33:48 +00:00
|
|
|
handle_b_res_3:
|
|
|
|
if (b_res[3].parent)
|
|
|
|
goto handle_done;
|
2012-02-10 23:33:47 +00:00
|
|
|
b_res[3].start = pci_cardbus_mem_size;
|
|
|
|
b_res[3].end = b_res[3].start + b_res_3_size - 1;
|
|
|
|
b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_STARTALIGN;
|
|
|
|
if (realloc_head) {
|
|
|
|
b_res[3].end -= b_res_3_size;
|
|
|
|
add_to_list(realloc_head, bridge, b_res+3, b_res_3_size,
|
|
|
|
pci_cardbus_mem_size);
|
|
|
|
}
|
2012-02-10 23:33:48 +00:00
|
|
|
|
|
|
|
handle_done:
|
|
|
|
;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2014-04-14 22:11:40 +00:00
|
|
|
void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
struct pci_dev *dev;
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
unsigned long mask, prefmask, type2 = 0, type3 = 0;
|
2011-02-15 01:43:20 +00:00
|
|
|
resource_size_t additional_mem_size = 0, additional_io_size = 0;
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
struct resource *b_res;
|
2014-05-20 00:28:37 +00:00
|
|
|
int ret;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
list_for_each_entry(dev, &bus->devices, bus_list) {
|
|
|
|
struct pci_bus *b = dev->subordinate;
|
|
|
|
if (!b)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (dev->class >> 8) {
|
|
|
|
case PCI_CLASS_BRIDGE_CARDBUS:
|
2011-07-25 20:08:42 +00:00
|
|
|
pci_bus_size_cardbus(b, realloc_head);
|
2005-04-16 22:20:36 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PCI_CLASS_BRIDGE_PCI:
|
|
|
|
default:
|
2011-07-25 20:08:42 +00:00
|
|
|
__pci_bus_size_bridges(b, realloc_head);
|
2005-04-16 22:20:36 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The root bus? */
|
2013-09-06 01:45:56 +00:00
|
|
|
if (pci_is_root_bus(bus))
|
2005-04-16 22:20:36 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
switch (bus->self->class >> 8) {
|
|
|
|
case PCI_CLASS_BRIDGE_CARDBUS:
|
|
|
|
/* don't size cardbuses yet. */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PCI_CLASS_BRIDGE_PCI:
|
|
|
|
pci_bridge_check_ranges(bus);
|
2009-09-09 21:09:24 +00:00
|
|
|
if (bus->self->is_hotplug_bridge) {
|
2011-02-15 01:43:20 +00:00
|
|
|
additional_io_size = pci_hotplug_io_size;
|
|
|
|
additional_mem_size = pci_hotplug_mem_size;
|
2009-09-09 21:09:24 +00:00
|
|
|
}
|
2014-05-20 00:32:18 +00:00
|
|
|
/* Fall through */
|
2005-04-16 22:20:36 +00:00
|
|
|
default:
|
2012-01-21 10:08:24 +00:00
|
|
|
pbus_size_io(bus, realloc_head ? 0 : additional_io_size,
|
|
|
|
additional_io_size, realloc_head);
|
2014-05-20 00:32:18 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If there's a 64-bit prefetchable MMIO window, compute
|
|
|
|
* the size required to put all 64-bit prefetchable
|
|
|
|
* resources in it.
|
|
|
|
*/
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
b_res = &bus->self->resource[PCI_BRIDGE_RESOURCES];
|
2005-04-16 22:20:36 +00:00
|
|
|
mask = IORESOURCE_MEM;
|
|
|
|
prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
if (b_res[2].flags & IORESOURCE_MEM_64) {
|
|
|
|
prefmask |= IORESOURCE_MEM_64;
|
2014-05-20 00:28:37 +00:00
|
|
|
ret = pbus_size_mem(bus, prefmask, prefmask,
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
prefmask, prefmask,
|
2012-01-21 10:08:24 +00:00
|
|
|
realloc_head ? 0 : additional_mem_size,
|
2014-05-20 00:28:37 +00:00
|
|
|
additional_mem_size, realloc_head);
|
2014-05-20 00:32:18 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If successful, all non-prefetchable resources
|
|
|
|
* and any 32-bit prefetchable resources will go in
|
|
|
|
* the non-prefetchable window.
|
|
|
|
*/
|
2014-05-20 00:28:37 +00:00
|
|
|
if (ret == 0) {
|
|
|
|
mask = prefmask;
|
|
|
|
type2 = prefmask & ~IORESOURCE_MEM_64;
|
|
|
|
type3 = prefmask & ~IORESOURCE_PREFETCH;
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
}
|
|
|
|
}
|
2014-05-20 00:32:18 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If there is no 64-bit prefetchable window, compute the
|
|
|
|
* size required to put all prefetchable resources in the
|
|
|
|
* 32-bit prefetchable window (if there is one).
|
|
|
|
*/
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
if (!type2) {
|
|
|
|
prefmask &= ~IORESOURCE_MEM_64;
|
2014-05-20 00:28:37 +00:00
|
|
|
ret = pbus_size_mem(bus, prefmask, prefmask,
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
prefmask, prefmask,
|
|
|
|
realloc_head ? 0 : additional_mem_size,
|
2014-05-20 00:28:37 +00:00
|
|
|
additional_mem_size, realloc_head);
|
2014-05-20 00:32:18 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If successful, only non-prefetchable resources
|
|
|
|
* will go in the non-prefetchable window.
|
|
|
|
*/
|
|
|
|
if (ret == 0)
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
mask = prefmask;
|
2014-05-20 00:32:18 +00:00
|
|
|
else
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
additional_mem_size += additional_mem_size;
|
2014-05-20 00:32:18 +00:00
|
|
|
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
type2 = type3 = IORESOURCE_MEM;
|
|
|
|
}
|
2014-05-20 00:32:18 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Compute the size required to put everything else in the
|
|
|
|
* non-prefetchable window. This includes:
|
|
|
|
*
|
|
|
|
* - all non-prefetchable resources
|
|
|
|
* - 32-bit prefetchable resources if there's a 64-bit
|
|
|
|
* prefetchable window or no prefetchable window at all
|
|
|
|
* - 64-bit prefetchable resources if there's no
|
|
|
|
* prefetchable window at all
|
|
|
|
*
|
|
|
|
* Note that the strategy in __pci_assign_resource() must
|
|
|
|
* match that used here. Specifically, we cannot put a
|
|
|
|
* 32-bit prefetchable resource in a 64-bit prefetchable
|
|
|
|
* window.
|
|
|
|
*/
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
pbus_size_mem(bus, mask, IORESOURCE_MEM, type2, type3,
|
2012-01-21 10:08:24 +00:00
|
|
|
realloc_head ? 0 : additional_mem_size,
|
|
|
|
additional_mem_size, realloc_head);
|
2005-04-16 22:20:36 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-02-15 01:43:20 +00:00
|
|
|
|
2014-04-14 22:11:40 +00:00
|
|
|
void pci_bus_size_bridges(struct pci_bus *bus)
|
2011-02-15 01:43:20 +00:00
|
|
|
{
|
|
|
|
__pci_bus_size_bridges(bus, NULL);
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
EXPORT_SYMBOL(pci_bus_size_bridges);
|
|
|
|
|
2015-10-29 22:35:39 +00:00
|
|
|
static void assign_fixed_resource_on_bus(struct pci_bus *b, struct resource *r)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct resource *parent_r;
|
|
|
|
unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM |
|
|
|
|
IORESOURCE_PREFETCH;
|
|
|
|
|
|
|
|
pci_bus_for_each_resource(b, parent_r, i) {
|
|
|
|
if (!parent_r)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ((r->flags & mask) == (parent_r->flags & mask) &&
|
|
|
|
resource_contains(parent_r, r))
|
|
|
|
request_resource(parent_r, r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Try to assign any resources marked as IORESOURCE_PCI_FIXED, as they
|
|
|
|
* are skipped by pbus_assign_resources_sorted().
|
|
|
|
*/
|
|
|
|
static void pdev_assign_fixed_resources(struct pci_dev *dev)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
|
|
|
|
struct pci_bus *b;
|
|
|
|
struct resource *r = &dev->resource[i];
|
|
|
|
|
|
|
|
if (r->parent || !(r->flags & IORESOURCE_PCI_FIXED) ||
|
|
|
|
!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
b = dev->bus;
|
|
|
|
while (b && !r->parent) {
|
|
|
|
assign_fixed_resource_on_bus(b, r);
|
|
|
|
b = b->parent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-14 22:11:40 +00:00
|
|
|
void __pci_bus_assign_resources(const struct pci_bus *bus,
|
|
|
|
struct list_head *realloc_head,
|
|
|
|
struct list_head *fail_head)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
struct pci_bus *b;
|
|
|
|
struct pci_dev *dev;
|
|
|
|
|
2011-07-25 20:08:42 +00:00
|
|
|
pbus_assign_resources_sorted(bus, realloc_head, fail_head);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
list_for_each_entry(dev, &bus->devices, bus_list) {
|
2015-10-29 22:35:39 +00:00
|
|
|
pdev_assign_fixed_resources(dev);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
b = dev->subordinate;
|
|
|
|
if (!b)
|
|
|
|
continue;
|
|
|
|
|
2011-07-25 20:08:42 +00:00
|
|
|
__pci_bus_assign_resources(b, realloc_head, fail_head);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
switch (dev->class >> 8) {
|
|
|
|
case PCI_CLASS_BRIDGE_PCI:
|
2010-01-22 09:02:25 +00:00
|
|
|
if (!pci_is_enabled(dev))
|
|
|
|
pci_setup_bridge(b);
|
2005-04-16 22:20:36 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PCI_CLASS_BRIDGE_CARDBUS:
|
|
|
|
pci_setup_cardbus(b);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2014-04-19 00:13:50 +00:00
|
|
|
dev_info(&dev->dev, "not setting up bridge for bus %04x:%02x\n",
|
|
|
|
pci_domain_nr(b), b->number);
|
2005-04-16 22:20:36 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-01-22 09:02:21 +00:00
|
|
|
|
2014-04-14 22:11:40 +00:00
|
|
|
void pci_bus_assign_resources(const struct pci_bus *bus)
|
2010-01-22 09:02:21 +00:00
|
|
|
{
|
2011-02-15 01:43:20 +00:00
|
|
|
__pci_bus_assign_resources(bus, NULL, NULL);
|
2010-01-22 09:02:21 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
EXPORT_SYMBOL(pci_bus_assign_resources);
|
|
|
|
|
2016-06-08 11:04:47 +00:00
|
|
|
static void pci_claim_device_resources(struct pci_dev *dev)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {
|
|
|
|
struct resource *r = &dev->resource[i];
|
|
|
|
|
|
|
|
if (!r->flags || r->parent)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
pci_claim_resource(dev, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pci_claim_bridge_resources(struct pci_dev *dev)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) {
|
|
|
|
struct resource *r = &dev->resource[i];
|
|
|
|
|
|
|
|
if (!r->flags || r->parent)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
pci_claim_bridge_resource(dev, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pci_bus_allocate_dev_resources(struct pci_bus *b)
|
|
|
|
{
|
|
|
|
struct pci_dev *dev;
|
|
|
|
struct pci_bus *child;
|
|
|
|
|
|
|
|
list_for_each_entry(dev, &b->devices, bus_list) {
|
|
|
|
pci_claim_device_resources(dev);
|
|
|
|
|
|
|
|
child = dev->subordinate;
|
|
|
|
if (child)
|
|
|
|
pci_bus_allocate_dev_resources(child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pci_bus_allocate_resources(struct pci_bus *b)
|
|
|
|
{
|
|
|
|
struct pci_bus *child;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Carry out a depth-first search on the PCI bus
|
|
|
|
* tree to allocate bridge apertures. Read the
|
|
|
|
* programmed bridge bases and recursively claim
|
|
|
|
* the respective bridge resources.
|
|
|
|
*/
|
|
|
|
if (b->self) {
|
|
|
|
pci_read_bridge_bases(b);
|
|
|
|
pci_claim_bridge_resources(b->self);
|
|
|
|
}
|
|
|
|
|
|
|
|
list_for_each_entry(child, &b->children, node)
|
|
|
|
pci_bus_allocate_resources(child);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pci_bus_claim_resources(struct pci_bus *b)
|
|
|
|
{
|
|
|
|
pci_bus_allocate_resources(b);
|
|
|
|
pci_bus_allocate_dev_resources(b);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(pci_bus_claim_resources);
|
|
|
|
|
2014-04-14 22:11:40 +00:00
|
|
|
static void __pci_bridge_assign_resources(const struct pci_dev *bridge,
|
|
|
|
struct list_head *add_head,
|
|
|
|
struct list_head *fail_head)
|
2010-01-22 09:02:25 +00:00
|
|
|
{
|
|
|
|
struct pci_bus *b;
|
|
|
|
|
2012-01-21 10:08:21 +00:00
|
|
|
pdev_assign_resources_sorted((struct pci_dev *)bridge,
|
|
|
|
add_head, fail_head);
|
2010-01-22 09:02:25 +00:00
|
|
|
|
|
|
|
b = bridge->subordinate;
|
|
|
|
if (!b)
|
|
|
|
return;
|
|
|
|
|
2012-01-21 10:08:21 +00:00
|
|
|
__pci_bus_assign_resources(b, add_head, fail_head);
|
2010-01-22 09:02:25 +00:00
|
|
|
|
|
|
|
switch (bridge->class >> 8) {
|
|
|
|
case PCI_CLASS_BRIDGE_PCI:
|
|
|
|
pci_setup_bridge(b);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PCI_CLASS_BRIDGE_CARDBUS:
|
|
|
|
pci_setup_cardbus(b);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2014-04-19 00:13:50 +00:00
|
|
|
dev_info(&bridge->dev, "not setting up bridge for bus %04x:%02x\n",
|
|
|
|
pci_domain_nr(b), b->number);
|
2010-01-22 09:02:25 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-10-18 13:58:17 +00:00
|
|
|
|
|
|
|
#define PCI_RES_TYPE_MASK \
|
|
|
|
(IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH |\
|
|
|
|
IORESOURCE_MEM_64)
|
|
|
|
|
2010-01-22 09:02:20 +00:00
|
|
|
static void pci_bridge_release_resources(struct pci_bus *bus,
|
|
|
|
unsigned long type)
|
|
|
|
{
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
struct pci_dev *dev = bus->self;
|
2010-01-22 09:02:20 +00:00
|
|
|
struct resource *r;
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
unsigned old_flags = 0;
|
|
|
|
struct resource *b_res;
|
|
|
|
int idx = 1;
|
2010-01-22 09:02:20 +00:00
|
|
|
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
b_res = &dev->resource[PCI_BRIDGE_RESOURCES];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 1. if there is io port assign fail, will release bridge
|
|
|
|
* io port.
|
|
|
|
* 2. if there is non pref mmio assign fail, release bridge
|
|
|
|
* nonpref mmio.
|
|
|
|
* 3. if there is 64bit pref mmio assign fail, and bridge pref
|
|
|
|
* is 64bit, release bridge pref mmio.
|
|
|
|
* 4. if there is pref mmio assign fail, and bridge pref is
|
|
|
|
* 32bit mmio, release bridge pref mmio
|
|
|
|
* 5. if there is pref mmio assign fail, and bridge pref is not
|
|
|
|
* assigned, release bridge nonpref mmio.
|
|
|
|
*/
|
|
|
|
if (type & IORESOURCE_IO)
|
|
|
|
idx = 0;
|
|
|
|
else if (!(type & IORESOURCE_PREFETCH))
|
|
|
|
idx = 1;
|
|
|
|
else if ((type & IORESOURCE_MEM_64) &&
|
|
|
|
(b_res[2].flags & IORESOURCE_MEM_64))
|
|
|
|
idx = 2;
|
|
|
|
else if (!(b_res[2].flags & IORESOURCE_MEM_64) &&
|
|
|
|
(b_res[2].flags & IORESOURCE_PREFETCH))
|
|
|
|
idx = 2;
|
|
|
|
else
|
|
|
|
idx = 1;
|
|
|
|
|
|
|
|
r = &b_res[idx];
|
|
|
|
|
|
|
|
if (!r->parent)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if there are children under that, we should release them
|
|
|
|
* all
|
|
|
|
*/
|
|
|
|
release_child_resources(r);
|
|
|
|
if (!release_resource(r)) {
|
2017-10-18 13:58:17 +00:00
|
|
|
type = old_flags = r->flags & PCI_RES_TYPE_MASK;
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
dev_printk(KERN_DEBUG, &dev->dev, "resource %d %pR released\n",
|
|
|
|
PCI_BRIDGE_RESOURCES + idx, r);
|
|
|
|
/* keep the old size */
|
|
|
|
r->end = resource_size(r) - 1;
|
|
|
|
r->start = 0;
|
|
|
|
r->flags = 0;
|
2010-01-22 09:02:20 +00:00
|
|
|
|
|
|
|
/* avoiding touch the one without PREF */
|
|
|
|
if (type & IORESOURCE_PREFETCH)
|
|
|
|
type = IORESOURCE_PREFETCH;
|
|
|
|
__pci_setup_bridge(bus, type);
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-19 23:01:55 +00:00
|
|
|
/* for next child res under same bridge */
|
|
|
|
r->flags = old_flags;
|
2010-01-22 09:02:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
enum release_type {
|
|
|
|
leaf_only,
|
|
|
|
whole_subtree,
|
|
|
|
};
|
|
|
|
/*
|
|
|
|
* try to release pci bridge resources that is from leaf bridge,
|
|
|
|
* so we can allocate big new one later
|
|
|
|
*/
|
2014-04-14 22:11:40 +00:00
|
|
|
static void pci_bus_release_bridge_resources(struct pci_bus *bus,
|
|
|
|
unsigned long type,
|
|
|
|
enum release_type rel_type)
|
2010-01-22 09:02:20 +00:00
|
|
|
{
|
|
|
|
struct pci_dev *dev;
|
|
|
|
bool is_leaf_bridge = true;
|
|
|
|
|
|
|
|
list_for_each_entry(dev, &bus->devices, bus_list) {
|
|
|
|
struct pci_bus *b = dev->subordinate;
|
|
|
|
if (!b)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
is_leaf_bridge = false;
|
|
|
|
|
|
|
|
if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (rel_type == whole_subtree)
|
|
|
|
pci_bus_release_bridge_resources(b, type,
|
|
|
|
whole_subtree);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pci_is_root_bus(bus))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ((bus->self->class >> 8) != PCI_CLASS_BRIDGE_PCI)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ((rel_type == whole_subtree) || is_leaf_bridge)
|
|
|
|
pci_bridge_release_resources(bus, type);
|
|
|
|
}
|
|
|
|
|
2008-06-23 18:33:06 +00:00
|
|
|
static void pci_bus_dump_res(struct pci_bus *bus)
|
|
|
|
{
|
2010-02-23 17:24:31 +00:00
|
|
|
struct resource *res;
|
|
|
|
int i;
|
2009-12-22 23:02:24 +00:00
|
|
|
|
2010-02-23 17:24:31 +00:00
|
|
|
pci_bus_for_each_resource(bus, res, i) {
|
2009-12-22 23:02:24 +00:00
|
|
|
if (!res || !res->end || !res->flags)
|
2014-04-19 00:13:49 +00:00
|
|
|
continue;
|
2008-06-23 18:33:06 +00:00
|
|
|
|
2009-10-27 19:26:47 +00:00
|
|
|
dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR\n", i, res);
|
2014-04-19 00:13:49 +00:00
|
|
|
}
|
2008-06-23 18:33:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void pci_bus_dump_resources(struct pci_bus *bus)
|
|
|
|
{
|
|
|
|
struct pci_bus *b;
|
|
|
|
struct pci_dev *dev;
|
|
|
|
|
|
|
|
|
|
|
|
pci_bus_dump_res(bus);
|
|
|
|
|
|
|
|
list_for_each_entry(dev, &bus->devices, bus_list) {
|
|
|
|
b = dev->subordinate;
|
|
|
|
if (!b)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
pci_bus_dump_resources(b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-24 21:37:13 +00:00
|
|
|
static int pci_bus_get_depth(struct pci_bus *bus)
|
2011-05-13 00:11:37 +00:00
|
|
|
{
|
|
|
|
int depth = 0;
|
2013-08-02 09:31:03 +00:00
|
|
|
struct pci_bus *child_bus;
|
2011-05-13 00:11:37 +00:00
|
|
|
|
2014-04-19 00:13:49 +00:00
|
|
|
list_for_each_entry(child_bus, &bus->children, node) {
|
2011-05-13 00:11:37 +00:00
|
|
|
int ret;
|
|
|
|
|
2013-08-02 09:31:03 +00:00
|
|
|
ret = pci_bus_get_depth(child_bus);
|
2011-05-13 00:11:37 +00:00
|
|
|
if (ret + 1 > depth)
|
|
|
|
depth = ret + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return depth;
|
|
|
|
}
|
|
|
|
|
2012-02-24 03:23:30 +00:00
|
|
|
/*
|
|
|
|
* -1: undefined, will auto detect later
|
|
|
|
* 0: disabled by user
|
|
|
|
* 1: disabled by auto detect
|
|
|
|
* 2: enabled by user
|
|
|
|
* 3: enabled by auto detect
|
|
|
|
*/
|
|
|
|
enum enable_type {
|
|
|
|
undefined = -1,
|
|
|
|
user_disabled,
|
|
|
|
auto_disabled,
|
|
|
|
user_enabled,
|
|
|
|
auto_enabled,
|
|
|
|
};
|
|
|
|
|
2013-07-24 21:37:13 +00:00
|
|
|
static enum enable_type pci_realloc_enable = undefined;
|
2012-02-24 03:23:30 +00:00
|
|
|
void __init pci_realloc_get_opt(char *str)
|
|
|
|
{
|
|
|
|
if (!strncmp(str, "off", 3))
|
|
|
|
pci_realloc_enable = user_disabled;
|
|
|
|
else if (!strncmp(str, "on", 2))
|
|
|
|
pci_realloc_enable = user_enabled;
|
|
|
|
}
|
2013-07-24 21:37:13 +00:00
|
|
|
static bool pci_realloc_enabled(enum enable_type enable)
|
2012-02-24 03:23:30 +00:00
|
|
|
{
|
2013-07-22 21:37:15 +00:00
|
|
|
return enable >= user_enabled;
|
2012-02-24 03:23:30 +00:00
|
|
|
}
|
2011-07-07 18:19:10 +00:00
|
|
|
|
2012-02-24 03:23:32 +00:00
|
|
|
#if defined(CONFIG_PCI_IOV) && defined(CONFIG_PCI_REALLOC_ENABLE_AUTO)
|
2013-07-24 21:37:13 +00:00
|
|
|
static int iov_resources_unassigned(struct pci_dev *dev, void *data)
|
2013-07-22 21:37:13 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
bool *unassigned = data;
|
2012-02-24 03:23:32 +00:00
|
|
|
|
2013-07-22 21:37:13 +00:00
|
|
|
for (i = PCI_IOV_RESOURCES; i <= PCI_IOV_RESOURCE_END; i++) {
|
|
|
|
struct resource *r = &dev->resource[i];
|
2013-07-22 21:37:14 +00:00
|
|
|
struct pci_bus_region region;
|
2012-02-24 03:23:32 +00:00
|
|
|
|
2013-07-22 21:37:13 +00:00
|
|
|
/* Not assigned or rejected by kernel? */
|
2013-07-22 21:37:14 +00:00
|
|
|
if (!r->flags)
|
|
|
|
continue;
|
2012-02-24 03:23:32 +00:00
|
|
|
|
PCI: Convert pcibios_resource_to_bus() to take a pci_bus, not a pci_dev
These interfaces:
pcibios_resource_to_bus(struct pci_dev *dev, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_dev *dev, *resource, *bus_region)
took a pci_dev, but they really depend only on the pci_bus. And we want to
use them in resource allocation paths where we have the bus but not a
device, so this patch converts them to take the pci_bus instead of the
pci_dev:
pcibios_resource_to_bus(struct pci_bus *bus, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_bus *bus, *resource, *bus_region)
In fact, with standard PCI-PCI bridges, they only depend on the host
bridge, because that's the only place address translation occurs, but
we aren't going that far yet.
[bhelgaas: changelog]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2013-12-10 06:54:40 +00:00
|
|
|
pcibios_resource_to_bus(dev->bus, ®ion, r);
|
2013-07-22 21:37:14 +00:00
|
|
|
if (!region.start) {
|
2013-07-22 21:37:13 +00:00
|
|
|
*unassigned = true;
|
|
|
|
return 1; /* return early from pci_walk_bus() */
|
2012-02-24 03:23:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-22 21:37:13 +00:00
|
|
|
return 0;
|
2012-02-24 03:23:32 +00:00
|
|
|
}
|
|
|
|
|
2013-07-24 21:37:13 +00:00
|
|
|
static enum enable_type pci_realloc_detect(struct pci_bus *bus,
|
2013-07-22 21:37:15 +00:00
|
|
|
enum enable_type enable_local)
|
2013-07-22 21:37:13 +00:00
|
|
|
{
|
|
|
|
bool unassigned = false;
|
2012-02-24 03:23:32 +00:00
|
|
|
|
2013-07-22 21:37:15 +00:00
|
|
|
if (enable_local != undefined)
|
|
|
|
return enable_local;
|
2013-07-22 21:37:13 +00:00
|
|
|
|
2013-07-22 21:37:15 +00:00
|
|
|
pci_walk_bus(bus, iov_resources_unassigned, &unassigned);
|
|
|
|
if (unassigned)
|
|
|
|
return auto_enabled;
|
|
|
|
|
|
|
|
return enable_local;
|
2012-02-24 03:23:32 +00:00
|
|
|
}
|
2013-07-22 21:37:13 +00:00
|
|
|
#else
|
2013-07-24 21:37:13 +00:00
|
|
|
static enum enable_type pci_realloc_detect(struct pci_bus *bus,
|
2013-07-22 21:37:15 +00:00
|
|
|
enum enable_type enable_local)
|
|
|
|
{
|
|
|
|
return enable_local;
|
2012-02-24 03:23:32 +00:00
|
|
|
}
|
2013-07-22 21:37:13 +00:00
|
|
|
#endif
|
2012-02-24 03:23:32 +00:00
|
|
|
|
2011-05-13 00:11:37 +00:00
|
|
|
/*
|
|
|
|
* first try will not touch pci bridge res
|
2013-11-14 18:28:18 +00:00
|
|
|
* second and later try will clear small leaf bridge res
|
|
|
|
* will stop till to the max depth if can not find good one
|
2011-05-13 00:11:37 +00:00
|
|
|
*/
|
2013-07-22 21:37:18 +00:00
|
|
|
void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2012-01-21 10:08:27 +00:00
|
|
|
LIST_HEAD(realloc_head); /* list of resources that
|
2011-02-15 01:43:20 +00:00
|
|
|
want additional resources */
|
2012-01-21 10:08:27 +00:00
|
|
|
struct list_head *add_list = NULL;
|
2011-05-13 00:11:37 +00:00
|
|
|
int tried_times = 0;
|
|
|
|
enum release_type rel_type = leaf_only;
|
2012-01-21 10:08:27 +00:00
|
|
|
LIST_HEAD(fail_head);
|
2012-01-21 10:08:29 +00:00
|
|
|
struct pci_dev_resource *fail_res;
|
2012-01-21 10:08:24 +00:00
|
|
|
int pci_try_num = 1;
|
2013-07-22 21:37:16 +00:00
|
|
|
enum enable_type enable_local;
|
2011-05-13 00:11:37 +00:00
|
|
|
|
2012-01-21 10:08:24 +00:00
|
|
|
/* don't realloc if asked to do so */
|
2013-07-22 21:37:16 +00:00
|
|
|
enable_local = pci_realloc_detect(bus, pci_realloc_enable);
|
2013-07-22 21:37:15 +00:00
|
|
|
if (pci_realloc_enabled(enable_local)) {
|
2013-07-22 21:37:16 +00:00
|
|
|
int max_depth = pci_bus_get_depth(bus);
|
2012-01-21 10:08:24 +00:00
|
|
|
|
|
|
|
pci_try_num = max_depth + 1;
|
2013-07-22 21:37:16 +00:00
|
|
|
dev_printk(KERN_DEBUG, &bus->dev,
|
|
|
|
"max bus depth: %d pci_try_num: %d\n",
|
|
|
|
max_depth, pci_try_num);
|
2012-01-21 10:08:24 +00:00
|
|
|
}
|
2011-05-13 00:11:37 +00:00
|
|
|
|
|
|
|
again:
|
2012-01-21 10:08:24 +00:00
|
|
|
/*
|
|
|
|
* last try will use add_list, otherwise will try good to have as
|
|
|
|
* must have, so can realloc parent bridge resource
|
|
|
|
*/
|
|
|
|
if (tried_times + 1 == pci_try_num)
|
2012-01-21 10:08:27 +00:00
|
|
|
add_list = &realloc_head;
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Depth first, calculate sizes and alignments of all
|
|
|
|
subordinate buses. */
|
2013-07-22 21:37:16 +00:00
|
|
|
__pci_bus_size_bridges(bus, add_list);
|
2011-02-15 01:43:20 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Depth last, allocate resources and update the hardware. */
|
2013-07-22 21:37:16 +00:00
|
|
|
__pci_bus_assign_resources(bus, add_list, &fail_head);
|
2012-01-21 10:08:24 +00:00
|
|
|
if (add_list)
|
2012-01-21 10:08:27 +00:00
|
|
|
BUG_ON(!list_empty(add_list));
|
2011-05-13 00:11:37 +00:00
|
|
|
tried_times++;
|
|
|
|
|
|
|
|
/* any device complain? */
|
2012-01-21 10:08:27 +00:00
|
|
|
if (list_empty(&fail_head))
|
2013-07-22 21:37:17 +00:00
|
|
|
goto dump;
|
2011-07-07 18:19:10 +00:00
|
|
|
|
2012-02-24 03:23:29 +00:00
|
|
|
if (tried_times >= pci_try_num) {
|
2013-07-22 21:37:15 +00:00
|
|
|
if (enable_local == undefined)
|
2013-07-22 21:37:16 +00:00
|
|
|
dev_info(&bus->dev, "Some PCI device resources are unassigned, try booting with pci=realloc\n");
|
2013-07-22 21:37:15 +00:00
|
|
|
else if (enable_local == auto_enabled)
|
2013-07-22 21:37:16 +00:00
|
|
|
dev_info(&bus->dev, "Automatically enabled pci realloc, if you have problem, try booting with pci=realloc=off\n");
|
2012-02-24 03:23:31 +00:00
|
|
|
|
2012-01-21 10:08:30 +00:00
|
|
|
free_list(&fail_head);
|
2013-07-22 21:37:17 +00:00
|
|
|
goto dump;
|
2011-05-13 00:11:37 +00:00
|
|
|
}
|
|
|
|
|
2013-07-22 21:37:16 +00:00
|
|
|
dev_printk(KERN_DEBUG, &bus->dev,
|
|
|
|
"No. %d try to assign unassigned res\n", tried_times + 1);
|
2011-05-13 00:11:37 +00:00
|
|
|
|
|
|
|
/* third times and later will not check if it is leaf */
|
|
|
|
if ((tried_times + 1) > 2)
|
|
|
|
rel_type = whole_subtree;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Try to release leaf bridge's resources that doesn't fit resource of
|
|
|
|
* child device under that bridge
|
|
|
|
*/
|
2013-07-22 21:37:12 +00:00
|
|
|
list_for_each_entry(fail_res, &fail_head, list)
|
|
|
|
pci_bus_release_bridge_resources(fail_res->dev->bus,
|
2017-10-18 13:58:17 +00:00
|
|
|
fail_res->flags & PCI_RES_TYPE_MASK,
|
2012-01-21 10:08:27 +00:00
|
|
|
rel_type);
|
2013-07-22 21:37:12 +00:00
|
|
|
|
2011-05-13 00:11:37 +00:00
|
|
|
/* restore size and flags */
|
2012-01-21 10:08:29 +00:00
|
|
|
list_for_each_entry(fail_res, &fail_head, list) {
|
|
|
|
struct resource *res = fail_res->res;
|
2011-05-13 00:11:37 +00:00
|
|
|
|
2012-01-21 10:08:29 +00:00
|
|
|
res->start = fail_res->start;
|
|
|
|
res->end = fail_res->end;
|
|
|
|
res->flags = fail_res->flags;
|
|
|
|
if (fail_res->dev->subordinate)
|
2011-05-13 00:11:37 +00:00
|
|
|
res->flags = 0;
|
|
|
|
}
|
2012-01-21 10:08:30 +00:00
|
|
|
free_list(&fail_head);
|
2011-05-13 00:11:37 +00:00
|
|
|
|
|
|
|
goto again;
|
|
|
|
|
2013-07-22 21:37:17 +00:00
|
|
|
dump:
|
2008-06-23 18:33:06 +00:00
|
|
|
/* dump the resource on buses */
|
2013-07-22 21:37:16 +00:00
|
|
|
pci_bus_dump_resources(bus);
|
|
|
|
}
|
|
|
|
|
|
|
|
void __init pci_assign_unassigned_resources(void)
|
|
|
|
{
|
|
|
|
struct pci_bus *root_bus;
|
|
|
|
|
2016-08-17 08:00:34 +00:00
|
|
|
list_for_each_entry(root_bus, &pci_root_buses, node) {
|
2013-07-22 21:37:16 +00:00
|
|
|
pci_assign_unassigned_root_bus_resources(root_bus);
|
2016-09-10 15:40:45 +00:00
|
|
|
|
|
|
|
/* Make sure the root bridge has a companion ACPI device: */
|
|
|
|
if (ACPI_HANDLE(root_bus->bridge))
|
|
|
|
acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge));
|
2016-08-17 08:00:34 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2010-01-22 09:02:25 +00:00
|
|
|
|
2017-10-13 18:35:45 +00:00
|
|
|
static void extend_bridge_window(struct pci_dev *bridge, struct resource *res,
|
|
|
|
struct list_head *add_list, resource_size_t available)
|
|
|
|
{
|
|
|
|
struct pci_dev_resource *dev_res;
|
|
|
|
|
|
|
|
if (res->parent)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (resource_size(res) >= available)
|
|
|
|
return;
|
|
|
|
|
|
|
|
dev_res = res_to_dev_res(add_list, res);
|
|
|
|
if (!dev_res)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Is there room to extend the window? */
|
|
|
|
if (available - resource_size(res) <= dev_res->add_size)
|
|
|
|
return;
|
|
|
|
|
|
|
|
dev_res->add_size = available - resource_size(res);
|
|
|
|
dev_dbg(&bridge->dev, "bridge window %pR extended by %pa\n", res,
|
|
|
|
&dev_res->add_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pci_bus_distribute_available_resources(struct pci_bus *bus,
|
|
|
|
struct list_head *add_list, resource_size_t available_io,
|
|
|
|
resource_size_t available_mmio, resource_size_t available_mmio_pref)
|
|
|
|
{
|
|
|
|
resource_size_t remaining_io, remaining_mmio, remaining_mmio_pref;
|
|
|
|
unsigned int normal_bridges = 0, hotplug_bridges = 0;
|
|
|
|
struct resource *io_res, *mmio_res, *mmio_pref_res;
|
|
|
|
struct pci_dev *dev, *bridge = bus->self;
|
|
|
|
|
|
|
|
io_res = &bridge->resource[PCI_BRIDGE_RESOURCES + 0];
|
|
|
|
mmio_res = &bridge->resource[PCI_BRIDGE_RESOURCES + 1];
|
|
|
|
mmio_pref_res = &bridge->resource[PCI_BRIDGE_RESOURCES + 2];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update additional resource list (add_list) to fill all the
|
|
|
|
* extra resource space available for this port except the space
|
|
|
|
* calculated in __pci_bus_size_bridges() which covers all the
|
|
|
|
* devices currently connected to the port and below.
|
|
|
|
*/
|
|
|
|
extend_bridge_window(bridge, io_res, add_list, available_io);
|
|
|
|
extend_bridge_window(bridge, mmio_res, add_list, available_mmio);
|
|
|
|
extend_bridge_window(bridge, mmio_pref_res, add_list,
|
|
|
|
available_mmio_pref);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Calculate the total amount of extra resource space we can
|
|
|
|
* pass to bridges below this one. This is basically the
|
|
|
|
* extra space reduced by the minimal required space for the
|
|
|
|
* non-hotplug bridges.
|
|
|
|
*/
|
|
|
|
remaining_io = available_io;
|
|
|
|
remaining_mmio = available_mmio;
|
|
|
|
remaining_mmio_pref = available_mmio_pref;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Calculate how many hotplug bridges and normal bridges there
|
|
|
|
* are on this bus. We will distribute the additional available
|
|
|
|
* resources between hotplug bridges.
|
|
|
|
*/
|
|
|
|
for_each_pci_bridge(dev, bus) {
|
|
|
|
if (dev->is_hotplug_bridge)
|
|
|
|
hotplug_bridges++;
|
|
|
|
else
|
|
|
|
normal_bridges++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for_each_pci_bridge(dev, bus) {
|
|
|
|
const struct resource *res;
|
|
|
|
|
|
|
|
if (dev->is_hotplug_bridge)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reduce the available resource space by what the
|
|
|
|
* bridge and devices below it occupy.
|
|
|
|
*/
|
|
|
|
res = &dev->resource[PCI_BRIDGE_RESOURCES + 0];
|
|
|
|
if (!res->parent && available_io > resource_size(res))
|
|
|
|
remaining_io -= resource_size(res);
|
|
|
|
|
|
|
|
res = &dev->resource[PCI_BRIDGE_RESOURCES + 1];
|
|
|
|
if (!res->parent && available_mmio > resource_size(res))
|
|
|
|
remaining_mmio -= resource_size(res);
|
|
|
|
|
|
|
|
res = &dev->resource[PCI_BRIDGE_RESOURCES + 2];
|
|
|
|
if (!res->parent && available_mmio_pref > resource_size(res))
|
|
|
|
remaining_mmio_pref -= resource_size(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Go over devices on this bus and distribute the remaining
|
|
|
|
* resource space between hotplug bridges.
|
|
|
|
*/
|
|
|
|
for_each_pci_bridge(dev, bus) {
|
|
|
|
struct pci_bus *b;
|
|
|
|
|
|
|
|
b = dev->subordinate;
|
|
|
|
if (!b)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!hotplug_bridges && normal_bridges == 1) {
|
|
|
|
/*
|
|
|
|
* There is only one bridge on the bus (upstream
|
|
|
|
* port) so it gets all available resources
|
|
|
|
* which it can then distribute to the possible
|
|
|
|
* hotplug bridges below.
|
|
|
|
*/
|
|
|
|
pci_bus_distribute_available_resources(b, add_list,
|
|
|
|
available_io, available_mmio,
|
|
|
|
available_mmio_pref);
|
|
|
|
} else if (dev->is_hotplug_bridge) {
|
|
|
|
resource_size_t align, io, mmio, mmio_pref;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Distribute available extra resources equally
|
|
|
|
* between hotplug-capable downstream ports
|
|
|
|
* taking alignment into account.
|
|
|
|
*
|
|
|
|
* Here hotplug_bridges is always != 0.
|
|
|
|
*/
|
|
|
|
align = pci_resource_alignment(bridge, io_res);
|
|
|
|
io = div64_ul(available_io, hotplug_bridges);
|
|
|
|
io = min(ALIGN(io, align), remaining_io);
|
|
|
|
remaining_io -= io;
|
|
|
|
|
|
|
|
align = pci_resource_alignment(bridge, mmio_res);
|
|
|
|
mmio = div64_ul(available_mmio, hotplug_bridges);
|
|
|
|
mmio = min(ALIGN(mmio, align), remaining_mmio);
|
|
|
|
remaining_mmio -= mmio;
|
|
|
|
|
|
|
|
align = pci_resource_alignment(bridge, mmio_pref_res);
|
|
|
|
mmio_pref = div64_ul(available_mmio_pref,
|
|
|
|
hotplug_bridges);
|
|
|
|
mmio_pref = min(ALIGN(mmio_pref, align),
|
|
|
|
remaining_mmio_pref);
|
|
|
|
remaining_mmio_pref -= mmio_pref;
|
|
|
|
|
|
|
|
pci_bus_distribute_available_resources(b, add_list, io,
|
|
|
|
mmio, mmio_pref);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
pci_bridge_distribute_available_resources(struct pci_dev *bridge,
|
|
|
|
struct list_head *add_list)
|
|
|
|
{
|
|
|
|
resource_size_t available_io, available_mmio, available_mmio_pref;
|
|
|
|
const struct resource *res;
|
|
|
|
|
|
|
|
if (!bridge->is_hotplug_bridge)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Take the initial extra resources from the hotplug port */
|
|
|
|
res = &bridge->resource[PCI_BRIDGE_RESOURCES + 0];
|
|
|
|
available_io = resource_size(res);
|
|
|
|
res = &bridge->resource[PCI_BRIDGE_RESOURCES + 1];
|
|
|
|
available_mmio = resource_size(res);
|
|
|
|
res = &bridge->resource[PCI_BRIDGE_RESOURCES + 2];
|
|
|
|
available_mmio_pref = resource_size(res);
|
|
|
|
|
|
|
|
pci_bus_distribute_available_resources(bridge->subordinate,
|
|
|
|
add_list, available_io, available_mmio, available_mmio_pref);
|
|
|
|
}
|
|
|
|
|
2010-01-22 09:02:25 +00:00
|
|
|
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
|
|
|
|
{
|
|
|
|
struct pci_bus *parent = bridge->subordinate;
|
2012-01-21 10:08:27 +00:00
|
|
|
LIST_HEAD(add_list); /* list of resources that
|
2012-01-21 10:08:21 +00:00
|
|
|
want additional resources */
|
2010-01-22 09:02:27 +00:00
|
|
|
int tried_times = 0;
|
2012-01-21 10:08:27 +00:00
|
|
|
LIST_HEAD(fail_head);
|
2012-01-21 10:08:29 +00:00
|
|
|
struct pci_dev_resource *fail_res;
|
2010-01-22 09:02:25 +00:00
|
|
|
int retval;
|
2010-01-22 09:02:27 +00:00
|
|
|
|
|
|
|
again:
|
2012-01-21 10:08:21 +00:00
|
|
|
__pci_bus_size_bridges(parent, &add_list);
|
2017-10-13 18:35:45 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Distribute remaining resources (if any) equally between
|
|
|
|
* hotplug bridges below. This makes it possible to extend the
|
|
|
|
* hierarchy later without running out of resources.
|
|
|
|
*/
|
|
|
|
pci_bridge_distribute_available_resources(bridge, &add_list);
|
|
|
|
|
2012-01-21 10:08:27 +00:00
|
|
|
__pci_bridge_assign_resources(bridge, &add_list, &fail_head);
|
|
|
|
BUG_ON(!list_empty(&add_list));
|
2010-01-22 09:02:27 +00:00
|
|
|
tried_times++;
|
|
|
|
|
2012-01-21 10:08:27 +00:00
|
|
|
if (list_empty(&fail_head))
|
2010-05-21 21:35:06 +00:00
|
|
|
goto enable_all;
|
2010-01-22 09:02:27 +00:00
|
|
|
|
|
|
|
if (tried_times >= 2) {
|
|
|
|
/* still fail, don't need to try more */
|
2012-01-21 10:08:30 +00:00
|
|
|
free_list(&fail_head);
|
2010-05-21 21:35:06 +00:00
|
|
|
goto enable_all;
|
2010-01-22 09:02:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n",
|
|
|
|
tried_times + 1);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Try to release leaf bridge's resources that doesn't fit resource of
|
|
|
|
* child device under that bridge
|
|
|
|
*/
|
2013-07-22 21:37:12 +00:00
|
|
|
list_for_each_entry(fail_res, &fail_head, list)
|
|
|
|
pci_bus_release_bridge_resources(fail_res->dev->bus,
|
2017-10-18 13:58:17 +00:00
|
|
|
fail_res->flags & PCI_RES_TYPE_MASK,
|
2010-01-22 09:02:27 +00:00
|
|
|
whole_subtree);
|
2013-07-22 21:37:12 +00:00
|
|
|
|
2010-01-22 09:02:27 +00:00
|
|
|
/* restore size and flags */
|
2012-01-21 10:08:29 +00:00
|
|
|
list_for_each_entry(fail_res, &fail_head, list) {
|
|
|
|
struct resource *res = fail_res->res;
|
2010-01-22 09:02:27 +00:00
|
|
|
|
2012-01-21 10:08:29 +00:00
|
|
|
res->start = fail_res->start;
|
|
|
|
res->end = fail_res->end;
|
|
|
|
res->flags = fail_res->flags;
|
|
|
|
if (fail_res->dev->subordinate)
|
2010-01-22 09:02:27 +00:00
|
|
|
res->flags = 0;
|
|
|
|
}
|
2012-01-21 10:08:30 +00:00
|
|
|
free_list(&fail_head);
|
2010-01-22 09:02:27 +00:00
|
|
|
|
|
|
|
goto again;
|
2010-05-21 21:35:06 +00:00
|
|
|
|
|
|
|
enable_all:
|
|
|
|
retval = pci_reenable_device(bridge);
|
2013-04-12 17:35:40 +00:00
|
|
|
if (retval)
|
|
|
|
dev_err(&bridge->dev, "Error reenabling bridge (%d)\n", retval);
|
2010-05-21 21:35:06 +00:00
|
|
|
pci_set_master(bridge);
|
2010-01-22 09:02:25 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
|
2012-01-21 10:08:23 +00:00
|
|
|
|
2017-10-24 19:40:26 +00:00
|
|
|
int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
|
|
|
|
{
|
|
|
|
struct pci_dev_resource *dev_res;
|
|
|
|
struct pci_dev *next;
|
|
|
|
LIST_HEAD(saved);
|
|
|
|
LIST_HEAD(added);
|
|
|
|
LIST_HEAD(failed);
|
|
|
|
unsigned int i;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* Walk to the root hub, releasing bridge BARs when possible */
|
|
|
|
next = bridge;
|
|
|
|
do {
|
|
|
|
bridge = next;
|
|
|
|
for (i = PCI_BRIDGE_RESOURCES; i < PCI_BRIDGE_RESOURCE_END;
|
|
|
|
i++) {
|
|
|
|
struct resource *res = &bridge->resource[i];
|
|
|
|
|
|
|
|
if ((res->flags ^ type) & PCI_RES_TYPE_MASK)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Ignore BARs which are still in use */
|
|
|
|
if (res->child)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
ret = add_to_list(&saved, bridge, res, 0, 0);
|
|
|
|
if (ret)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
dev_info(&bridge->dev, "BAR %d: releasing %pR\n",
|
|
|
|
i, res);
|
|
|
|
|
|
|
|
if (res->parent)
|
|
|
|
release_resource(res);
|
|
|
|
res->start = 0;
|
|
|
|
res->end = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == PCI_BRIDGE_RESOURCE_END)
|
|
|
|
break;
|
|
|
|
|
|
|
|
next = bridge->bus ? bridge->bus->self : NULL;
|
|
|
|
} while (next);
|
|
|
|
|
|
|
|
if (list_empty(&saved))
|
|
|
|
return -ENOENT;
|
|
|
|
|
|
|
|
__pci_bus_size_bridges(bridge->subordinate, &added);
|
|
|
|
__pci_bridge_assign_resources(bridge, &added, &failed);
|
|
|
|
BUG_ON(!list_empty(&added));
|
|
|
|
|
|
|
|
if (!list_empty(&failed)) {
|
|
|
|
ret = -ENOSPC;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
list_for_each_entry(dev_res, &saved, list) {
|
|
|
|
/* Skip the bridge we just assigned resources for. */
|
|
|
|
if (bridge == dev_res->dev)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
bridge = dev_res->dev;
|
|
|
|
pci_setup_bridge(bridge->subordinate);
|
|
|
|
}
|
|
|
|
|
|
|
|
free_list(&saved);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
/* restore size and flags */
|
|
|
|
list_for_each_entry(dev_res, &failed, list) {
|
|
|
|
struct resource *res = dev_res->res;
|
|
|
|
|
|
|
|
res->start = dev_res->start;
|
|
|
|
res->end = dev_res->end;
|
|
|
|
res->flags = dev_res->flags;
|
|
|
|
}
|
|
|
|
free_list(&failed);
|
|
|
|
|
|
|
|
/* Revert to the old configuration */
|
|
|
|
list_for_each_entry(dev_res, &saved, list) {
|
|
|
|
struct resource *res = dev_res->res;
|
|
|
|
|
|
|
|
bridge = dev_res->dev;
|
|
|
|
i = res - bridge->resource;
|
|
|
|
|
|
|
|
res->start = dev_res->start;
|
|
|
|
res->end = dev_res->end;
|
|
|
|
res->flags = dev_res->flags;
|
|
|
|
|
|
|
|
pci_claim_resource(bridge, i);
|
|
|
|
pci_setup_bridge(bridge->subordinate);
|
|
|
|
}
|
|
|
|
free_list(&saved);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-10-30 20:31:10 +00:00
|
|
|
void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
|
2012-01-21 10:08:23 +00:00
|
|
|
{
|
|
|
|
struct pci_dev *dev;
|
2012-01-21 10:08:27 +00:00
|
|
|
LIST_HEAD(add_list); /* list of resources that
|
2012-01-21 10:08:23 +00:00
|
|
|
want additional resources */
|
|
|
|
|
|
|
|
down_read(&pci_bus_sem);
|
2017-10-20 20:38:54 +00:00
|
|
|
for_each_pci_bridge(dev, bus)
|
|
|
|
if (pci_has_subordinate(dev))
|
|
|
|
__pci_bus_size_bridges(dev->subordinate, &add_list);
|
2012-01-21 10:08:23 +00:00
|
|
|
up_read(&pci_bus_sem);
|
|
|
|
__pci_bus_assign_resources(bus, &add_list, NULL);
|
2012-01-21 10:08:27 +00:00
|
|
|
BUG_ON(!list_empty(&add_list));
|
2012-10-30 20:31:10 +00:00
|
|
|
}
|
2015-04-08 18:21:33 +00:00
|
|
|
EXPORT_SYMBOL_GPL(pci_assign_unassigned_bus_resources);
|