]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'bjorn-pci-root-v4-2.6.35' into release
authorLen Brown <len.brown@intel.com>
Fri, 28 May 2010 20:17:16 +0000 (16:17 -0400)
committerLen Brown <len.brown@intel.com>
Fri, 28 May 2010 20:17:16 +0000 (16:17 -0400)
1  2 
arch/x86/pci/acpi.c
drivers/acpi/pci_root.c

diff --combined arch/x86/pci/acpi.c
index 31930fd30ea95a36232c2ed7df0a6a1f97147b1f,0b7882dbe784a870da04f44a4faafd5f82c77508..9dcf43d7d0c091e20550c7e393e5f055307e3d08
@@@ -3,7 -3,6 +3,7 @@@
  #include <linux/init.h>
  #include <linux/irq.h>
  #include <linux/dmi.h>
 +#include <linux/slab.h>
  #include <asm/numa.h>
  #include <asm/pci_x86.h>
  
@@@ -66,44 -65,14 +66,44 @@@ resource_to_addr(struct acpi_resource *
                        struct acpi_resource_address64 *addr)
  {
        acpi_status status;
 -
 -      status = acpi_resource_to_address64(resource, addr);
 -      if (ACPI_SUCCESS(status) &&
 -          (addr->resource_type == ACPI_MEMORY_RANGE ||
 -          addr->resource_type == ACPI_IO_RANGE) &&
 -          addr->address_length > 0 &&
 -          addr->producer_consumer == ACPI_PRODUCER) {
 +      struct acpi_resource_memory24 *memory24;
 +      struct acpi_resource_memory32 *memory32;
 +      struct acpi_resource_fixed_memory32 *fixed_memory32;
 +
 +      memset(addr, 0, sizeof(*addr));
 +      switch (resource->type) {
 +      case ACPI_RESOURCE_TYPE_MEMORY24:
 +              memory24 = &resource->data.memory24;
 +              addr->resource_type = ACPI_MEMORY_RANGE;
 +              addr->minimum = memory24->minimum;
 +              addr->address_length = memory24->address_length;
 +              addr->maximum = addr->minimum + addr->address_length - 1;
 +              return AE_OK;
 +      case ACPI_RESOURCE_TYPE_MEMORY32:
 +              memory32 = &resource->data.memory32;
 +              addr->resource_type = ACPI_MEMORY_RANGE;
 +              addr->minimum = memory32->minimum;
 +              addr->address_length = memory32->address_length;
 +              addr->maximum = addr->minimum + addr->address_length - 1;
                return AE_OK;
 +      case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
 +              fixed_memory32 = &resource->data.fixed_memory32;
 +              addr->resource_type = ACPI_MEMORY_RANGE;
 +              addr->minimum = fixed_memory32->address;
 +              addr->address_length = fixed_memory32->address_length;
 +              addr->maximum = addr->minimum + addr->address_length - 1;
 +              return AE_OK;
 +      case ACPI_RESOURCE_TYPE_ADDRESS16:
 +      case ACPI_RESOURCE_TYPE_ADDRESS32:
 +      case ACPI_RESOURCE_TYPE_ADDRESS64:
 +              status = acpi_resource_to_address64(resource, addr);
 +              if (ACPI_SUCCESS(status) &&
 +                  (addr->resource_type == ACPI_MEMORY_RANGE ||
 +                  addr->resource_type == ACPI_IO_RANGE) &&
 +                  addr->address_length > 0) {
 +                      return AE_OK;
 +              }
 +              break;
        }
        return AE_ERROR;
  }
@@@ -121,6 -90,30 +121,6 @@@ count_resource(struct acpi_resource *ac
        return AE_OK;
  }
  
 -static void
 -align_resource(struct acpi_device *bridge, struct resource *res)
 -{
 -      int align = (res->flags & IORESOURCE_MEM) ? 16 : 4;
 -
 -      /*
 -       * Host bridge windows are not BARs, but the decoders on the PCI side
 -       * that claim this address space have starting alignment and length
 -       * constraints, so fix any obvious BIOS goofs.
 -       */
 -      if (!IS_ALIGNED(res->start, align)) {
 -              dev_printk(KERN_DEBUG, &bridge->dev,
 -                         "host bridge window %pR invalid; "
 -                         "aligning start to %d-byte boundary\n", res, align);
 -              res->start &= ~(align - 1);
 -      }
 -      if (!IS_ALIGNED(res->end + 1, align)) {
 -              dev_printk(KERN_DEBUG, &bridge->dev,
 -                         "host bridge window %pR invalid; "
 -                         "aligning end to %d-byte boundary\n", res, align);
 -              res->end = ALIGN(res->end, align) - 1;
 -      }
 -}
 -
  static acpi_status
  setup_resource(struct acpi_resource *acpi_res, void *data)
  {
        acpi_status status;
        unsigned long flags;
        struct resource *root, *conflict;
 -      u64 start, end, max_len;
 +      u64 start, end;
  
        status = resource_to_addr(acpi_res, &addr);
        if (!ACPI_SUCCESS(status))
        } else
                return AE_OK;
  
 -      max_len = addr.maximum - addr.minimum + 1;
 -      if (addr.address_length > max_len) {
 -              dev_printk(KERN_DEBUG, &info->bridge->dev,
 -                         "host bridge window length %#llx doesn't fit in "
 -                         "%#llx-%#llx, trimming\n",
 -                         (unsigned long long) addr.address_length,
 -                         (unsigned long long) addr.minimum,
 -                         (unsigned long long) addr.maximum);
 -              addr.address_length = max_len;
 -      }
 -
        start = addr.minimum + addr.translation_offset;
 -      end = start + addr.address_length - 1;
 +      end = addr.maximum + addr.translation_offset;
  
        res = &info->res[info->res_num];
        res->name = info->name;
        res->start = start;
        res->end = end;
        res->child = NULL;
 -      align_resource(info->bridge, res);
  
        if (!pci_use_crs) {
                dev_printk(KERN_DEBUG, &info->bridge->dev,
@@@ -224,8 -229,11 +224,11 @@@ res_alloc_fail
        return;
  }
  
- struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
+ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
  {
+       struct acpi_device *device = root->device;
+       int domain = root->segment;
+       int busnum = root->secondary.start;
        struct pci_bus *bus;
        struct pci_sysdata *sd;
        int node;
diff --combined drivers/acpi/pci_root.c
index aefce33f2a09c88d8fb3fec7b2bd7fa57a899de2,680450c905b32f1feb7d042262128bb402414c0a..4eac59393edc5b13e3c25283f08e6cf899fb61d7
@@@ -34,7 -34,6 +34,7 @@@
  #include <linux/pci.h>
  #include <linux/pci-acpi.h>
  #include <linux/acpi.h>
 +#include <linux/slab.h>
  #include <acpi/acpi_bus.h>
  #include <acpi/acpi_drivers.h>
  
@@@ -120,7 -119,8 +120,8 @@@ acpi_handle acpi_get_pci_rootbridge_han
        struct acpi_pci_root *root;
        
        list_for_each_entry(root, &acpi_pci_roots, node)
-               if ((root->segment == (u16) seg) && (root->bus_nr == (u16) bus))
+               if ((root->segment == (u16) seg) &&
+                   (root->secondary.start == (u16) bus))
                        return root->device->handle;
        return NULL;            
  }
@@@ -154,7 -154,7 +155,7 @@@ EXPORT_SYMBOL_GPL(acpi_is_root_bridge)
  static acpi_status
  get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
  {
-       int *busnr = data;
+       struct resource *res = data;
        struct acpi_resource_address64 address;
  
        if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
  
        acpi_resource_to_address64(resource, &address);
        if ((address.address_length > 0) &&
-           (address.resource_type == ACPI_BUS_NUMBER_RANGE))
-               *busnr = address.minimum;
+           (address.resource_type == ACPI_BUS_NUMBER_RANGE)) {
+               res->start = address.minimum;
+               res->end = address.minimum + address.address_length - 1;
+       }
  
        return AE_OK;
  }
  
  static acpi_status try_get_root_bridge_busnr(acpi_handle handle,
-                                            unsigned long long *bus)
+                                            struct resource *res)
  {
        acpi_status status;
-       int busnum;
  
-       busnum = -1;
+       res->start = -1;
        status =
            acpi_walk_resources(handle, METHOD_NAME__CRS,
-                               get_root_bridge_busnr_callback, &busnum);
+                               get_root_bridge_busnr_callback, res);
        if (ACPI_FAILURE(status))
                return status;
