aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/setup-bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r--drivers/pci/setup-bus.c116
1 files changed, 89 insertions, 27 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index f76f6e90f3b9..b19a56b8b17a 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -71,35 +71,34 @@ static void free_failed_list(struct resource_list_x *head)
71 head->next = NULL; 71 head->next = NULL;
72} 72}
73 73
74static void pbus_assign_resources_sorted(const struct pci_bus *bus, 74static void __dev_sort_resources(struct pci_dev *dev,
75 struct resource_list_x *fail_head) 75 struct resource_list *head)
76{ 76{
77 struct pci_dev *dev; 77 u16 class = dev->class >> 8;
78 struct resource *res;
79 struct resource_list head, *list, *tmp;
80 int idx;
81 78
82 head.next = NULL; 79 /* Don't touch classless devices or host bridges or ioapics. */
83 list_for_each_entry(dev, &bus->devices, bus_list) { 80 if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST)
84 u16 class = dev->class >> 8; 81 return;
85 82
86 /* Don't touch classless devices or host bridges or ioapics. */ 83 /* Don't touch ioapic devices already enabled by firmware */
87 if (class == PCI_CLASS_NOT_DEFINED || 84 if (class == PCI_CLASS_SYSTEM_PIC) {
88 class == PCI_CLASS_BRIDGE_HOST) 85 u16 command;
89 continue; 86 pci_read_config_word(dev, PCI_COMMAND, &command);
87 if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY))
88 return;
89 }
90 90
91 /* Don't touch ioapic devices already enabled by firmware */ 91 pdev_sort_resources(dev, head);
92 if (class == PCI_CLASS_SYSTEM_PIC) { 92}
93 u16 command;
94 pci_read_config_word(dev, PCI_COMMAND, &command);
95 if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY))
96 continue;
97 }
98 93
99 pdev_sort_resources(dev, &head); 94static void __assign_resources_sorted(struct resource_list *head,
100 } 95 struct resource_list_x *fail_head)
96{
97 struct resource *res;
98 struct resource_list *list, *tmp;
99 int idx;
101 100
102 for (list = head.next; list;) { 101 for (list = head->next; list;) {
103 res = list->res; 102 res = list->res;
104 idx = res - &list->dev->resource[0]; 103 idx = res - &list->dev->resource[0];
105 if (pci_assign_resource(list->dev, idx)) { 104 if (pci_assign_resource(list->dev, idx)) {
@@ -115,6 +114,30 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus,
115 } 114 }
116} 115}
117 116
117static void pdev_assign_resources_sorted(struct pci_dev *dev,
118 struct resource_list_x *fail_head)
119{
120 struct resource_list head;
121
122 head.next = NULL;
123 __dev_sort_resources(dev, &head);
124 __assign_resources_sorted(&head, fail_head);
125
126}
127
128static void pbus_assign_resources_sorted(const struct pci_bus *bus,
129 struct resource_list_x *fail_head)
130{
131 struct pci_dev *dev;
132 struct resource_list head;
133
134 head.next = NULL;
135 list_for_each_entry(dev, &bus->devices, bus_list)
136 __dev_sort_resources(dev, &head);
137
138 __assign_resources_sorted(&head, fail_head);
139}
140
118void pci_setup_cardbus(struct pci_bus *bus) 141void pci_setup_cardbus(struct pci_bus *bus)
119{ 142{
120 struct pci_dev *bridge = bus->self; 143 struct pci_dev *bridge = bus->self;
@@ -273,9 +296,6 @@ static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type)
273{ 296{
274 struct pci_dev *bridge = bus->self; 297 struct pci_dev *bridge = bus->self;
275 298
276 if (pci_is_enabled(bridge))
277 return;
278
279 dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n", 299 dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n",
280 bus->secondary, bus->subordinate); 300 bus->secondary, bus->subordinate);
281 301
@@ -646,7 +666,8 @@ static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
646 666
647 switch (dev->class >> 8) { 667 switch (dev->class >> 8) {
648 case PCI_CLASS_BRIDGE_PCI: 668 case PCI_CLASS_BRIDGE_PCI:
649 pci_setup_bridge(b); 669 if (!pci_is_enabled(dev))
670 pci_setup_bridge(b);
650 break; 671 break;
651 672
652 case PCI_CLASS_BRIDGE_CARDBUS: 673 case PCI_CLASS_BRIDGE_CARDBUS:
@@ -667,6 +688,34 @@ void __ref pci_bus_assign_resources(const struct pci_bus *bus)
667} 688}
668EXPORT_SYMBOL(pci_bus_assign_resources); 689EXPORT_SYMBOL(pci_bus_assign_resources);
669 690
691static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge,
692 struct resource_list_x *fail_head)
693{
694 struct pci_bus *b;
695
696 pdev_assign_resources_sorted((struct pci_dev *)bridge, fail_head);
697
698 b = bridge->subordinate;
699 if (!b)
700 return;
701
702 __pci_bus_assign_resources(b, fail_head);
703
704 switch (bridge->class >> 8) {
705 case PCI_CLASS_BRIDGE_PCI:
706 pci_setup_bridge(b);
707 break;
708
709 case PCI_CLASS_BRIDGE_CARDBUS:
710 pci_setup_cardbus(b);
711 break;
712
713 default:
714 dev_info(&bridge->dev, "not setting up bridge for bus "
715 "%04x:%02x\n", pci_domain_nr(b), b->number);
716 break;
717 }
718}
670static void pci_bridge_release_resources(struct pci_bus *bus, 719static void pci_bridge_release_resources(struct pci_bus *bus,
671 unsigned long type) 720 unsigned long type)
672{ 721{
@@ -911,3 +960,16 @@ enable_and_dump:
911 pci_bus_dump_resources(bus); 960 pci_bus_dump_resources(bus);
912 } 961 }
913} 962}
963
964void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
965{
966 struct pci_bus *parent = bridge->subordinate;
967 int retval;
968
969 pci_bus_size_bridges(parent);
970 __pci_bridge_assign_resources(bridge, NULL);
971 retval = pci_reenable_device(bridge);
972 pci_set_master(bridge);
973 pci_enable_bridges(parent);
974}
975EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);