diff options
Diffstat (limited to 'drivers/acpi/resources/rscreate.c')
| -rw-r--r-- | drivers/acpi/resources/rscreate.c | 41 | 
1 files changed, 29 insertions, 12 deletions
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c index faddaee1bc0..7804a8c40e7 100644 --- a/drivers/acpi/resources/rscreate.c +++ b/drivers/acpi/resources/rscreate.c @@ -181,9 +181,9 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,  	}  	/* -	 * Loop through the ACPI_INTERNAL_OBJECTS - Each object -	 * should be a package that in turn contains an -	 * acpi_integer Address, a u8 Pin, a Name and a u8 source_index. +	 * Loop through the ACPI_INTERNAL_OBJECTS - Each object should be a +	 * package that in turn contains an acpi_integer Address, a u8 Pin, +	 * a Name, and a u8 source_index.  	 */  	top_object_list = package_object->package.elements;  	number_of_elements = package_object->package.count; @@ -240,9 +240,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,  		/* 1) First subobject: Dereference the PRT.Address */  		obj_desc = sub_object_list[0]; -		if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { -			user_prt->address = obj_desc->integer.value; -		} else { +		if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) {  			ACPI_ERROR((AE_INFO,  				    "(PRT[%X].Address) Need Integer, found %s",  				    index, @@ -250,12 +248,12 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,  			return_ACPI_STATUS(AE_BAD_DATA);  		} +		user_prt->address = obj_desc->integer.value; +  		/* 2) Second subobject: Dereference the PRT.Pin */  		obj_desc = sub_object_list[1]; -		if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { -			user_prt->pin = (u32) obj_desc->integer.value; -		} else { +		if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) {  			ACPI_ERROR((AE_INFO,  				    "(PRT[%X].Pin) Need Integer, found %s",  				    index, @@ -284,6 +282,25 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,  			}  		} +		user_prt->pin = (u32) obj_desc->integer.value; + +		/* +		 * If the BIOS has erroneously reversed the _PRT source_name (index 2) +		 * and the source_index (index 3), fix it. _PRT is important enough to +		 * workaround this BIOS error. This also provides compatibility with +		 * other ACPI implementations. +		 */ +		obj_desc = sub_object_list[3]; +		if (!obj_desc +		    || (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { +			sub_object_list[3] = sub_object_list[2]; +			sub_object_list[2] = obj_desc; + +			ACPI_WARNING((AE_INFO, +				      "(PRT[%X].Source) SourceName and SourceIndex are reversed, fixed", +				      index)); +		} +  		/*  		 * 3) Third subobject: Dereference the PRT.source_name  		 * The name may be unresolved (slack mode), so allow a null object @@ -364,9 +381,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,  		/* 4) Fourth subobject: Dereference the PRT.source_index */  		obj_desc = sub_object_list[source_index_index]; -		if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { -			user_prt->source_index = (u32) obj_desc->integer.value; -		} else { +		if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) {  			ACPI_ERROR((AE_INFO,  				    "(PRT[%X].SourceIndex) Need Integer, found %s",  				    index, @@ -374,6 +389,8 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,  			return_ACPI_STATUS(AE_BAD_DATA);  		} +		user_prt->source_index = (u32) obj_desc->integer.value; +  		/* Point to the next union acpi_operand_object in the top level package */  		top_object_list++;  |