diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 3f0173f45019a99bfa0616e3a290c7feb7a100ad..e9acd5540d297dbd7f5bf2e5a6d48c7d46696053 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1318,6 +1318,8 @@ and is between 256 and 4096 characters. It is defined in the file
 				IRQ routing is enabled.
 		noacpi		[X86-32] Do not use ACPI for IRQ routing
 				or for PCI scanning.
+		use_crs		[X86-32] Use _CRS for PCI resource
+				allocation.
 		routeirq	Do IRQ routing for all PCI devices.
 				This is normally done in pci_enable_device(),
 				so this option is a temporary workaround
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 1dd6f3fc077db0724aaea14752577c6882b23bed..c6fd3a6afa4268b5aca819561365723e67902d7c 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -45,6 +45,142 @@ static struct dmi_system_id acpi_pciprobe_dmi_table[] = {
 	{}
 };
 
+struct pci_root_info {
+	char *name;
+	unsigned int res_num;
+	struct resource *res;
+	struct pci_bus *bus;
+	int busnum;
+};
+
+static acpi_status
+resource_to_addr(struct acpi_resource *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) {
+		return AE_OK;
+	}
+	return AE_ERROR;
+}
+
+static acpi_status
+count_resource(struct acpi_resource *acpi_res, void *data)
+{
+	struct pci_root_info *info = data;
+	struct acpi_resource_address64 addr;
+	acpi_status status;
+
+	status = resource_to_addr(acpi_res, &addr);
+	if (ACPI_SUCCESS(status))
+		info->res_num++;
+	return AE_OK;
+}
+
+static acpi_status
+setup_resource(struct acpi_resource *acpi_res, void *data)
+{
+	struct pci_root_info *info = data;
+	struct resource *res;
+	struct acpi_resource_address64 addr;
+	acpi_status status;
+	unsigned long flags;
+	struct resource *root;
+
+	status = resource_to_addr(acpi_res, &addr);
+	if (!ACPI_SUCCESS(status))
+		return AE_OK;
+
+	if (addr.resource_type == ACPI_MEMORY_RANGE) {
+		root = &iomem_resource;
+		flags = IORESOURCE_MEM;
+		if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
+			flags |= IORESOURCE_PREFETCH;
+	} else if (addr.resource_type == ACPI_IO_RANGE) {
+		root = &ioport_resource;
+		flags = IORESOURCE_IO;
+	} else
+		return AE_OK;
+
+	res = &info->res[info->res_num];
+	res->name = info->name;
+	res->flags = flags;
+	res->start = addr.minimum + addr.translation_offset;
+	res->end = res->start + addr.address_length - 1;
+	res->child = NULL;
+
+	if (insert_resource(root, res)) {
+		printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx "
+			"from %s for %s\n", (unsigned long) res->start,
+			(unsigned long) res->end, root->name, info->name);
+	} else {
+		info->bus->resource[info->res_num] = res;
+		info->res_num++;
+	}
+	return AE_OK;
+}
+
+static void
+adjust_transparent_bridge_resources(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		int i;
+		u16 class = dev->class >> 8;
+
+		if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent) {
+			for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++)
+				dev->subordinate->resource[i] =
+						dev->bus->resource[i - 3];
+		}
+	}
+}
+
+static void
+get_current_resources(struct acpi_device *device, int busnum,
+			struct pci_bus *bus)
+{
+	struct pci_root_info info;
+	size_t size;
+
+	info.bus = bus;
+	info.res_num = 0;
+	acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
+				&info);
+	if (!info.res_num)
+		return;
+
+	size = sizeof(*info.res) * info.res_num;
+	info.res = kmalloc(size, GFP_KERNEL);
+	if (!info.res)
+		goto res_alloc_fail;
+
+	info.name = kmalloc(12, GFP_KERNEL);
+	if (!info.name)
+		goto name_alloc_fail;
+	sprintf(info.name, "PCI Bus #%02x", busnum);
+
+	info.res_num = 0;
+	acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
+				&info);
+	if (info.res_num)
+		adjust_transparent_bridge_resources(bus);
+
+	return;
+
+name_alloc_fail:
+	kfree(info.res);
+res_alloc_fail:
+	return;
+}
+
 struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
 {
 	struct pci_bus *bus;
@@ -89,6 +225,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
 		}
 	}
 #endif
+
+	if (bus && (pci_probe & PCI_USE__CRS))
+		get_current_resources(device, busnum, bus);
 	
 	return bus;
 }
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 7c4d75e3c5f3dc4e207af3ee5c7c30ddda72c022..7d6a9a5aa7cdcd326273e586cd45f49a492c8497 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -436,6 +436,9 @@ char * __devinit  pcibios_setup(char *str)
 	} else if (!strcmp(str, "assign-busses")) {
 		pci_probe |= PCI_ASSIGN_ALL_BUSSES;
 		return NULL;
+	} else if (!strcmp(str, "use_crs")) {
+		pci_probe |= PCI_USE__CRS;
+		return NULL;
 	} else if (!strcmp(str, "routeirq")) {
 		pci_routeirq = 1;
 		return NULL;
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h
index 057f335fa3f6d1aa8d84ac049865d421aed83235..ac56d3916c50e3491ff6ca0421950a3f3a3efc39 100644
--- a/arch/x86/pci/pci.h
+++ b/arch/x86/pci/pci.h
@@ -27,6 +27,7 @@
 #define PCI_BIOS_IRQ_SCAN	0x2000
 #define PCI_ASSIGN_ALL_BUSSES	0x4000
 #define PCI_CAN_SKIP_ISA_ALIGN	0x8000
+#define PCI_USE__CRS		0x10000
 
 extern unsigned int pci_probe;
 extern unsigned long pirq_table_addr;