diff options
author | Yinghai Lu <yinghai@kernel.org> | 2012-02-10 18:33:47 -0500 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2012-02-23 14:59:56 -0500 |
commit | 1184893439b1a7532b579a85a354db12bbf1b277 (patch) | |
tree | cfba5be149def3389707a0773909d44c50b58f30 /drivers/pci/setup-bus.c | |
parent | dcef0d06b34a80071da4496556e85f9bf3b3c0bf (diff) |
PCI: Fix "cardbus bridge resources as optional" size handling
We should not set the requested size to -2; that will confuse the
resource list sorting with align when SIZEALIGN is used.
Change to STARTALIGN and pass align from start; we are safe to do that
just as we do that regular pci bridge. In the long run, we should just
treat cardbus like a regular pci bridge.
Also fix the case when realloc_head is not passed: we should keep the
requested size.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Tested-by: Dominik Brodowski <linux@dominikbrodowski.net>
Acked-by: Ram Pai <linuxram@us.ibm.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r-- | drivers/pci/setup-bus.c | 65 |
1 files changed, 37 insertions, 28 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index d5897c32f66..3b3932a6465 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -898,21 +898,30 @@ static void pci_bus_size_cardbus(struct pci_bus *bus, | |||
898 | { | 898 | { |
899 | struct pci_dev *bridge = bus->self; | 899 | struct pci_dev *bridge = bus->self; |
900 | struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES]; | 900 | struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES]; |
901 | resource_size_t b_res_3_size = pci_cardbus_mem_size * 2; | ||
901 | u16 ctrl; | 902 | u16 ctrl; |
902 | 903 | ||
903 | /* | 904 | /* |
904 | * Reserve some resources for CardBus. We reserve | 905 | * Reserve some resources for CardBus. We reserve |
905 | * a fixed amount of bus space for CardBus bridges. | 906 | * a fixed amount of bus space for CardBus bridges. |
906 | */ | 907 | */ |
907 | b_res[0].start = 0; | 908 | b_res[0].start = pci_cardbus_io_size; |
908 | b_res[0].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN; | 909 | b_res[0].end = b_res[0].start + pci_cardbus_io_size - 1; |
909 | if (realloc_head) | 910 | b_res[0].flags |= IORESOURCE_IO | IORESOURCE_STARTALIGN; |
910 | add_to_list(realloc_head, bridge, b_res, pci_cardbus_io_size, 0 /* dont care */); | 911 | if (realloc_head) { |
912 | b_res[0].end -= pci_cardbus_io_size; | ||
913 | add_to_list(realloc_head, bridge, b_res, pci_cardbus_io_size, | ||
914 | pci_cardbus_io_size); | ||
915 | } | ||
911 | 916 | ||
912 | b_res[1].start = 0; | 917 | b_res[1].start = pci_cardbus_io_size; |
913 | b_res[1].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN; | 918 | b_res[1].end = b_res[1].start + pci_cardbus_io_size - 1; |
914 | if (realloc_head) | 919 | b_res[1].flags |= IORESOURCE_IO | IORESOURCE_STARTALIGN; |
915 | add_to_list(realloc_head, bridge, b_res+1, pci_cardbus_io_size, 0 /* dont care */); | 920 | if (realloc_head) { |
921 | b_res[1].end -= pci_cardbus_io_size; | ||
922 | add_to_list(realloc_head, bridge, b_res+1, pci_cardbus_io_size, | ||
923 | pci_cardbus_io_size); | ||
924 | } | ||
916 | 925 | ||
917 | /* MEM1 must not be pref mmio */ | 926 | /* MEM1 must not be pref mmio */ |
918 | pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl); | 927 | pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl); |
@@ -939,28 +948,28 @@ static void pci_bus_size_cardbus(struct pci_bus *bus, | |||
939 | * twice the size. | 948 | * twice the size. |
940 | */ | 949 | */ |
941 | if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) { | 950 | if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) { |
942 | b_res[2].start = 0; | 951 | b_res[2].start = pci_cardbus_mem_size; |
943 | b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_SIZEALIGN; | 952 | b_res[2].end = b_res[2].start + pci_cardbus_mem_size - 1; |
944 | if (realloc_head) | 953 | b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH | |
945 | add_to_list(realloc_head, bridge, b_res+2, pci_cardbus_mem_size, 0 /* dont care */); | 954 | IORESOURCE_STARTALIGN; |
946 | 955 | if (realloc_head) { | |
947 | b_res[3].start = 0; | 956 | b_res[2].end -= pci_cardbus_mem_size; |
948 | b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN; | 957 | add_to_list(realloc_head, bridge, b_res+2, |
949 | if (realloc_head) | 958 | pci_cardbus_mem_size, pci_cardbus_mem_size); |
950 | add_to_list(realloc_head, bridge, b_res+3, pci_cardbus_mem_size, 0 /* dont care */); | 959 | } |
951 | } else { | 960 | |
952 | b_res[3].start = 0; | 961 | /* reduce that to half */ |
953 | b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN; | 962 | b_res_3_size = pci_cardbus_mem_size; |
954 | if (realloc_head) | ||
955 | add_to_list(realloc_head, bridge, b_res+3, pci_cardbus_mem_size * 2, 0 /* dont care */); | ||
956 | } | 963 | } |
957 | 964 | ||
958 | /* set the size of the resource to zero, so that the resource does not | 965 | b_res[3].start = pci_cardbus_mem_size; |
959 | * get assigned during required-resource allocation cycle but gets assigned | 966 | b_res[3].end = b_res[3].start + b_res_3_size - 1; |
960 | * during the optional-resource allocation cycle. | 967 | b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_STARTALIGN; |
961 | */ | 968 | if (realloc_head) { |
962 | b_res[0].start = b_res[1].start = b_res[2].start = b_res[3].start = 1; | 969 | b_res[3].end -= b_res_3_size; |
963 | b_res[0].end = b_res[1].end = b_res[2].end = b_res[3].end = 0; | 970 | add_to_list(realloc_head, bridge, b_res+3, b_res_3_size, |
971 | pci_cardbus_mem_size); | ||
972 | } | ||
964 | } | 973 | } |
965 | 974 | ||
966 | void __ref __pci_bus_size_bridges(struct pci_bus *bus, | 975 | void __ref __pci_bus_size_bridges(struct pci_bus *bus, |