diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-01-13 15:00:22 +0000 | 
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-01-13 15:00:22 +0000 | 
| commit | 4de3a8e101150feaefa1139611a50ff37467f33e (patch) | |
| tree | daada742542518b02d7db7c5d32e715eaa5f166d /arch/x86/pci/acpi.c | |
| parent | 294064f58953f9964e5945424b09c51800330a83 (diff) | |
| parent | 099469502f62fbe0d7e4f0b83a2f22538367f734 (diff) | |
| download | olio-linux-3.10-4de3a8e101150feaefa1139611a50ff37467f33e.tar.xz olio-linux-3.10-4de3a8e101150feaefa1139611a50ff37467f33e.zip  | |
Merge branch 'master' into fixes
Diffstat (limited to 'arch/x86/pci/acpi.c')
| -rw-r--r-- | arch/x86/pci/acpi.c | 75 | 
1 files changed, 59 insertions, 16 deletions
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 404f21a3ff9..a312e76063a 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -12,7 +12,7 @@ struct pci_root_info {  	char *name;  	unsigned int res_num;  	struct resource *res; -	struct pci_bus *bus; +	struct list_head *resources;  	int busnum;  }; @@ -24,6 +24,12 @@ static int __init set_use_crs(const struct dmi_system_id *id)  	return 0;  } +static int __init set_nouse_crs(const struct dmi_system_id *id) +{ +	pci_use_crs = false; +	return 0; +} +  static const struct dmi_system_id pci_use_crs_table[] __initconst = {  	/* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */  	{ @@ -54,6 +60,29 @@ static const struct dmi_system_id pci_use_crs_table[] __initconst = {  			DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),  		},  	}, + +	/* Now for the blacklist.. */ + +	/* https://bugzilla.redhat.com/show_bug.cgi?id=769657 */ +	{ +		.callback = set_nouse_crs, +		.ident = "Dell Studio 1557", +		.matches = { +			DMI_MATCH(DMI_BOARD_VENDOR, "Dell Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1557"), +			DMI_MATCH(DMI_BIOS_VERSION, "A09"), +		}, +	}, +	/* https://bugzilla.redhat.com/show_bug.cgi?id=769657 */ +	{ +		.callback = set_nouse_crs, +		.ident = "Thinkpad SL510", +		.matches = { +			DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), +			DMI_MATCH(DMI_BOARD_NAME, "2847DFG"), +			DMI_MATCH(DMI_BIOS_VERSION, "6JET85WW (1.43 )"), +		}, +	},  	{}  }; @@ -149,7 +178,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)  	struct acpi_resource_address64 addr;  	acpi_status status;  	unsigned long flags; -	u64 start, end; +	u64 start, orig_end, end;  	status = resource_to_addr(acpi_res, &addr);  	if (!ACPI_SUCCESS(status)) @@ -165,7 +194,21 @@ setup_resource(struct acpi_resource *acpi_res, void *data)  		return AE_OK;  	start = addr.minimum + addr.translation_offset; -	end = addr.maximum + addr.translation_offset; +	orig_end = end = addr.maximum + addr.translation_offset; + +	/* Exclude non-addressable range or non-addressable portion of range */ +	end = min(end, (u64)iomem_resource.end); +	if (end <= start) { +		dev_info(&info->bridge->dev, +			"host bridge window [%#llx-%#llx] " +			"(ignored, not CPU addressable)\n", start, orig_end); +		return AE_OK; +	} else if (orig_end != end) { +		dev_info(&info->bridge->dev, +			"host bridge window [%#llx-%#llx] " +			"([%#llx-%#llx] ignored, not CPU addressable)\n",  +			start, orig_end, end + 1, orig_end); +	}  	res = &info->res[info->res_num];  	res->name = info->name; @@ -261,23 +304,20 @@ static void add_resources(struct pci_root_info *info)  				 "ignoring host bridge window %pR (conflicts with %s %pR)\n",  				 res, conflict->name, conflict);  		else -			pci_bus_add_resource(info->bus, res, 0); +			pci_add_resource(info->resources, res);  	}  }  static void  get_current_resources(struct acpi_device *device, int busnum, -			int domain, struct pci_bus *bus) +		      int domain, struct list_head *resources)  {  	struct pci_root_info info;  	size_t size; -	if (pci_use_crs) -		pci_bus_remove_resources(bus); -  	info.bridge = device; -	info.bus = bus;  	info.res_num = 0; +	info.resources = resources;  	acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,  				&info);  	if (!info.res_num) @@ -286,7 +326,7 @@ get_current_resources(struct acpi_device *device, int busnum,  	size = sizeof(*info.res) * info.res_num;  	info.res = kmalloc(size, GFP_KERNEL);  	if (!info.res) -		goto res_alloc_fail; +		return;  	info.name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum);  	if (!info.name) @@ -301,8 +341,6 @@ get_current_resources(struct acpi_device *device, int busnum,  name_alloc_fail:  	kfree(info.res); -res_alloc_fail: -	return;  }  struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) @@ -310,6 +348,7 @@ 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; +	LIST_HEAD(resources);  	struct pci_bus *bus;  	struct pci_sysdata *sd;  	int node; @@ -364,11 +403,15 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)  		memcpy(bus->sysdata, sd, sizeof(*sd));  		kfree(sd);  	} else { -		bus = pci_create_bus(NULL, busnum, &pci_root_ops, sd); -		if (bus) { -			get_current_resources(device, busnum, domain, bus); +		get_current_resources(device, busnum, domain, &resources); +		if (list_empty(&resources)) +			x86_pci_root_bus_resources(busnum, &resources); +		bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd, +					  &resources); +		if (bus)  			bus->subordinate = pci_scan_child_bus(bus); -		} +		else +			pci_free_resource_list(&resources);  	}  	/* After the PCI-E bus has been walked and all devices discovered,  |