-       /* Check if we really get a bus number from _CRS */
-       if (busnum == -1)
+       if (res->start == -1)
                return AE_ERROR;
-       *bus = busnum;
        return AE_OK;
  }
  
@@@ -429,34 -428,47 +429,47 @@@ static int __devinit acpi_pci_root_add(
        struct acpi_device *child;
        u32 flags, base_flags;
  
+       root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
+       if (!root)
+               return -ENOMEM;
        segment = 0;
        status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
                                       &segment);
        if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
                printk(KERN_ERR PREFIX "can't evaluate _SEG\n");
-               return -ENODEV;
+               result = -ENODEV;
+               goto end;
        }
  
        /* Check _CRS first, then _BBN.  If no _BBN, default to zero. */
-       bus = 0;
-       status = try_get_root_bridge_busnr(device->handle, &bus);
+       root->secondary.flags = IORESOURCE_BUS;
+       status = try_get_root_bridge_busnr(device->handle, &root->secondary);
        if (ACPI_FAILURE(status)) {
+               /*
+                * We need both the start and end of the downstream bus range
+                * to interpret _CBA (MMCONFIG base address), so it really is
+                * supposed to be in _CRS.  If we don't find it there, all we
+                * can do is assume [_BBN-0xFF] or [0-0xFF].
+                */
+               root->secondary.end = 0xFF;
+               printk(KERN_WARNING FW_BUG PREFIX
+                      "no secondary bus range in _CRS\n");
                status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN,                                               NULL, &bus);
