aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/setup-bus.c
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2010-01-22 04:02:24 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-02-22 19:17:22 -0500
commit977d17bb1749517b353874ccdc9b85abc7a58c2a (patch)
tree7abb576779682d20fb71d8656d50741571f0cdb2 /drivers/pci/setup-bus.c
parentd65245c3297ac63abc51a976d92f45f2195d2854 (diff)
PCI: update bridge resources to get more big ranges in PCI assign unssigned
BIOS separates IO ranges between several IOHs, and on some slots, BIOS assigns resources to a bridge, but stops assigning resources to the device under that bridge, because the device needs a big resource. So: 1. allocate resources and record the failed device resources 2. clear the BIOS assigned resources of the parent bridge of failing device 3. go back and call pci assign unassigned 4. if it still fails, go up the tree, clear more bridges. and try again Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r--drivers/pci/setup-bus.c114
1 files changed, 112 insertions, 2 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index f560814c557c..f76f6e90f3b9 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -780,11 +780,65 @@ static void pci_bus_dump_resources(struct pci_bus *bus)
780 } 780 }
781} 781}
782 782
783static int __init pci_bus_get_depth(struct pci_bus *bus)
784{
785 int depth = 0;
786 struct pci_dev *dev;
787
788 list_for_each_entry(dev, &bus->devices, bus_list) {
789 int ret;
790 struct pci_bus *b = dev->subordinate;
791 if (!b)
792 continue;
793
794 ret = pci_bus_get_depth(b);
795 if (ret + 1 > depth)
796 depth = ret + 1;
797 }
798
799 return depth;
800}
801static int __init pci_get_max_depth(void)
802{
803 int depth = 0;
804 struct pci_bus *bus;
805
806 list_for_each_entry(bus, &pci_root_buses, node) {
807 int ret;
808
809 ret = pci_bus_get_depth(bus);
810 if (ret > depth)
811 depth = ret;
812 }
813
814 return depth;
815}
816
817/*
818 * first try will not touch pci bridge res
819 * second and later try will clear small leaf bridge res
820 * will stop till to the max deepth if can not find good one
821 */
783void __init 822void __init
784pci_assign_unassigned_resources(void) 823pci_assign_unassigned_resources(void)
785{ 824{
786 struct pci_bus *bus; 825 struct pci_bus *bus;
826 int tried_times = 0;
827 enum release_type rel_type = leaf_only;
828 struct resource_list_x head, *list;
829 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
830 IORESOURCE_PREFETCH;
831 unsigned long failed_type;
832 int max_depth = pci_get_max_depth();
833 int pci_try_num;
834
835 head.next = NULL;
787 836
837 pci_try_num = max_depth + 1;
838 printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n",
839 max_depth, pci_try_num);
840
841again:
788 /* Depth first, calculate sizes and alignments of all 842 /* Depth first, calculate sizes and alignments of all
789 subordinate buses. */ 843 subordinate buses. */
790 list_for_each_entry(bus, &pci_root_buses, node) { 844 list_for_each_entry(bus, &pci_root_buses, node) {
@@ -792,9 +846,65 @@ pci_assign_unassigned_resources(void)
792 } 846 }
793 /* Depth last, allocate resources and update the hardware. */ 847 /* Depth last, allocate resources and update the hardware. */
794 list_for_each_entry(bus, &pci_root_buses, node) { 848 list_for_each_entry(bus, &pci_root_buses, node) {
795 pci_bus_assign_resources(bus); 849 __pci_bus_assign_resources(bus, &head);
796 pci_enable_bridges(bus); 850 }
851 tried_times++;
852
853 /* any device complain? */
854 if (!head.next)
855 goto enable_and_dump;
856 failed_type = 0;
857 for (list = head.next; list;) {
858 failed_type |= list->flags;
859 list = list->next;
860 }
861 /*
862 * io port are tight, don't try extra
863 * or if reach the limit, don't want to try more
864 */
865 failed_type &= type_mask;
866 if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) {
867 free_failed_list(&head);
868 goto enable_and_dump;
869 }
870
871 printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n",
872 tried_times + 1);
873
874 /* third times and later will not check if it is leaf */
875 if ((tried_times + 1) > 2)
876 rel_type = whole_subtree;
877
878 /*
879 * Try to release leaf bridge's resources that doesn't fit resource of
880 * child device under that bridge
881 */
882 for (list = head.next; list;) {
883 bus = list->dev->bus;
884 pci_bus_release_bridge_resources(bus, list->flags & type_mask,
885 rel_type);
886 list = list->next;
797 } 887 }
888 /* restore size and flags */
889 for (list = head.next; list;) {
890 struct resource *res = list->res;
891
892 res->start = list->start;
893 res->end = list->end;
894 res->flags = list->flags;
895 if (list->dev->subordinate)
896 res->flags = 0;
897
898 list = list->next;
899 }
900 free_failed_list(&head);
901
902 goto again;
903
904enable_and_dump:
905 /* Depth last, update the hardware. */
906 list_for_each_entry(bus, &pci_root_buses, node)
907 pci_enable_bridges(bus);
798 908
799 /* dump the resource on buses */ 909 /* dump the resource on buses */
800 list_for_each_entry(bus, &pci_root_buses, node) { 910 list_for_each_entry(bus, &pci_root_buses, node) {