mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-22 13:54:57 +08:00
PCI: Cleanup setup-bus.c comments and whitespace
Cleanup comments, kernel-doc, coding style. No functional changes intended; comment and whitespace changes only. Link: https://lore.kernel.org/lkml/PS2P216MB06427E290A68CDB921FB4B2980250@PS2P216MB0642.KORP216.PROD.OUTLOOK.COM Signed-off-by: Nicholas Johnson <nicholas.johnson-opensource@outlook.com.au> [bhelgaas: tidy related things throughout the file] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
This commit is contained in:
parent
113fb03ed1
commit
0d6076184a
@ -49,17 +49,15 @@ static void free_list(struct list_head *head)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add_to_list() - add a new resource tracker to the list
|
* add_to_list() - Add a new resource tracker to the list
|
||||||
* @head: Head of the list
|
* @head: Head of the list
|
||||||
* @dev: device corresponding to which the resource
|
* @dev: Device to which the resource belongs
|
||||||
* belongs
|
* @res: Resource to be tracked
|
||||||
* @res: The resource to be tracked
|
* @add_size: Additional size to be optionally added to the resource
|
||||||
* @add_size: additional size to be optionally added
|
|
||||||
* to the resource
|
|
||||||
*/
|
*/
|
||||||
static int add_to_list(struct list_head *head,
|
static int add_to_list(struct list_head *head, struct pci_dev *dev,
|
||||||
struct pci_dev *dev, struct resource *res,
|
struct resource *res, resource_size_t add_size,
|
||||||
resource_size_t add_size, resource_size_t min_align)
|
resource_size_t min_align)
|
||||||
{
|
{
|
||||||
struct pci_dev_resource *tmp;
|
struct pci_dev_resource *tmp;
|
||||||
|
|
||||||
@ -80,8 +78,7 @@ static int add_to_list(struct list_head *head,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_from_list(struct list_head *head,
|
static void remove_from_list(struct list_head *head, struct resource *res)
|
||||||
struct resource *res)
|
|
||||||
{
|
{
|
||||||
struct pci_dev_resource *dev_res, *tmp;
|
struct pci_dev_resource *dev_res, *tmp;
|
||||||
|
|
||||||
@ -158,7 +155,7 @@ static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)
|
|||||||
tmp->res = r;
|
tmp->res = r;
|
||||||
tmp->dev = dev;
|
tmp->dev = dev;
|
||||||
|
|
||||||
/* fallback is smallest one or list is empty*/
|
/* Fallback is smallest one or list is empty */
|
||||||
n = head;
|
n = head;
|
||||||
list_for_each_entry(dev_res, head, list) {
|
list_for_each_entry(dev_res, head, list) {
|
||||||
resource_size_t align;
|
resource_size_t align;
|
||||||
@ -176,16 +173,15 @@ static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __dev_sort_resources(struct pci_dev *dev,
|
static void __dev_sort_resources(struct pci_dev *dev, struct list_head *head)
|
||||||
struct list_head *head)
|
|
||||||
{
|
{
|
||||||
u16 class = dev->class >> 8;
|
u16 class = dev->class >> 8;
|
||||||
|
|
||||||
/* Don't touch classless devices or host bridges or ioapics. */
|
/* Don't touch classless devices or host bridges or IOAPICs */
|
||||||
if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST)
|
if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Don't touch ioapic devices already enabled by firmware */
|
/* Don't touch IOAPIC devices already enabled by firmware */
|
||||||
if (class == PCI_CLASS_SYSTEM_PIC) {
|
if (class == PCI_CLASS_SYSTEM_PIC) {
|
||||||
u16 command;
|
u16 command;
|
||||||
pci_read_config_word(dev, PCI_COMMAND, &command);
|
pci_read_config_word(dev, PCI_COMMAND, &command);
|
||||||
@ -204,16 +200,15 @@ static inline void reset_resource(struct resource *res)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reassign_resources_sorted() - satisfy any additional resource requests
|
* reassign_resources_sorted() - Satisfy any additional resource requests
|
||||||
*
|
*
|
||||||
* @realloc_head : head of the list tracking requests requiring additional
|
* @realloc_head: Head of the list tracking requests requiring
|
||||||
* resources
|
* additional resources
|
||||||
* @head : head of the list tracking requests with allocated
|
* @head: Head of the list tracking requests with allocated
|
||||||
* resources
|
* resources
|
||||||
*
|
*
|
||||||
* Walk through each element of the realloc_head and try to procure
|
* Walk through each element of the realloc_head and try to procure additional
|
||||||
* additional resources for the element, provided the element
|
* resources for the element, provided the element is in the head list.
|
||||||
* is in the head list.
|
|
||||||
*/
|
*/
|
||||||
static void reassign_resources_sorted(struct list_head *realloc_head,
|
static void reassign_resources_sorted(struct list_head *realloc_head,
|
||||||
struct list_head *head)
|
struct list_head *head)
|
||||||
@ -228,18 +223,18 @@ static void reassign_resources_sorted(struct list_head *realloc_head,
|
|||||||
bool found_match = false;
|
bool found_match = false;
|
||||||
|
|
||||||
res = add_res->res;
|
res = add_res->res;
|
||||||
/* skip resource that has been reset */
|
/* Skip resource that has been reset */
|
||||||
if (!res->flags)
|
if (!res->flags)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* skip this resource if not found in head list */
|
/* Skip this resource if not found in head list */
|
||||||
list_for_each_entry(dev_res, head, list) {
|
list_for_each_entry(dev_res, head, list) {
|
||||||
if (dev_res->res == res) {
|
if (dev_res->res == res) {
|
||||||
found_match = true;
|
found_match = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found_match)/* just skip */
|
if (!found_match) /* Just skip */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
idx = res - &add_res->dev->resource[0];
|
idx = res - &add_res->dev->resource[0];
|
||||||
@ -267,14 +262,14 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* assign_requested_resources_sorted() - satisfy resource requests
|
* assign_requested_resources_sorted() - Satisfy resource requests
|
||||||
*
|
*
|
||||||
* @head : head of the list tracking requests for resources
|
* @head: Head of the list tracking requests for resources
|
||||||
* @fail_head : head of the list tracking requests that could
|
* @fail_head: Head of the list tracking requests that could not be
|
||||||
* not be allocated
|
* allocated
|
||||||
*
|
*
|
||||||
* Satisfy resource requests of each element in the list. Add
|
* Satisfy resource requests of each element in the list. Add requests that
|
||||||
* requests that could not satisfied to the failed_list.
|
* could not be satisfied to the failed_list.
|
||||||
*/
|
*/
|
||||||
static void assign_requested_resources_sorted(struct list_head *head,
|
static void assign_requested_resources_sorted(struct list_head *head,
|
||||||
struct list_head *fail_head)
|
struct list_head *fail_head)
|
||||||
@ -290,8 +285,9 @@ static void assign_requested_resources_sorted(struct list_head *head,
|
|||||||
pci_assign_resource(dev_res->dev, idx)) {
|
pci_assign_resource(dev_res->dev, idx)) {
|
||||||
if (fail_head) {
|
if (fail_head) {
|
||||||
/*
|
/*
|
||||||
* if the failed res is for ROM BAR, and it will
|
* If the failed resource is a ROM BAR and
|
||||||
* be enabled later, don't add it to the list
|
* it will be enabled later, don't add it
|
||||||
|
* to the list.
|
||||||
*/
|
*/
|
||||||
if (!((idx == PCI_ROM_RESOURCE) &&
|
if (!((idx == PCI_ROM_RESOURCE) &&
|
||||||
(!(res->flags & IORESOURCE_ROM_ENABLE))))
|
(!(res->flags & IORESOURCE_ROM_ENABLE))))
|
||||||
@ -310,15 +306,14 @@ static unsigned long pci_fail_res_type_mask(struct list_head *fail_head)
|
|||||||
struct pci_dev_resource *fail_res;
|
struct pci_dev_resource *fail_res;
|
||||||
unsigned long mask = 0;
|
unsigned long mask = 0;
|
||||||
|
|
||||||
/* check failed type */
|
/* Check failed type */
|
||||||
list_for_each_entry(fail_res, fail_head, list)
|
list_for_each_entry(fail_res, fail_head, list)
|
||||||
mask |= fail_res->flags;
|
mask |= fail_res->flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* one pref failed resource will set IORESOURCE_MEM,
|
* One pref failed resource will set IORESOURCE_MEM, as we can
|
||||||
* as we can allocate pref in non-pref range.
|
* allocate pref in non-pref range. Will release all assigned
|
||||||
* Will release all assigned non-pref sibling resources
|
* non-pref sibling resources according to that bit.
|
||||||
* according to that bit.
|
|
||||||
*/
|
*/
|
||||||
return mask & (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH);
|
return mask & (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH);
|
||||||
}
|
}
|
||||||
@ -328,11 +323,11 @@ static bool pci_need_to_release(unsigned long mask, struct resource *res)
|
|||||||
if (res->flags & IORESOURCE_IO)
|
if (res->flags & IORESOURCE_IO)
|
||||||
return !!(mask & IORESOURCE_IO);
|
return !!(mask & IORESOURCE_IO);
|
||||||
|
|
||||||
/* check pref at first */
|
/* Check pref at first */
|
||||||
if (res->flags & IORESOURCE_PREFETCH) {
|
if (res->flags & IORESOURCE_PREFETCH) {
|
||||||
if (mask & IORESOURCE_PREFETCH)
|
if (mask & IORESOURCE_PREFETCH)
|
||||||
return true;
|
return true;
|
||||||
/* count pref if its parent is non-pref */
|
/* Count pref if its parent is non-pref */
|
||||||
else if ((mask & IORESOURCE_MEM) &&
|
else if ((mask & IORESOURCE_MEM) &&
|
||||||
!(res->parent->flags & IORESOURCE_PREFETCH))
|
!(res->parent->flags & IORESOURCE_PREFETCH))
|
||||||
return true;
|
return true;
|
||||||
@ -343,7 +338,7 @@ static bool pci_need_to_release(unsigned long mask, struct resource *res)
|
|||||||
if (res->flags & IORESOURCE_MEM)
|
if (res->flags & IORESOURCE_MEM)
|
||||||
return !!(mask & IORESOURCE_MEM);
|
return !!(mask & IORESOURCE_MEM);
|
||||||
|
|
||||||
return false; /* should not get here */
|
return false; /* Should not get here */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __assign_resources_sorted(struct list_head *head,
|
static void __assign_resources_sorted(struct list_head *head,
|
||||||
@ -351,25 +346,25 @@ static void __assign_resources_sorted(struct list_head *head,
|
|||||||
struct list_head *fail_head)
|
struct list_head *fail_head)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Should not assign requested resources at first.
|
* Should not assign requested resources at first. They could be
|
||||||
* they could be adjacent, so later reassign can not reallocate
|
* adjacent, so later reassign can not reallocate them one by one in
|
||||||
* them one by one in parent resource window.
|
* parent resource window.
|
||||||
* Try to assign requested + add_size at beginning
|
*
|
||||||
* if could do that, could get out early.
|
* Try to assign requested + add_size at beginning. If could do that,
|
||||||
* if could not do that, we still try to assign requested at first,
|
* could get out early. If could not do that, we still try to assign
|
||||||
* then try to reassign add_size for some resources.
|
* requested at first, then try to reassign add_size for some resources.
|
||||||
*
|
*
|
||||||
* Separate three resource type checking if we need to release
|
* Separate three resource type checking if we need to release
|
||||||
* assigned resource after requested + add_size try.
|
* assigned resource after requested + add_size try.
|
||||||
* 1. if there is io port assign fail, will release assigned
|
*
|
||||||
* io port.
|
* 1. If IO port assignment fails, will release assigned IO
|
||||||
* 2. if there is pref mmio assign fail, release assigned
|
* port.
|
||||||
* pref mmio.
|
* 2. If pref MMIO assignment fails, release assigned pref
|
||||||
* if assigned pref mmio's parent is non-pref mmio and there
|
* MMIO. If assigned pref MMIO's parent is non-pref MMIO
|
||||||
* is non-pref mmio assign fail, will release that assigned
|
* and non-pref MMIO assignment fails, will release that
|
||||||
* pref mmio.
|
* assigned pref MMIO.
|
||||||
* 3. if there is non-pref mmio assign fail or pref mmio
|
* 3. If non-pref MMIO assignment fails or pref MMIO
|
||||||
* assigned fail, will release assigned non-pref mmio.
|
* assignment fails, will release assigned non-pref MMIO.
|
||||||
*/
|
*/
|
||||||
LIST_HEAD(save_head);
|
LIST_HEAD(save_head);
|
||||||
LIST_HEAD(local_fail_head);
|
LIST_HEAD(local_fail_head);
|
||||||
@ -407,10 +402,10 @@ static void __assign_resources_sorted(struct list_head *head,
|
|||||||
add_align = get_res_add_align(realloc_head, dev_res->res);
|
add_align = get_res_add_align(realloc_head, dev_res->res);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The "head" list is sorted by the alignment to make sure
|
* The "head" list is sorted by alignment so resources with
|
||||||
* resources with bigger alignment will be assigned first.
|
* bigger alignment will be assigned first. After we
|
||||||
* After we change the alignment of a dev_res in "head" list,
|
* change the alignment of a dev_res in "head" list, we
|
||||||
* we need to reorder the list by alignment to make it
|
* need to reorder the list by alignment to make it
|
||||||
* consistent.
|
* consistent.
|
||||||
*/
|
*/
|
||||||
if (add_align > dev_res->res->start) {
|
if (add_align > dev_res->res->start) {
|
||||||
@ -435,7 +430,7 @@ static void __assign_resources_sorted(struct list_head *head,
|
|||||||
/* Try updated head list with add_size added */
|
/* Try updated head list with add_size added */
|
||||||
assign_requested_resources_sorted(head, &local_fail_head);
|
assign_requested_resources_sorted(head, &local_fail_head);
|
||||||
|
|
||||||
/* all assigned with add_size ? */
|
/* All assigned with add_size? */
|
||||||
if (list_empty(&local_fail_head)) {
|
if (list_empty(&local_fail_head)) {
|
||||||
/* Remove head list from realloc_head list */
|
/* Remove head list from realloc_head list */
|
||||||
list_for_each_entry(dev_res, head, list)
|
list_for_each_entry(dev_res, head, list)
|
||||||
@ -445,13 +440,13 @@ static void __assign_resources_sorted(struct list_head *head,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check failed type */
|
/* Check failed type */
|
||||||
fail_type = pci_fail_res_type_mask(&local_fail_head);
|
fail_type = pci_fail_res_type_mask(&local_fail_head);
|
||||||
/* remove not need to be released assigned res from head list etc */
|
/* Remove not need to be released assigned res from head list etc */
|
||||||
list_for_each_entry_safe(dev_res, tmp_res, head, list)
|
list_for_each_entry_safe(dev_res, tmp_res, head, list)
|
||||||
if (dev_res->res->parent &&
|
if (dev_res->res->parent &&
|
||||||
!pci_need_to_release(fail_type, dev_res->res)) {
|
!pci_need_to_release(fail_type, dev_res->res)) {
|
||||||
/* remove it from realloc_head list */
|
/* Remove it from realloc_head list */
|
||||||
remove_from_list(realloc_head, dev_res->res);
|
remove_from_list(realloc_head, dev_res->res);
|
||||||
remove_from_list(&save_head, dev_res->res);
|
remove_from_list(&save_head, dev_res->res);
|
||||||
list_del(&dev_res->list);
|
list_del(&dev_res->list);
|
||||||
@ -477,8 +472,7 @@ requested_and_reassign:
|
|||||||
/* Satisfy the must-have resource requests */
|
/* Satisfy the must-have resource requests */
|
||||||
assign_requested_resources_sorted(head, fail_head);
|
assign_requested_resources_sorted(head, fail_head);
|
||||||
|
|
||||||
/* Try to satisfy any additional optional resource
|
/* Try to satisfy any additional optional resource requests */
|
||||||
requests */
|
|
||||||
if (realloc_head)
|
if (realloc_head)
|
||||||
reassign_resources_sorted(realloc_head, head);
|
reassign_resources_sorted(realloc_head, head);
|
||||||
free_list(head);
|
free_list(head);
|
||||||
@ -563,17 +557,19 @@ void pci_setup_cardbus(struct pci_bus *bus)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(pci_setup_cardbus);
|
EXPORT_SYMBOL(pci_setup_cardbus);
|
||||||
|
|
||||||
/* Initialize bridges with base/limit values we have collected.
|
/*
|
||||||
PCI-to-PCI Bridge Architecture Specification rev. 1.1 (1998)
|
* Initialize bridges with base/limit values we have collected. PCI-to-PCI
|
||||||
requires that if there is no I/O ports or memory behind the
|
* Bridge Architecture Specification rev. 1.1 (1998) requires that if there
|
||||||
bridge, corresponding range must be turned off by writing base
|
* are no I/O ports or memory behind the bridge, the corresponding range
|
||||||
value greater than limit to the bridge's base/limit registers.
|
* 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
|
* Note: care must be taken when updating I/O base/limit registers of
|
||||||
config space writes, so it's quite possible that an I/O window of
|
* bridges which support 32-bit I/O. This update requires two config space
|
||||||
the bridge will have some undesirable address (e.g. 0) after the
|
* writes, so it's quite possible that an I/O window of the bridge will
|
||||||
first write. Ditto 64-bit prefetchable MMIO. */
|
* have some undesirable address (e.g. 0) after the first write. Ditto
|
||||||
|
* 64-bit prefetchable MMIO.
|
||||||
|
*/
|
||||||
static void pci_setup_bridge_io(struct pci_dev *bridge)
|
static void pci_setup_bridge_io(struct pci_dev *bridge)
|
||||||
{
|
{
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
@ -587,7 +583,7 @@ static void pci_setup_bridge_io(struct pci_dev *bridge)
|
|||||||
if (bridge->io_window_1k)
|
if (bridge->io_window_1k)
|
||||||
io_mask = PCI_IO_1K_RANGE_MASK;
|
io_mask = PCI_IO_1K_RANGE_MASK;
|
||||||
|
|
||||||
/* Set up the top and bottom of the PCI I/O segment for this bus. */
|
/* Set up the top and bottom of the PCI I/O segment for this bus */
|
||||||
res = &bridge->resource[PCI_BRIDGE_RESOURCES + 0];
|
res = &bridge->resource[PCI_BRIDGE_RESOURCES + 0];
|
||||||
pcibios_resource_to_bus(bridge->bus, ®ion, res);
|
pcibios_resource_to_bus(bridge->bus, ®ion, res);
|
||||||
if (res->flags & IORESOURCE_IO) {
|
if (res->flags & IORESOURCE_IO) {
|
||||||
@ -595,19 +591,19 @@ static void pci_setup_bridge_io(struct pci_dev *bridge)
|
|||||||
io_base_lo = (region.start >> 8) & io_mask;
|
io_base_lo = (region.start >> 8) & io_mask;
|
||||||
io_limit_lo = (region.end >> 8) & io_mask;
|
io_limit_lo = (region.end >> 8) & io_mask;
|
||||||
l = ((u16) io_limit_lo << 8) | io_base_lo;
|
l = ((u16) io_limit_lo << 8) | io_base_lo;
|
||||||
/* Set up upper 16 bits of I/O base/limit. */
|
/* Set up upper 16 bits of I/O base/limit */
|
||||||
io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
|
io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
|
||||||
pci_info(bridge, " bridge window %pR\n", res);
|
pci_info(bridge, " bridge window %pR\n", res);
|
||||||
} else {
|
} else {
|
||||||
/* Clear upper 16 bits of I/O base/limit. */
|
/* Clear upper 16 bits of I/O base/limit */
|
||||||
io_upper16 = 0;
|
io_upper16 = 0;
|
||||||
l = 0x00f0;
|
l = 0x00f0;
|
||||||
}
|
}
|
||||||
/* Temporarily disable the I/O range before updating PCI_IO_BASE. */
|
/* Temporarily disable the I/O range before updating PCI_IO_BASE */
|
||||||
pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
|
pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
|
||||||
/* Update lower 16 bits of I/O base/limit. */
|
/* Update lower 16 bits of I/O base/limit */
|
||||||
pci_write_config_word(bridge, PCI_IO_BASE, l);
|
pci_write_config_word(bridge, PCI_IO_BASE, l);
|
||||||
/* Update upper 16 bits of I/O base/limit. */
|
/* Update upper 16 bits of I/O base/limit */
|
||||||
pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16);
|
pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -617,7 +613,7 @@ static void pci_setup_bridge_mmio(struct pci_dev *bridge)
|
|||||||
struct pci_bus_region region;
|
struct pci_bus_region region;
|
||||||
u32 l;
|
u32 l;
|
||||||
|
|
||||||
/* Set up the top and bottom of the PCI Memory segment for this bus. */
|
/* Set up the top and bottom of the PCI Memory segment for this bus */
|
||||||
res = &bridge->resource[PCI_BRIDGE_RESOURCES + 1];
|
res = &bridge->resource[PCI_BRIDGE_RESOURCES + 1];
|
||||||
pcibios_resource_to_bus(bridge->bus, ®ion, res);
|
pcibios_resource_to_bus(bridge->bus, ®ion, res);
|
||||||
if (res->flags & IORESOURCE_MEM) {
|
if (res->flags & IORESOURCE_MEM) {
|
||||||
@ -636,12 +632,14 @@ static void pci_setup_bridge_mmio_pref(struct pci_dev *bridge)
|
|||||||
struct pci_bus_region region;
|
struct pci_bus_region region;
|
||||||
u32 l, bu, lu;
|
u32 l, bu, lu;
|
||||||
|
|
||||||
/* Clear out the upper 32 bits of PREF limit.
|
/*
|
||||||
If PCI_PREF_BASE_UPPER32 was non-zero, this temporarily
|
* Clear out the upper 32 bits of PREF limit. If
|
||||||
disables PREF range, which is ok. */
|
* 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);
|
pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
|
||||||
|
|
||||||
/* Set up PREF base/limit. */
|
/* Set up PREF base/limit */
|
||||||
bu = lu = 0;
|
bu = lu = 0;
|
||||||
res = &bridge->resource[PCI_BRIDGE_RESOURCES + 2];
|
res = &bridge->resource[PCI_BRIDGE_RESOURCES + 2];
|
||||||
pcibios_resource_to_bus(bridge->bus, ®ion, res);
|
pcibios_resource_to_bus(bridge->bus, ®ion, res);
|
||||||
@ -658,7 +656,7 @@ static void pci_setup_bridge_mmio_pref(struct pci_dev *bridge)
|
|||||||
}
|
}
|
||||||
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
|
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
|
||||||
|
|
||||||
/* Set the upper 32 bits of PREF base & limit. */
|
/* 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_BASE_UPPER32, bu);
|
||||||
pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
|
pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
|
||||||
}
|
}
|
||||||
@ -702,13 +700,13 @@ int pci_claim_bridge_resource(struct pci_dev *bridge, int i)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (pci_claim_resource(bridge, i) == 0)
|
if (pci_claim_resource(bridge, i) == 0)
|
||||||
return 0; /* claimed the window */
|
return 0; /* Claimed the window */
|
||||||
|
|
||||||
if ((bridge->class >> 8) != PCI_CLASS_BRIDGE_PCI)
|
if ((bridge->class >> 8) != PCI_CLASS_BRIDGE_PCI)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!pci_bus_clip_resource(bridge, i))
|
if (!pci_bus_clip_resource(bridge, i))
|
||||||
return -EINVAL; /* clipping didn't change anything */
|
return -EINVAL; /* Clipping didn't change anything */
|
||||||
|
|
||||||
switch (i - PCI_BRIDGE_RESOURCES) {
|
switch (i - PCI_BRIDGE_RESOURCES) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -725,14 +723,16 @@ int pci_claim_bridge_resource(struct pci_dev *bridge, int i)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pci_claim_resource(bridge, i) == 0)
|
if (pci_claim_resource(bridge, i) == 0)
|
||||||
return 0; /* claimed a smaller window */
|
return 0; /* Claimed a smaller window */
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check whether the bridge supports optional I/O and
|
/*
|
||||||
prefetchable memory ranges. If not, the respective
|
* Check whether the bridge supports optional I/O and prefetchable memory
|
||||||
base/limit registers must be read-only and read as 0. */
|
* ranges. If not, the respective base/limit registers must be read-only
|
||||||
|
* and read as 0.
|
||||||
|
*/
|
||||||
static void pci_bridge_check_ranges(struct pci_bus *bus)
|
static void pci_bridge_check_ranges(struct pci_bus *bus)
|
||||||
{
|
{
|
||||||
struct pci_dev *bridge = bus->self;
|
struct pci_dev *bridge = bus->self;
|
||||||
@ -752,12 +752,14 @@ static void pci_bridge_check_ranges(struct pci_bus *bus)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function for sizing routines: find first available
|
/*
|
||||||
bus resource of a given type. Note: we intentionally skip
|
* Helper function for sizing routines: find first available bus resource
|
||||||
the bus resources which have already been assigned (that is,
|
* of a given type. Note: we intentionally skip the bus resources which
|
||||||
have non-NULL parent resource). */
|
* have already been assigned (that is, have non-NULL parent resource).
|
||||||
|
*/
|
||||||
static struct resource *find_free_bus_resource(struct pci_bus *bus,
|
static struct resource *find_free_bus_resource(struct pci_bus *bus,
|
||||||
unsigned long type_mask, unsigned long type)
|
unsigned long type_mask,
|
||||||
|
unsigned long type)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct resource *r;
|
struct resource *r;
|
||||||
@ -783,8 +785,10 @@ static resource_size_t calculate_iosize(resource_size_t size,
|
|||||||
size = min_size;
|
size = min_size;
|
||||||
if (old_size == 1)
|
if (old_size == 1)
|
||||||
old_size = 0;
|
old_size = 0;
|
||||||
/* To be fixed in 2.5: we should have sort of HAVE_ISA
|
/*
|
||||||
flag in the struct pci_bus. */
|
* 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)
|
#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
|
||||||
size = (size & 0xff) + ((size & ~0xffUL) << 2);
|
size = (size & 0xff) + ((size & ~0xffUL) << 2);
|
||||||
#endif
|
#endif
|
||||||
@ -824,8 +828,7 @@ resource_size_t __weak pcibios_window_alignment(struct pci_bus *bus,
|
|||||||
#define PCI_P2P_DEFAULT_IO_ALIGN 0x1000 /* 4KiB */
|
#define PCI_P2P_DEFAULT_IO_ALIGN 0x1000 /* 4KiB */
|
||||||
#define PCI_P2P_DEFAULT_IO_ALIGN_1K 0x400 /* 1KiB */
|
#define PCI_P2P_DEFAULT_IO_ALIGN_1K 0x400 /* 1KiB */
|
||||||
|
|
||||||
static resource_size_t window_alignment(struct pci_bus *bus,
|
static resource_size_t window_alignment(struct pci_bus *bus, unsigned long type)
|
||||||
unsigned long type)
|
|
||||||
{
|
{
|
||||||
resource_size_t align = 1, arch_align;
|
resource_size_t align = 1, arch_align;
|
||||||
|
|
||||||
@ -833,8 +836,8 @@ static resource_size_t window_alignment(struct pci_bus *bus,
|
|||||||
align = PCI_P2P_DEFAULT_MEM_ALIGN;
|
align = PCI_P2P_DEFAULT_MEM_ALIGN;
|
||||||
else if (type & IORESOURCE_IO) {
|
else if (type & IORESOURCE_IO) {
|
||||||
/*
|
/*
|
||||||
* Per spec, I/O windows are 4K-aligned, but some
|
* Per spec, I/O windows are 4K-aligned, but some bridges have
|
||||||
* bridges have an extension to support 1K alignment.
|
* an extension to support 1K alignment.
|
||||||
*/
|
*/
|
||||||
if (bus->self->io_window_1k)
|
if (bus->self->io_window_1k)
|
||||||
align = PCI_P2P_DEFAULT_IO_ALIGN_1K;
|
align = PCI_P2P_DEFAULT_IO_ALIGN_1K;
|
||||||
@ -847,20 +850,21 @@ static resource_size_t window_alignment(struct pci_bus *bus,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pbus_size_io() - size the io window of a given bus
|
* pbus_size_io() - Size the I/O window of a given bus
|
||||||
*
|
*
|
||||||
* @bus : the bus
|
* @bus: The bus
|
||||||
* @min_size : the minimum io window that must to be allocated
|
* @min_size: The minimum I/O window that must be allocated
|
||||||
* @add_size : additional optional io window
|
* @add_size: Additional optional I/O window
|
||||||
* @realloc_head : track the additional io window on this list
|
* @realloc_head: Track the additional I/O window on this list
|
||||||
*
|
*
|
||||||
* Sizing the IO windows of the PCI-PCI bridge is trivial,
|
* Sizing the I/O windows of the PCI-PCI bridge is trivial, since these
|
||||||
* since these windows have 1K or 4K granularity and the IO ranges
|
* windows have 1K or 4K granularity and the I/O ranges of non-bridge PCI
|
||||||
* of non-bridge PCI devices are limited to 256 bytes.
|
* devices are limited to 256 bytes. We must be careful with the ISA
|
||||||
* We must be careful with the ISA aliasing though.
|
* aliasing though.
|
||||||
*/
|
*/
|
||||||
static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
||||||
resource_size_t add_size, struct list_head *realloc_head)
|
resource_size_t add_size,
|
||||||
|
struct list_head *realloc_head)
|
||||||
{
|
{
|
||||||
struct pci_dev *dev;
|
struct pci_dev *dev;
|
||||||
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO,
|
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO,
|
||||||
@ -947,33 +951,33 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pbus_size_mem() - size the memory window of a given bus
|
* pbus_size_mem() - Size the memory window of a given bus
|
||||||
*
|
*
|
||||||
* @bus : the bus
|
* @bus: The bus
|
||||||
* @mask: mask the resource flag, then compare it with type
|
* @mask: Mask the resource flag, then compare it with type
|
||||||
* @type: the type of free resource from bridge
|
* @type: The type of free resource from bridge
|
||||||
* @type2: second match type
|
* @type2: Second match type
|
||||||
* @type3: third match type
|
* @type3: Third match type
|
||||||
* @min_size : the minimum memory window that must to be allocated
|
* @min_size: The minimum memory window that must be allocated
|
||||||
* @add_size : additional optional memory window
|
* @add_size: Additional optional memory window
|
||||||
* @realloc_head : track the additional memory window on this list
|
* @realloc_head: Track the additional memory window on this list
|
||||||
*
|
*
|
||||||
* Calculate the size of the bus and minimal alignment which
|
* Calculate the size of the bus and minimal alignment which guarantees
|
||||||
* guarantees that all child resources fit in this size.
|
* that all child resources fit in this size.
|
||||||
*
|
*
|
||||||
* Returns -ENOSPC if there's no available bus resource of the desired type.
|
* Return -ENOSPC if there's no available bus resource of the desired
|
||||||
* Otherwise, sets the bus resource start/end to indicate the required
|
* type. Otherwise, set the bus resource start/end to indicate the
|
||||||
* size, adds things to realloc_head (if supplied), and returns 0.
|
* required size, add things to realloc_head (if supplied), and return 0.
|
||||||
*/
|
*/
|
||||||
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
||||||
unsigned long type, unsigned long type2,
|
unsigned long type, unsigned long type2,
|
||||||
unsigned long type3,
|
unsigned long type3, resource_size_t min_size,
|
||||||
resource_size_t min_size, resource_size_t add_size,
|
resource_size_t add_size,
|
||||||
struct list_head *realloc_head)
|
struct list_head *realloc_head)
|
||||||
{
|
{
|
||||||
struct pci_dev *dev;
|
struct pci_dev *dev;
|
||||||
resource_size_t min_align, align, size, size0, size1;
|
resource_size_t min_align, align, size, size0, size1;
|
||||||
resource_size_t aligns[18]; /* Alignments from 1Mb to 128Gb */
|
resource_size_t aligns[18]; /* Alignments from 1MB to 128GB */
|
||||||
int order, max_order;
|
int order, max_order;
|
||||||
struct resource *b_res = find_free_bus_resource(bus,
|
struct resource *b_res = find_free_bus_resource(bus,
|
||||||
mask | IORESOURCE_PREFETCH, type);
|
mask | IORESOURCE_PREFETCH, type);
|
||||||
@ -1002,12 +1006,12 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
|||||||
continue;
|
continue;
|
||||||
r_size = resource_size(r);
|
r_size = resource_size(r);
|
||||||
#ifdef CONFIG_PCI_IOV
|
#ifdef CONFIG_PCI_IOV
|
||||||
/* put SRIOV requested res to the optional list */
|
/* Put SRIOV requested res to the optional list */
|
||||||
if (realloc_head && i >= PCI_IOV_RESOURCES &&
|
if (realloc_head && i >= PCI_IOV_RESOURCES &&
|
||||||
i <= PCI_IOV_RESOURCE_END) {
|
i <= PCI_IOV_RESOURCE_END) {
|
||||||
add_align = max(pci_resource_alignment(dev, r), add_align);
|
add_align = max(pci_resource_alignment(dev, r), add_align);
|
||||||
r->end = r->start - 1;
|
r->end = r->start - 1;
|
||||||
add_to_list(realloc_head, dev, r, r_size, 0/* don't care */);
|
add_to_list(realloc_head, dev, r, r_size, 0 /* Don't care */);
|
||||||
children_add_size += r_size;
|
children_add_size += r_size;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1029,8 +1033,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
size += max(r_size, align);
|
size += max(r_size, align);
|
||||||
/* Exclude ranges with size > align from
|
/*
|
||||||
calculation of the alignment. */
|
* Exclude ranges with size > align from calculation of
|
||||||
|
* the alignment.
|
||||||
|
*/
|
||||||
if (r_size <= align)
|
if (r_size <= align)
|
||||||
aligns[order] += align;
|
aligns[order] += align;
|
||||||
if (order > max_order)
|
if (order > max_order)
|
||||||
@ -1091,8 +1097,8 @@ static void pci_bus_size_cardbus(struct pci_bus *bus,
|
|||||||
if (b_res[0].parent)
|
if (b_res[0].parent)
|
||||||
goto handle_b_res_1;
|
goto handle_b_res_1;
|
||||||
/*
|
/*
|
||||||
* Reserve some resources for CardBus. We reserve
|
* Reserve some resources for CardBus. We reserve a fixed amount
|
||||||
* a fixed amount of bus space for CardBus bridges.
|
* of bus space for CardBus bridges.
|
||||||
*/
|
*/
|
||||||
b_res[0].start = pci_cardbus_io_size;
|
b_res[0].start = pci_cardbus_io_size;
|
||||||
b_res[0].end = b_res[0].start + pci_cardbus_io_size - 1;
|
b_res[0].end = b_res[0].start + pci_cardbus_io_size - 1;
|
||||||
@ -1116,7 +1122,7 @@ handle_b_res_1:
|
|||||||
}
|
}
|
||||||
|
|
||||||
handle_b_res_2:
|
handle_b_res_2:
|
||||||
/* MEM1 must not be pref mmio */
|
/* MEM1 must not be pref MMIO */
|
||||||
pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
|
pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
|
||||||
if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM1) {
|
if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM1) {
|
||||||
ctrl &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM1;
|
ctrl &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM1;
|
||||||
@ -1124,10 +1130,7 @@ handle_b_res_2:
|
|||||||
pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
|
pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Check whether prefetchable memory is supported by this bridge. */
|
||||||
* Check whether prefetchable memory is supported
|
|
||||||
* by this bridge.
|
|
||||||
*/
|
|
||||||
pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
|
pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
|
||||||
if (!(ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0)) {
|
if (!(ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0)) {
|
||||||
ctrl |= PCI_CB_BRIDGE_CTL_PREFETCH_MEM0;
|
ctrl |= PCI_CB_BRIDGE_CTL_PREFETCH_MEM0;
|
||||||
@ -1138,9 +1141,8 @@ handle_b_res_2:
|
|||||||
if (b_res[2].parent)
|
if (b_res[2].parent)
|
||||||
goto handle_b_res_3;
|
goto handle_b_res_3;
|
||||||
/*
|
/*
|
||||||
* If we have prefetchable memory support, allocate
|
* If we have prefetchable memory support, allocate two regions.
|
||||||
* two regions. Otherwise, allocate one region of
|
* Otherwise, allocate one region of twice the size.
|
||||||
* twice the size.
|
|
||||||
*/
|
*/
|
||||||
if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
|
if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
|
||||||
b_res[2].start = pci_cardbus_mem_size;
|
b_res[2].start = pci_cardbus_mem_size;
|
||||||
@ -1153,7 +1155,7 @@ handle_b_res_2:
|
|||||||
pci_cardbus_mem_size, pci_cardbus_mem_size);
|
pci_cardbus_mem_size, pci_cardbus_mem_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reduce that to half */
|
/* Reduce that to half */
|
||||||
b_res_3_size = pci_cardbus_mem_size;
|
b_res_3_size = pci_cardbus_mem_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1204,7 +1206,7 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
|
|||||||
|
|
||||||
switch (bus->self->hdr_type) {
|
switch (bus->self->hdr_type) {
|
||||||
case PCI_HEADER_TYPE_CARDBUS:
|
case PCI_HEADER_TYPE_CARDBUS:
|
||||||
/* don't size cardbuses yet. */
|
/* Don't size CardBuses yet */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCI_HEADER_TYPE_BRIDGE:
|
case PCI_HEADER_TYPE_BRIDGE:
|
||||||
@ -1276,13 +1278,12 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
|
|||||||
* - all non-prefetchable resources
|
* - all non-prefetchable resources
|
||||||
* - 32-bit prefetchable resources if there's a 64-bit
|
* - 32-bit prefetchable resources if there's a 64-bit
|
||||||
* prefetchable window or no prefetchable window at all
|
* prefetchable window or no prefetchable window at all
|
||||||
* - 64-bit prefetchable resources if there's no
|
* - 64-bit prefetchable resources if there's no prefetchable
|
||||||
* prefetchable window at all
|
* window at all
|
||||||
*
|
*
|
||||||
* Note that the strategy in __pci_assign_resource() must
|
* Note that the strategy in __pci_assign_resource() must match
|
||||||
* match that used here. Specifically, we cannot put a
|
* that used here. Specifically, we cannot put a 32-bit
|
||||||
* 32-bit prefetchable resource in a 64-bit prefetchable
|
* prefetchable resource in a 64-bit prefetchable window.
|
||||||
* window.
|
|
||||||
*/
|
*/
|
||||||
pbus_size_mem(bus, mask, IORESOURCE_MEM, type2, type3,
|
pbus_size_mem(bus, mask, IORESOURCE_MEM, type2, type3,
|
||||||
realloc_head ? 0 : additional_mem_size,
|
realloc_head ? 0 : additional_mem_size,
|
||||||
@ -1315,8 +1316,8 @@ static void assign_fixed_resource_on_bus(struct pci_bus *b, struct resource *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to assign any resources marked as IORESOURCE_PCI_FIXED, as they
|
* Try to assign any resources marked as IORESOURCE_PCI_FIXED, as they are
|
||||||
* are skipped by pbus_assign_resources_sorted().
|
* skipped by pbus_assign_resources_sorted().
|
||||||
*/
|
*/
|
||||||
static void pdev_assign_fixed_resources(struct pci_dev *dev)
|
static void pdev_assign_fixed_resources(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
@ -1427,10 +1428,9 @@ static void pci_bus_allocate_resources(struct pci_bus *b)
|
|||||||
struct pci_bus *child;
|
struct pci_bus *child;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Carry out a depth-first search on the PCI bus
|
* Carry out a depth-first search on the PCI bus tree to allocate
|
||||||
* tree to allocate bridge apertures. Read the
|
* bridge apertures. Read the programmed bridge bases and
|
||||||
* programmed bridge bases and recursively claim
|
* recursively claim the respective bridge resources.
|
||||||
* the respective bridge resources.
|
|
||||||
*/
|
*/
|
||||||
if (b->self) {
|
if (b->self) {
|
||||||
pci_read_bridge_bases(b);
|
pci_read_bridge_bases(b);
|
||||||
@ -1495,16 +1495,14 @@ static void pci_bridge_release_resources(struct pci_bus *bus,
|
|||||||
b_res = &dev->resource[PCI_BRIDGE_RESOURCES];
|
b_res = &dev->resource[PCI_BRIDGE_RESOURCES];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 1. if there is io port assign fail, will release bridge
|
* 1. If IO port assignment fails, release bridge IO port.
|
||||||
* io port.
|
* 2. If non pref MMIO assignment fails, release bridge nonpref MMIO.
|
||||||
* 2. if there is non pref mmio assign fail, release bridge
|
* 3. If 64bit pref MMIO assignment fails, and bridge pref is 64bit,
|
||||||
* nonpref mmio.
|
* release bridge pref MMIO.
|
||||||
* 3. if there is 64bit pref mmio assign fail, and bridge pref
|
* 4. If pref MMIO assignment fails, and bridge pref is 32bit,
|
||||||
* is 64bit, release bridge pref mmio.
|
* release bridge pref MMIO.
|
||||||
* 4. if there is pref mmio assign fail, and bridge pref is
|
* 5. If pref MMIO assignment fails, and bridge pref is not
|
||||||
* 32bit mmio, release bridge pref mmio
|
* assigned, release bridge nonpref MMIO.
|
||||||
* 5. if there is pref mmio assign fail, and bridge pref is not
|
|
||||||
* assigned, release bridge nonpref mmio.
|
|
||||||
*/
|
*/
|
||||||
if (type & IORESOURCE_IO)
|
if (type & IORESOURCE_IO)
|
||||||
idx = 0;
|
idx = 0;
|
||||||
@ -1524,25 +1522,22 @@ static void pci_bridge_release_resources(struct pci_bus *bus,
|
|||||||
if (!r->parent)
|
if (!r->parent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/* If there are children, release them all */
|
||||||
* if there are children under that, we should release them
|
|
||||||
* all
|
|
||||||
*/
|
|
||||||
release_child_resources(r);
|
release_child_resources(r);
|
||||||
if (!release_resource(r)) {
|
if (!release_resource(r)) {
|
||||||
type = old_flags = r->flags & PCI_RES_TYPE_MASK;
|
type = old_flags = r->flags & PCI_RES_TYPE_MASK;
|
||||||
pci_printk(KERN_DEBUG, dev, "resource %d %pR released\n",
|
pci_printk(KERN_DEBUG, dev, "resource %d %pR released\n",
|
||||||
PCI_BRIDGE_RESOURCES + idx, r);
|
PCI_BRIDGE_RESOURCES + idx, r);
|
||||||
/* keep the old size */
|
/* Keep the old size */
|
||||||
r->end = resource_size(r) - 1;
|
r->end = resource_size(r) - 1;
|
||||||
r->start = 0;
|
r->start = 0;
|
||||||
r->flags = 0;
|
r->flags = 0;
|
||||||
|
|
||||||
/* avoiding touch the one without PREF */
|
/* Avoiding touch the one without PREF */
|
||||||
if (type & IORESOURCE_PREFETCH)
|
if (type & IORESOURCE_PREFETCH)
|
||||||
type = IORESOURCE_PREFETCH;
|
type = IORESOURCE_PREFETCH;
|
||||||
__pci_setup_bridge(bus, type);
|
__pci_setup_bridge(bus, type);
|
||||||
/* for next child res under same bridge */
|
/* For next child res under same bridge */
|
||||||
r->flags = old_flags;
|
r->flags = old_flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1551,9 +1546,10 @@ enum release_type {
|
|||||||
leaf_only,
|
leaf_only,
|
||||||
whole_subtree,
|
whole_subtree,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* try to release pci bridge resources that is from leaf bridge,
|
* Try to release PCI bridge resources from leaf bridge, so we can allocate
|
||||||
* so we can allocate big new one later
|
* a larger window later.
|
||||||
*/
|
*/
|
||||||
static void pci_bus_release_bridge_resources(struct pci_bus *bus,
|
static void pci_bus_release_bridge_resources(struct pci_bus *bus,
|
||||||
unsigned long type,
|
unsigned long type,
|
||||||
@ -1678,7 +1674,7 @@ static int iov_resources_unassigned(struct pci_dev *dev, void *data)
|
|||||||
pcibios_resource_to_bus(dev->bus, ®ion, r);
|
pcibios_resource_to_bus(dev->bus, ®ion, r);
|
||||||
if (!region.start) {
|
if (!region.start) {
|
||||||
*unassigned = true;
|
*unassigned = true;
|
||||||
return 1; /* return early from pci_walk_bus() */
|
return 1; /* Return early from pci_walk_bus() */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1708,14 +1704,14 @@ static enum enable_type pci_realloc_detect(struct pci_bus *bus,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* first try will not touch pci bridge res
|
* First try will not touch PCI bridge res.
|
||||||
* second and later try will clear small leaf bridge res
|
* Second and later try will clear small leaf bridge res.
|
||||||
* will stop till to the max depth if can not find good one
|
* Will stop till to the max depth if can not find good one.
|
||||||
*/
|
*/
|
||||||
void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)
|
void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)
|
||||||
{
|
{
|
||||||
LIST_HEAD(realloc_head); /* list of resources that
|
LIST_HEAD(realloc_head);
|
||||||
want additional resources */
|
/* List of resources that want additional resources */
|
||||||
struct list_head *add_list = NULL;
|
struct list_head *add_list = NULL;
|
||||||
int tried_times = 0;
|
int tried_times = 0;
|
||||||
enum release_type rel_type = leaf_only;
|
enum release_type rel_type = leaf_only;
|
||||||
@ -1724,7 +1720,7 @@ void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)
|
|||||||
int pci_try_num = 1;
|
int pci_try_num = 1;
|
||||||
enum enable_type enable_local;
|
enum enable_type enable_local;
|
||||||
|
|
||||||
/* don't realloc if asked to do so */
|
/* Don't realloc if asked to do so */
|
||||||
enable_local = pci_realloc_detect(bus, pci_realloc_enable);
|
enable_local = pci_realloc_detect(bus, pci_realloc_enable);
|
||||||
if (pci_realloc_enabled(enable_local)) {
|
if (pci_realloc_enabled(enable_local)) {
|
||||||
int max_depth = pci_bus_get_depth(bus);
|
int max_depth = pci_bus_get_depth(bus);
|
||||||
@ -1737,13 +1733,14 @@ void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)
|
|||||||
|
|
||||||
again:
|
again:
|
||||||
/*
|
/*
|
||||||
* last try will use add_list, otherwise will try good to have as
|
* Last try will use add_list, otherwise will try good to have as must
|
||||||
* must have, so can realloc parent bridge resource
|
* have, so can realloc parent bridge resource
|
||||||
*/
|
*/
|
||||||
if (tried_times + 1 == pci_try_num)
|
if (tried_times + 1 == pci_try_num)
|
||||||
add_list = &realloc_head;
|
add_list = &realloc_head;
|
||||||
/* Depth first, calculate sizes and alignments of all
|
/*
|
||||||
subordinate buses. */
|
* Depth first, calculate sizes and alignments of all subordinate buses.
|
||||||
|
*/
|
||||||
__pci_bus_size_bridges(bus, add_list);
|
__pci_bus_size_bridges(bus, add_list);
|
||||||
|
|
||||||
/* Depth last, allocate resources and update the hardware. */
|
/* Depth last, allocate resources and update the hardware. */
|
||||||
@ -1752,7 +1749,7 @@ again:
|
|||||||
BUG_ON(!list_empty(add_list));
|
BUG_ON(!list_empty(add_list));
|
||||||
tried_times++;
|
tried_times++;
|
||||||
|
|
||||||
/* any device complain? */
|
/* Any device complain? */
|
||||||
if (list_empty(&fail_head))
|
if (list_empty(&fail_head))
|
||||||
goto dump;
|
goto dump;
|
||||||
|
|
||||||
@ -1769,20 +1766,20 @@ again:
|
|||||||
dev_printk(KERN_DEBUG, &bus->dev,
|
dev_printk(KERN_DEBUG, &bus->dev,
|
||||||
"No. %d try to assign unassigned res\n", tried_times + 1);
|
"No. %d try to assign unassigned res\n", tried_times + 1);
|
||||||
|
|
||||||
/* third times and later will not check if it is leaf */
|
/* Third times and later will not check if it is leaf */
|
||||||
if ((tried_times + 1) > 2)
|
if ((tried_times + 1) > 2)
|
||||||
rel_type = whole_subtree;
|
rel_type = whole_subtree;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to release leaf bridge's resources that doesn't fit resource of
|
* Try to release leaf bridge's resources that doesn't fit resource of
|
||||||
* child device under that bridge
|
* child device under that bridge.
|
||||||
*/
|
*/
|
||||||
list_for_each_entry(fail_res, &fail_head, list)
|
list_for_each_entry(fail_res, &fail_head, list)
|
||||||
pci_bus_release_bridge_resources(fail_res->dev->bus,
|
pci_bus_release_bridge_resources(fail_res->dev->bus,
|
||||||
fail_res->flags & PCI_RES_TYPE_MASK,
|
fail_res->flags & PCI_RES_TYPE_MASK,
|
||||||
rel_type);
|
rel_type);
|
||||||
|
|
||||||
/* restore size and flags */
|
/* Restore size and flags */
|
||||||
list_for_each_entry(fail_res, &fail_head, list) {
|
list_for_each_entry(fail_res, &fail_head, list) {
|
||||||
struct resource *res = fail_res->res;
|
struct resource *res = fail_res->res;
|
||||||
|
|
||||||
@ -1797,7 +1794,7 @@ again:
|
|||||||
goto again;
|
goto again;
|
||||||
|
|
||||||
dump:
|
dump:
|
||||||
/* dump the resource on buses */
|
/* Dump the resource on buses */
|
||||||
pci_bus_dump_resources(bus);
|
pci_bus_dump_resources(bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1808,14 +1805,15 @@ void __init pci_assign_unassigned_resources(void)
|
|||||||
list_for_each_entry(root_bus, &pci_root_buses, node) {
|
list_for_each_entry(root_bus, &pci_root_buses, node) {
|
||||||
pci_assign_unassigned_root_bus_resources(root_bus);
|
pci_assign_unassigned_root_bus_resources(root_bus);
|
||||||
|
|
||||||
/* Make sure the root bridge has a companion ACPI device: */
|
/* Make sure the root bridge has a companion ACPI device */
|
||||||
if (ACPI_HANDLE(root_bus->bridge))
|
if (ACPI_HANDLE(root_bus->bridge))
|
||||||
acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge));
|
acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void extend_bridge_window(struct pci_dev *bridge, struct resource *res,
|
static void extend_bridge_window(struct pci_dev *bridge, struct resource *res,
|
||||||
struct list_head *add_list, resource_size_t available)
|
struct list_head *add_list,
|
||||||
|
resource_size_t available)
|
||||||
{
|
{
|
||||||
struct pci_dev_resource *dev_res;
|
struct pci_dev_resource *dev_res;
|
||||||
|
|
||||||
@ -1839,8 +1837,10 @@ static void extend_bridge_window(struct pci_dev *bridge, struct resource *res,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void pci_bus_distribute_available_resources(struct pci_bus *bus,
|
static void pci_bus_distribute_available_resources(struct pci_bus *bus,
|
||||||
struct list_head *add_list, resource_size_t available_io,
|
struct list_head *add_list,
|
||||||
resource_size_t available_mmio, resource_size_t available_mmio_pref)
|
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;
|
resource_size_t remaining_io, remaining_mmio, remaining_mmio_pref;
|
||||||
unsigned int normal_bridges = 0, hotplug_bridges = 0;
|
unsigned int normal_bridges = 0, hotplug_bridges = 0;
|
||||||
@ -1909,8 +1909,8 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* There is only one bridge on the bus so it gets all available
|
* There is only one bridge on the bus so it gets all available
|
||||||
* resources which it can then distribute to the possible
|
* resources which it can then distribute to the possible hotplug
|
||||||
* hotplug bridges below.
|
* bridges below.
|
||||||
*/
|
*/
|
||||||
if (hotplug_bridges + normal_bridges == 1) {
|
if (hotplug_bridges + normal_bridges == 1) {
|
||||||
dev = list_first_entry(&bus->devices, struct pci_dev, bus_list);
|
dev = list_first_entry(&bus->devices, struct pci_dev, bus_list);
|
||||||
@ -1961,8 +1961,7 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void pci_bridge_distribute_available_resources(struct pci_dev *bridge,
|
||||||
pci_bridge_distribute_available_resources(struct pci_dev *bridge,
|
|
||||||
struct list_head *add_list)
|
struct list_head *add_list)
|
||||||
{
|
{
|
||||||
resource_size_t available_io, available_mmio, available_mmio_pref;
|
resource_size_t available_io, available_mmio, available_mmio_pref;
|
||||||
@ -1980,14 +1979,17 @@ pci_bridge_distribute_available_resources(struct pci_dev *bridge,
|
|||||||
available_mmio_pref = resource_size(res);
|
available_mmio_pref = resource_size(res);
|
||||||
|
|
||||||
pci_bus_distribute_available_resources(bridge->subordinate,
|
pci_bus_distribute_available_resources(bridge->subordinate,
|
||||||
add_list, available_io, available_mmio, available_mmio_pref);
|
add_list, available_io,
|
||||||
|
available_mmio,
|
||||||
|
available_mmio_pref);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
|
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
|
||||||
{
|
{
|
||||||
struct pci_bus *parent = bridge->subordinate;
|
struct pci_bus *parent = bridge->subordinate;
|
||||||
LIST_HEAD(add_list); /* list of resources that
|
/* List of resources that want additional resources */
|
||||||
want additional resources */
|
LIST_HEAD(add_list);
|
||||||
|
|
||||||
int tried_times = 0;
|
int tried_times = 0;
|
||||||
LIST_HEAD(fail_head);
|
LIST_HEAD(fail_head);
|
||||||
struct pci_dev_resource *fail_res;
|
struct pci_dev_resource *fail_res;
|
||||||
@ -1997,9 +1999,9 @@ again:
|
|||||||
__pci_bus_size_bridges(parent, &add_list);
|
__pci_bus_size_bridges(parent, &add_list);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Distribute remaining resources (if any) equally between
|
* Distribute remaining resources (if any) equally between hotplug
|
||||||
* hotplug bridges below. This makes it possible to extend the
|
* bridges below. This makes it possible to extend the hierarchy
|
||||||
* hierarchy later without running out of resources.
|
* later without running out of resources.
|
||||||
*/
|
*/
|
||||||
pci_bridge_distribute_available_resources(bridge, &add_list);
|
pci_bridge_distribute_available_resources(bridge, &add_list);
|
||||||
|
|
||||||
@ -2011,7 +2013,7 @@ again:
|
|||||||
goto enable_all;
|
goto enable_all;
|
||||||
|
|
||||||
if (tried_times >= 2) {
|
if (tried_times >= 2) {
|
||||||
/* still fail, don't need to try more */
|
/* Still fail, don't need to try more */
|
||||||
free_list(&fail_head);
|
free_list(&fail_head);
|
||||||
goto enable_all;
|
goto enable_all;
|
||||||
}
|
}
|
||||||
@ -2020,15 +2022,15 @@ again:
|
|||||||
tried_times + 1);
|
tried_times + 1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to release leaf bridge's resources that doesn't fit resource of
|
* Try to release leaf bridge's resources that aren't big enough
|
||||||
* child device under that bridge
|
* to contain child device resources.
|
||||||
*/
|
*/
|
||||||
list_for_each_entry(fail_res, &fail_head, list)
|
list_for_each_entry(fail_res, &fail_head, list)
|
||||||
pci_bus_release_bridge_resources(fail_res->dev->bus,
|
pci_bus_release_bridge_resources(fail_res->dev->bus,
|
||||||
fail_res->flags & PCI_RES_TYPE_MASK,
|
fail_res->flags & PCI_RES_TYPE_MASK,
|
||||||
whole_subtree);
|
whole_subtree);
|
||||||
|
|
||||||
/* restore size and flags */
|
/* Restore size and flags */
|
||||||
list_for_each_entry(fail_res, &fail_head, list) {
|
list_for_each_entry(fail_res, &fail_head, list) {
|
||||||
struct resource *res = fail_res->res;
|
struct resource *res = fail_res->res;
|
||||||
|
|
||||||
@ -2107,7 +2109,7 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(dev_res, &saved, list) {
|
list_for_each_entry(dev_res, &saved, list) {
|
||||||
/* Skip the bridge we just assigned resources for. */
|
/* Skip the bridge we just assigned resources for */
|
||||||
if (bridge == dev_res->dev)
|
if (bridge == dev_res->dev)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -2119,7 +2121,7 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
/* restore size and flags */
|
/* Restore size and flags */
|
||||||
list_for_each_entry(dev_res, &failed, list) {
|
list_for_each_entry(dev_res, &failed, list) {
|
||||||
struct resource *res = dev_res->res;
|
struct resource *res = dev_res->res;
|
||||||
|
|
||||||
@ -2151,8 +2153,8 @@ cleanup:
|
|||||||
void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
|
void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
|
||||||
{
|
{
|
||||||
struct pci_dev *dev;
|
struct pci_dev *dev;
|
||||||
LIST_HEAD(add_list); /* list of resources that
|
/* List of resources that want additional resources */
|
||||||
want additional resources */
|
LIST_HEAD(add_list);
|
||||||
|
|
||||||
down_read(&pci_bus_sem);
|
down_read(&pci_bus_sem);
|
||||||
for_each_pci_bridge(dev, bus)
|
for_each_pci_bridge(dev, bus)
|
||||||
|
Loading…
Reference in New Issue
Block a user