-               if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-                       printk(KERN_ERR PREFIX
-                            "no bus number in _CRS and can't evaluate _BBN\n");
-                       return -ENODEV;
+               if (ACPI_SUCCESS(status))
+                       root->secondary.start = bus;
+               else if (status == AE_NOT_FOUND)
+                       root->secondary.start = 0;
+               else {
+                       printk(KERN_ERR PREFIX "can't evaluate _BBN\n");
+                       result = -ENODEV;
+                       goto end;
                }
        }
  
-       root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
-       if (!root)
-               return -ENOMEM;
        INIT_LIST_HEAD(&root->node);
        root->device = device;
        root->segment = segment & 0xFFFF;
-       root->bus_nr = bus & 0xFF;
        strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
        device->driver_data = root;
        /* TBD: Locking */
        list_add_tail(&root->node, &acpi_pci_roots);
  
-       printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n",
+       printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
               acpi_device_name(device), acpi_device_bid(device),
-              root->segment, root->bus_nr);
+              root->segment, &root->secondary);
  
        /*
         * Scan the Root Bridge
         * PCI namespace does not get created until this call is made (and 
         * thus the root bridge's pci_dev does not exist).
         */
-       root->bus = pci_acpi_scan_root(device, segment, bus);
+       root->bus = pci_acpi_scan_root(root);
        if (!root->bus) {
                printk(KERN_ERR PREFIX
                            "Bus %04x:%02x not present in PCI namespace\n",
-                           root->segment, root->bus_nr);
+                           root->segment, (unsigned int)root->secondary.start);
                result = -ENODEV;
                goto end;
        }