Commit 6841ec68 authored by Yinghai Lu's avatar Yinghai Lu Committed by Jesse Barnes

PCI: introduce pci_assign_unassigned_bridge_resources

For use by pciehp.

pci_setup_bridge() will not check enabled for the slot bridge, otherwise
update res is not updated to bridge BAR.  That is, bridge is already
enabled for port service.
Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Reviewed-by: default avatarAlex Chiang <achiang@hp.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 977d17bb
...@@ -71,35 +71,34 @@ static void free_failed_list(struct resource_list_x *head) ...@@ -71,35 +71,34 @@ static void free_failed_list(struct resource_list_x *head)
head->next = NULL; head->next = NULL;
} }
static void pbus_assign_resources_sorted(const struct pci_bus *bus, static void __dev_sort_resources(struct pci_dev *dev,
struct resource_list_x *fail_head) struct resource_list *head)
{ {
struct pci_dev *dev;
struct resource *res;
struct resource_list head, *list, *tmp;
int idx;
head.next = NULL;
list_for_each_entry(dev, &bus->devices, bus_list) {
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 || if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST)
class == PCI_CLASS_BRIDGE_HOST) return;
continue;
/* 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);
if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY))
continue; return;
} }
pdev_sort_resources(dev, &head); pdev_sort_resources(dev, head);
} }
for (list = head.next; list;) { static void __assign_resources_sorted(struct resource_list *head,
struct resource_list_x *fail_head)
{
struct resource *res;
struct resource_list *list, *tmp;
int idx;
for (list = head->next; list;) {
res = list->res; res = list->res;
idx = res - &list->dev->resource[0]; idx = res - &list->dev->resource[0];
if (pci_assign_resource(list->dev, idx)) { if (pci_assign_resource(list->dev, idx)) {
...@@ -115,6 +114,30 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus, ...@@ -115,6 +114,30 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus,
} }
} }
static void pdev_assign_resources_sorted(struct pci_dev *dev,
struct resource_list_x *fail_head)
{
struct resource_list head;
head.next = NULL;
__dev_sort_resources(dev, &head);
__assign_resources_sorted(&head, fail_head);
}
static void pbus_assign_resources_sorted(const struct pci_bus *bus,
struct resource_list_x *fail_head)
{
struct pci_dev *dev;
struct resource_list head;
head.next = NULL;
list_for_each_entry(dev, &bus->devices, bus_list)
__dev_sort_resources(dev, &head);
__assign_resources_sorted(&head, fail_head);
}
void pci_setup_cardbus(struct pci_bus *bus) void pci_setup_cardbus(struct pci_bus *bus)
{ {
struct pci_dev *bridge = bus->self; struct pci_dev *bridge = bus->self;
...@@ -273,9 +296,6 @@ static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type) ...@@ -273,9 +296,6 @@ static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type)
{ {
struct pci_dev *bridge = bus->self; struct pci_dev *bridge = bus->self;
if (pci_is_enabled(bridge))
return;
dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n", dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n",
bus->secondary, bus->subordinate); bus->secondary, bus->subordinate);
...@@ -646,6 +666,7 @@ static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, ...@@ -646,6 +666,7 @@ static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
switch (dev->class >> 8) { switch (dev->class >> 8) {
case PCI_CLASS_BRIDGE_PCI: case PCI_CLASS_BRIDGE_PCI:
if (!pci_is_enabled(dev))
pci_setup_bridge(b); pci_setup_bridge(b);
break; break;
...@@ -667,6 +688,34 @@ void __ref pci_bus_assign_resources(const struct pci_bus *bus) ...@@ -667,6 +688,34 @@ void __ref pci_bus_assign_resources(const struct pci_bus *bus)
} }
EXPORT_SYMBOL(pci_bus_assign_resources); EXPORT_SYMBOL(pci_bus_assign_resources);
static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge,
struct resource_list_x *fail_head)
{
struct pci_bus *b;
pdev_assign_resources_sorted((struct pci_dev *)bridge, fail_head);
b = bridge->subordinate;
if (!b)
return;
__pci_bus_assign_resources(b, fail_head);
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:
dev_info(&bridge->dev, "not setting up bridge for bus "
"%04x:%02x\n", pci_domain_nr(b), b->number);
break;
}
}
static void pci_bridge_release_resources(struct pci_bus *bus, static void pci_bridge_release_resources(struct pci_bus *bus,
unsigned long type) unsigned long type)
{ {
...@@ -911,3 +960,16 @@ pci_assign_unassigned_resources(void) ...@@ -911,3 +960,16 @@ pci_assign_unassigned_resources(void)
pci_bus_dump_resources(bus); pci_bus_dump_resources(bus);
} }
} }
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
{
struct pci_bus *parent = bridge->subordinate;
int retval;
pci_bus_size_bridges(parent);
__pci_bridge_assign_resources(bridge, NULL);
retval = pci_reenable_device(bridge);
pci_set_master(bridge);
pci_enable_bridges(parent);
}
EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
...@@ -801,6 +801,7 @@ void pci_bus_assign_resources(const struct pci_bus *bus); ...@@ -801,6 +801,7 @@ void pci_bus_assign_resources(const struct pci_bus *bus);
void pci_bus_size_bridges(struct pci_bus *bus); void pci_bus_size_bridges(struct pci_bus *bus);
int pci_claim_resource(struct pci_dev *, int); int pci_claim_resource(struct pci_dev *, int);
void pci_assign_unassigned_resources(void); void pci_assign_unassigned_resources(void);
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge);
void pdev_enable_device(struct pci_dev *); void pdev_enable_device(struct pci_dev *);
void pdev_sort_resources(struct pci_dev *, struct resource_list *); void pdev_sort_resources(struct pci_dev *, struct resource_list *);
int pci_enable_resources(struct pci_dev *, int mask); int pci_enable_resources(struct pci_dev *, int mask);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment