diff options
Diffstat (limited to 'drivers/acpi/scan.c')
| -rw-r--r-- | drivers/acpi/scan.c | 186 | 
1 files changed, 116 insertions, 70 deletions
| diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 2c80765670bc..1331756d4cfc 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -19,6 +19,7 @@  #include <linux/dma-map-ops.h>  #include <linux/platform_data/x86/apple.h>  #include <linux/pgtable.h> +#include <linux/crc32.h>  #include "internal.h" @@ -135,12 +136,12 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent)  static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data,  				    void **ret_p)  { -	struct acpi_device *device = NULL; +	struct acpi_device *device = acpi_fetch_acpi_dev(handle);  	struct acpi_device_physical_node *pn;  	bool second_pass = (bool)data;  	acpi_status status = AE_OK; -	if (acpi_bus_get_device(handle, &device)) +	if (!device)  		return AE_OK;  	if (device->handler && !device->handler->hotplug.enabled) { @@ -180,10 +181,10 @@ static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data,  static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data,  				   void **ret_p)  { -	struct acpi_device *device = NULL; +	struct acpi_device *device = acpi_fetch_acpi_dev(handle);  	struct acpi_device_physical_node *pn; -	if (acpi_bus_get_device(handle, &device)) +	if (!device)  		return AE_OK;  	mutex_lock(&device->physical_node_lock); @@ -599,6 +600,19 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)  }  EXPORT_SYMBOL(acpi_bus_get_device); +/** + * acpi_fetch_acpi_dev - Retrieve ACPI device object. + * @handle: ACPI handle associated with the requested ACPI device object. + * + * Return a pointer to the ACPI device object associated with @handle, if + * present, or NULL otherwise. + */ +struct acpi_device *acpi_fetch_acpi_dev(acpi_handle handle) +{ +	return handle_to_device(handle, NULL); +} +EXPORT_SYMBOL_GPL(acpi_fetch_acpi_dev); +  static void get_acpi_device(void *dev)  {  	acpi_dev_get(dev); @@ -654,6 +668,19 @@ static int acpi_tie_acpi_dev(struct acpi_device *adev)  	return 0;  } +static void acpi_store_pld_crc(struct acpi_device *adev) +{ +	struct acpi_pld_info *pld; +	acpi_status status; + +	status = acpi_get_physical_device_location(adev->handle, &pld); +	if (ACPI_FAILURE(status)) +		return; + +	adev->pld_crc = crc32(~0, pld, sizeof(*pld)); +	ACPI_FREE(pld); +} +  static int __acpi_device_add(struct acpi_device *device,  			     void (*release)(struct device *))  { @@ -712,6 +739,8 @@ static int __acpi_device_add(struct acpi_device *device,  	if (device->wakeup.flags.valid)  		list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list); +	acpi_store_pld_crc(device); +  	mutex_unlock(&acpi_device_lock);  	if (device->parent) @@ -797,9 +826,15 @@ static const char * const acpi_ignore_dep_ids[] = {  	NULL  }; +/* List of HIDs for which we honor deps of matching ACPI devs, when checking _DEP lists. */ +static const char * const acpi_honor_dep_ids[] = { +	"INT3472", /* Camera sensor PMIC / clk and regulator info */ +	NULL +}; +  static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)  { -	struct acpi_device *device = NULL; +	struct acpi_device *device;  	acpi_status status;  	/* @@ -814,7 +849,9 @@ static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)  		status = acpi_get_parent(handle, &handle);  		if (ACPI_FAILURE(status))  			return status == AE_NULL_ENTRY ? NULL : acpi_root; -	} while (acpi_bus_get_device(handle, &device)); + +		device = acpi_fetch_acpi_dev(handle); +	} while (!device);  	return device;  } @@ -1340,11 +1377,11 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,  		if (info->valid & ACPI_VALID_HID) {  			acpi_add_id(pnp, info->hardware_id.string);  			pnp->type.platform_id = 1; -		} -		if (info->valid & ACPI_VALID_CID) { -			cid_list = &info->compatible_id_list; -			for (i = 0; i < cid_list->count; i++) -				acpi_add_id(pnp, cid_list->ids[i].string); +			if (info->valid & ACPI_VALID_CID) { +				cid_list = &info->compatible_id_list; +				for (i = 0; i < cid_list->count; i++) +					acpi_add_id(pnp, cid_list->ids[i].string); +			}  		}  		if (info->valid & ACPI_VALID_ADR) {  			pnp->bus_address = info->address; @@ -1695,6 +1732,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)  {  	struct list_head resource_list;  	bool is_serial_bus_slave = false; +	static const struct acpi_device_id ignore_serial_bus_ids[] = {  	/*  	 * These devices have multiple I2cSerialBus resources and an i2c-client  	 * must be instantiated for each, each with its own i2c_device_id. @@ -1703,11 +1741,18 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)  	 * drivers/platform/x86/i2c-multi-instantiate.c driver, which knows  	 * which i2c_device_id to use for each resource.  	 */ -	static const struct acpi_device_id i2c_multi_instantiate_ids[] = {  		{"BSG1160", },  		{"BSG2150", },  		{"INT33FE", },  		{"INT3515", }, +	/* +	 * HIDs of device with an UartSerialBusV2 resource for which userspace +	 * expects a regular tty cdev to be created (instead of the in kernel +	 * serdev) and which have a kernel driver which expects a platform_dev +	 * such as the rfkill-gpio driver. +	 */ +		{"BCM4752", }, +		{"LNV4752", },  		{}  	}; @@ -1721,8 +1766,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)  	     fwnode_property_present(&device->fwnode, "baud")))  		return true; -	/* Instantiate a pdev for the i2c-multi-instantiate drv to bind to */ -	if (!acpi_match_device_ids(device, i2c_multi_instantiate_ids)) +	if (!acpi_match_device_ids(device, ignore_serial_bus_ids))  		return false;  	INIT_LIST_HEAD(&resource_list); @@ -1762,8 +1806,12 @@ static void acpi_scan_dep_init(struct acpi_device *adev)  	struct acpi_dep_data *dep;  	list_for_each_entry(dep, &acpi_dep_list, node) { -		if (dep->consumer == adev->handle) +		if (dep->consumer == adev->handle) { +			if (dep->honor_dep) +				adev->flags.honor_deps = 1; +  			adev->dep_unmet++; +		}  	}  } @@ -1967,7 +2015,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)  	for (count = 0, i = 0; i < dep_devices.count; i++) {  		struct acpi_device_info *info;  		struct acpi_dep_data *dep; -		bool skip; +		bool skip, honor_dep;  		status = acpi_get_object_info(dep_devices.handles[i], &info);  		if (ACPI_FAILURE(status)) { @@ -1976,6 +2024,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)  		}  		skip = acpi_info_matches_ids(info, acpi_ignore_dep_ids); +		honor_dep = acpi_info_matches_ids(info, acpi_honor_dep_ids);  		kfree(info);  		if (skip) @@ -1989,6 +2038,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)  		dep->supplier = dep_devices.handles[i];  		dep->consumer = handle; +		dep->honor_dep = honor_dep;  		mutex_lock(&acpi_dep_list_lock);  		list_add_tail(&dep->node , &acpi_dep_list); @@ -2003,11 +2053,10 @@ static bool acpi_bus_scan_second_pass;  static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep,  				      struct acpi_device **adev_p)  { -	struct acpi_device *device = NULL; +	struct acpi_device *device = acpi_fetch_acpi_dev(handle);  	acpi_object_type acpi_type;  	int type; -	acpi_bus_get_device(handle, &device);  	if (device)  		goto out; @@ -2155,8 +2204,8 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass)  		register_dock_dependent_device(device, ejd);  	acpi_bus_get_status(device); -	/* Skip devices that are not present. */ -	if (!acpi_device_is_present(device)) { +	/* Skip devices that are not ready for enumeration (e.g. not present) */ +	if (!acpi_dev_ready_for_enumeration(device)) {  		device->flags.initialized = false;  		acpi_device_clear_enumerated(device);  		device->flags.power_manageable = 0; @@ -2319,6 +2368,23 @@ void acpi_dev_clear_dependencies(struct acpi_device *supplier)  EXPORT_SYMBOL_GPL(acpi_dev_clear_dependencies);  /** + * acpi_dev_ready_for_enumeration - Check if the ACPI device is ready for enumeration + * @device: Pointer to the &struct acpi_device to check + * + * Check if the device is present and has no unmet dependencies. + * + * Return true if the device is ready for enumeratino. Otherwise, return false. + */ +bool acpi_dev_ready_for_enumeration(const struct acpi_device *device) +{ +	if (device->flags.honor_deps && device->dep_unmet) +		return false; + +	return acpi_device_is_present(device); +} +EXPORT_SYMBOL_GPL(acpi_dev_ready_for_enumeration); + +/**   * acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier   * @supplier: Pointer to the dependee device   * @@ -2436,42 +2502,33 @@ int acpi_bus_register_early_device(int type)  }  EXPORT_SYMBOL_GPL(acpi_bus_register_early_device); -static int acpi_bus_scan_fixed(void) +static void acpi_bus_scan_fixed(void)  { -	int result = 0; - -	/* -	 * Enumerate all fixed-feature devices. -	 */  	if (!(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) { -		struct acpi_device *device = NULL; - -		result = acpi_add_single_object(&device, NULL, -						ACPI_BUS_TYPE_POWER_BUTTON, false); -		if (result) -			return result; - -		device->flags.match_driver = true; -		result = device_attach(&device->dev); -		if (result < 0) -			return result; - -		device_init_wakeup(&device->dev, true); +		struct acpi_device *adev = NULL; + +		acpi_add_single_object(&adev, NULL, ACPI_BUS_TYPE_POWER_BUTTON, +				       false); +		if (adev) { +			adev->flags.match_driver = true; +			if (device_attach(&adev->dev) >= 0) +				device_init_wakeup(&adev->dev, true); +			else +				dev_dbg(&adev->dev, "No driver\n"); +		}  	}  	if (!(acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON)) { -		struct acpi_device *device = NULL; - -		result = acpi_add_single_object(&device, NULL, -						ACPI_BUS_TYPE_SLEEP_BUTTON, false); -		if (result) -			return result; - -		device->flags.match_driver = true; -		result = device_attach(&device->dev); +		struct acpi_device *adev = NULL; + +		acpi_add_single_object(&adev, NULL, ACPI_BUS_TYPE_SLEEP_BUTTON, +				       false); +		if (adev) { +			adev->flags.match_driver = true; +			if (device_attach(&adev->dev) < 0) +				dev_dbg(&adev->dev, "No driver\n"); +		}  	} - -	return result < 0 ? result : 0;  }  static void __init acpi_get_spcr_uart_addr(void) @@ -2492,9 +2549,8 @@ static void __init acpi_get_spcr_uart_addr(void)  static bool acpi_scan_initialized; -int __init acpi_scan_init(void) +void __init acpi_scan_init(void)  { -	int result;  	acpi_status status;  	struct acpi_table_stao *stao_ptr; @@ -2544,33 +2600,23 @@ int __init acpi_scan_init(void)  	/*  	 * Enumerate devices in the ACPI namespace.  	 */ -	result = acpi_bus_scan(ACPI_ROOT_OBJECT); -	if (result) -		goto out; +	if (acpi_bus_scan(ACPI_ROOT_OBJECT)) +		goto unlock; -	result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root); -	if (result) -		goto out; +	acpi_root = acpi_fetch_acpi_dev(ACPI_ROOT_OBJECT); +	if (!acpi_root) +		goto unlock;  	/* Fixed feature devices do not exist on HW-reduced platform */ -	if (!acpi_gbl_reduced_hardware) { -		result = acpi_bus_scan_fixed(); -		if (result) { -			acpi_detach_data(acpi_root->handle, -					 acpi_scan_drop_device); -			acpi_device_del(acpi_root); -			acpi_bus_put_acpi_device(acpi_root); -			goto out; -		} -	} +	if (!acpi_gbl_reduced_hardware) +		acpi_bus_scan_fixed();  	acpi_turn_off_unused_power_resources();  	acpi_scan_initialized = true; - out: +unlock:  	mutex_unlock(&acpi_scan_lock); -	return result;  }  static struct acpi_probe_entry *ape; |