diff options
| author | Len Brown <len.brown@intel.com> | 2010-05-28 16:17:16 -0400 | 
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2010-05-28 16:17:16 -0400 | 
| commit | dc1544ea5d6dfdf29440295788e639e4b44c605a (patch) | |
| tree | fd4a26e78c32a43a7eb59860774f7f960f91a60c /drivers/acpi/pci_root.c | |
| parent | 6e320ec1d98f9eb93d5b2a5d70e2f40dce923f1b (diff) | |
| parent | 57283776b2b821ba4d592f61cad04d0293412740 (diff) | |
| download | olio-linux-3.10-dc1544ea5d6dfdf29440295788e639e4b44c605a.tar.xz olio-linux-3.10-dc1544ea5d6dfdf29440295788e639e4b44c605a.zip  | |
Merge branch 'bjorn-pci-root-v4-2.6.35' into release
Diffstat (limited to 'drivers/acpi/pci_root.c')
| -rw-r--r-- | drivers/acpi/pci_root.c | 67 | 
1 files changed, 40 insertions, 27 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index aefce33f2a0..4eac59393ed 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -120,7 +120,8 @@ acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus)  	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 +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 && @@ -164,28 +165,27 @@ get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)  	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 +429,47 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)  	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; @@ -475,9 +488,9 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)  	/* 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 @@ -486,11 +499,11 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)  	 * 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;  	}  |