ACPI: add ACPI bus_type for driver model
Add ACPI bus_type for Linux driver model. 1. .shutdown method is added into acpi_driver.ops needed by bus_type operations. 2. remove useless parameter 'int state' in .resume method. 3. change parameter 'int state' to 'pm_message_t state' in .suspend method. Note: The new .uevent method mark ACPI drivers by PNPID instead of by name. Udev script needs to look for "HWID=" or "COMPTID=" to load ACPI drivers as a result. Signed-off-by: Li Shaohua <shaohua.li@intel.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
This commit is contained in:
		
							parent
							
								
									d43ec68e98
								
							
						
					
					
						commit
						5d9464a469
					
				| @ -64,7 +64,7 @@ extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); | ||||
| 
 | ||||
| static int acpi_battery_add(struct acpi_device *device); | ||||
| static int acpi_battery_remove(struct acpi_device *device, int type); | ||||
| static int acpi_battery_resume(struct acpi_device *device, int status); | ||||
| static int acpi_battery_resume(struct acpi_device *device); | ||||
| 
 | ||||
| static struct acpi_driver acpi_battery_driver = { | ||||
| 	.name = ACPI_BATTERY_DRIVER_NAME, | ||||
| @ -756,7 +756,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) | ||||
| } | ||||
| 
 | ||||
| /* this is needed to learn about changes made in suspended state */ | ||||
| static int acpi_battery_resume(struct acpi_device *device, int state) | ||||
| static int acpi_battery_resume(struct acpi_device *device) | ||||
| { | ||||
| 	struct acpi_battery *battery; | ||||
| 
 | ||||
|  | ||||
| @ -48,8 +48,8 @@ MODULE_LICENSE("GPL"); | ||||
| 
 | ||||
| static int acpi_fan_add(struct acpi_device *device); | ||||
| static int acpi_fan_remove(struct acpi_device *device, int type); | ||||
| static int acpi_fan_suspend(struct acpi_device *device, int state); | ||||
| static int acpi_fan_resume(struct acpi_device *device, int state); | ||||
| static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state); | ||||
| static int acpi_fan_resume(struct acpi_device *device); | ||||
| 
 | ||||
| static struct acpi_driver acpi_fan_driver = { | ||||
| 	.name = ACPI_FAN_DRIVER_NAME, | ||||
| @ -238,7 +238,7 @@ static int acpi_fan_remove(struct acpi_device *device, int type) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int acpi_fan_suspend(struct acpi_device *device, int state) | ||||
| static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state) | ||||
| { | ||||
| 	if (!device) | ||||
| 		return -EINVAL; | ||||
| @ -248,7 +248,7 @@ static int acpi_fan_suspend(struct acpi_device *device, int state) | ||||
| 	return AE_OK; | ||||
| } | ||||
| 
 | ||||
| static int acpi_fan_resume(struct acpi_device *device, int state) | ||||
| static int acpi_fan_resume(struct acpi_device *device) | ||||
| { | ||||
| 	int result = 0; | ||||
| 	int power_state = 0; | ||||
|  | ||||
| @ -222,100 +222,124 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count) | ||||
| /* --------------------------------------------------------------------------
 | ||||
| 			ACPI Bus operations | ||||
|    -------------------------------------------------------------------------- */ | ||||
| static int root_suspend(struct acpi_device * acpi_dev, pm_message_t state) | ||||
| static int acpi_device_suspend(struct device *dev, pm_message_t state) | ||||
| { | ||||
| 	struct acpi_device * dev, * next; | ||||
| 	int result; | ||||
| 	struct acpi_device *acpi_dev = to_acpi_device(dev); | ||||
| 	struct acpi_driver *acpi_drv = acpi_dev->driver; | ||||
| 
 | ||||
| 	spin_lock(&acpi_device_lock); | ||||
| 	list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) { | ||||
| 		if (dev->driver && dev->driver->ops.suspend) { | ||||
| 			spin_unlock(&acpi_device_lock); | ||||
| 			result = dev->driver->ops.suspend(dev, 0); | ||||
| 			if (result) { | ||||
| 				printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n", | ||||
| 				       acpi_device_name(dev), | ||||
| 				       acpi_device_bid(dev), result); | ||||
| 			} | ||||
| 			spin_lock(&acpi_device_lock); | ||||
| 	if (acpi_drv && acpi_drv->ops.suspend) | ||||
| 		return acpi_drv->ops.suspend(acpi_dev, state); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int acpi_device_resume(struct device *dev) | ||||
| { | ||||
| 	struct acpi_device *acpi_dev = to_acpi_device(dev); | ||||
| 	struct acpi_driver *acpi_drv = acpi_dev->driver; | ||||
| 
 | ||||
| 	if (acpi_drv && acpi_drv->ops.resume) | ||||
| 		return acpi_drv->ops.resume(acpi_dev); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int acpi_bus_match(struct device *dev, struct device_driver *drv) | ||||
| { | ||||
| 	struct acpi_device *acpi_dev = to_acpi_device(dev); | ||||
| 	struct acpi_driver *acpi_drv = to_acpi_driver(drv); | ||||
| 
 | ||||
| 	if (acpi_drv->ops.match) | ||||
| 		return !acpi_drv->ops.match(acpi_dev, acpi_drv); | ||||
| 	return !acpi_match_ids(acpi_dev, acpi_drv->ids); | ||||
| } | ||||
| 
 | ||||
| static int acpi_device_uevent(struct device *dev, char **envp, int num_envp, | ||||
| 	char *buffer, int buffer_size) | ||||
| { | ||||
| 	struct acpi_device *acpi_dev = to_acpi_device(dev); | ||||
| 	int i = 0, length = 0, ret = 0; | ||||
| 
 | ||||
| 	if (acpi_dev->flags.hardware_id) | ||||
| 		ret = add_uevent_var(envp, num_envp, &i, | ||||
| 			buffer, buffer_size, &length, | ||||
| 			"HWID=%s", acpi_dev->pnp.hardware_id); | ||||
| 	if (ret) | ||||
| 		return -ENOMEM; | ||||
| 	if (acpi_dev->flags.compatible_ids) { | ||||
| 		int j; | ||||
| 		struct acpi_compatible_id_list *cid_list; | ||||
| 
 | ||||
| 		cid_list = acpi_dev->pnp.cid_list; | ||||
| 
 | ||||
| 		for (j = 0; j < cid_list->count; j++) { | ||||
| 			ret = add_uevent_var(envp, num_envp, &i, buffer, | ||||
| 				buffer_size, &length, "COMPTID=%s", | ||||
| 				cid_list->id[j].value); | ||||
| 			if (ret) | ||||
| 				return -ENOMEM; | ||||
| 		} | ||||
| 	} | ||||
| 	spin_unlock(&acpi_device_lock); | ||||
| 
 | ||||
| 	envp[i] = NULL; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int acpi_device_suspend(struct device * dev, pm_message_t state) | ||||
| static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *); | ||||
| static int acpi_start_single_object(struct acpi_device *); | ||||
| static int acpi_device_probe(struct device * dev) | ||||
| { | ||||
| 	struct acpi_device * acpi_dev = to_acpi_device(dev); | ||||
| 	struct acpi_device *acpi_dev = to_acpi_device(dev); | ||||
| 	struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver); | ||||
| 	int ret; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * For now, we should only register 1 generic device - | ||||
| 	 * the ACPI root device - and from there, we walk the | ||||
| 	 * tree of ACPI devices to suspend each one using the | ||||
| 	 * ACPI driver methods. | ||||
| 	 */ | ||||
| 	if (acpi_dev->handle == ACPI_ROOT_OBJECT) | ||||
| 		root_suspend(acpi_dev, state); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int root_resume(struct acpi_device * acpi_dev) | ||||
| { | ||||
| 	struct acpi_device * dev, * next; | ||||
| 	int result; | ||||
| 
 | ||||
| 	spin_lock(&acpi_device_lock); | ||||
| 	list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) { | ||||
| 		if (dev->driver && dev->driver->ops.resume) { | ||||
| 			spin_unlock(&acpi_device_lock); | ||||
| 			result = dev->driver->ops.resume(dev, 0); | ||||
| 			if (result) { | ||||
| 				printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n", | ||||
| 				       acpi_device_name(dev), | ||||
| 				       acpi_device_bid(dev), result); | ||||
| 			} | ||||
| 			spin_lock(&acpi_device_lock); | ||||
| 		} | ||||
| 	ret = acpi_bus_driver_init(acpi_dev, acpi_drv); | ||||
| 	if (!ret) { | ||||
| 		acpi_start_single_object(acpi_dev); | ||||
| 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||||
| 			"Found driver [%s] for device [%s]\n", | ||||
| 			acpi_drv->name, acpi_dev->pnp.bus_id)); | ||||
| 		get_device(dev); | ||||
| 	} | ||||
| 	spin_unlock(&acpi_device_lock); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static int acpi_device_remove(struct device * dev) | ||||
| { | ||||
| 	struct acpi_device *acpi_dev = to_acpi_device(dev); | ||||
| 	struct acpi_driver *acpi_drv = acpi_dev->driver; | ||||
| 
 | ||||
| 	if (acpi_drv) { | ||||
| 		if (acpi_drv->ops.stop) | ||||
| 			acpi_drv->ops.stop(acpi_dev, ACPI_BUS_REMOVAL_NORMAL); | ||||
| 		if (acpi_drv->ops.remove) | ||||
| 			acpi_drv->ops.remove(acpi_dev, ACPI_BUS_REMOVAL_NORMAL); | ||||
| 	} | ||||
| 	acpi_dev->driver = NULL; | ||||
| 	acpi_driver_data(dev) = NULL; | ||||
| 
 | ||||
| 	put_device(dev); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int acpi_device_resume(struct device * dev) | ||||
| static void acpi_device_shutdown(struct device *dev) | ||||
| { | ||||
| 	struct acpi_device * acpi_dev = to_acpi_device(dev); | ||||
| 	struct acpi_device *acpi_dev = to_acpi_device(dev); | ||||
| 	struct acpi_driver *acpi_drv = acpi_dev->driver; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * For now, we should only register 1 generic device - | ||||
| 	 * the ACPI root device - and from there, we walk the | ||||
| 	 * tree of ACPI devices to resume each one using the | ||||
| 	 * ACPI driver methods. | ||||
| 	 */ | ||||
| 	if (acpi_dev->handle == ACPI_ROOT_OBJECT) | ||||
| 		root_resume(acpi_dev); | ||||
| 	return 0; | ||||
| } | ||||
| 	if (acpi_drv && acpi_drv->ops.shutdown) | ||||
| 		acpi_drv->ops.shutdown(acpi_dev); | ||||
| 
 | ||||
| /**
 | ||||
|  * acpi_bus_match - match device IDs to driver's supported IDs | ||||
|  * @device: the device that we are trying to match to a driver | ||||
|  * @driver: driver whose device id table is being checked | ||||
|  * | ||||
|  * Checks the device's hardware (_HID) or compatible (_CID) ids to see if it | ||||
|  * matches the specified driver's criteria. | ||||
|  */ | ||||
| static int | ||||
| acpi_bus_match(struct acpi_device *device, struct acpi_driver *driver) | ||||
| { | ||||
| 	if (driver && driver->ops.match) | ||||
| 		return driver->ops.match(device, driver); | ||||
| 	return acpi_match_ids(device, driver->ids); | ||||
| 	return ; | ||||
| } | ||||
| 
 | ||||
| static struct bus_type acpi_bus_type = { | ||||
| 	.name		= "acpi", | ||||
| 	.suspend	= acpi_device_suspend, | ||||
| 	.resume		= acpi_device_resume, | ||||
| 	.shutdown	= acpi_device_shutdown, | ||||
| 	.match		= acpi_bus_match, | ||||
| 	.probe		= acpi_device_probe, | ||||
| 	.remove		= acpi_device_remove, | ||||
| 	.uevent		= acpi_device_uevent, | ||||
| }; | ||||
| 
 | ||||
| static void acpi_device_register(struct acpi_device *device, | ||||
| @ -449,7 +473,7 @@ static void acpi_driver_attach(struct acpi_driver *drv) | ||||
| 			continue; | ||||
| 		spin_unlock(&acpi_device_lock); | ||||
| 
 | ||||
| 		if (!acpi_bus_match(dev, drv)) { | ||||
| 		if (!acpi_bus_match(&(dev->dev), &(drv->drv))) { | ||||
| 			if (!acpi_bus_driver_init(dev, drv)) { | ||||
| 				acpi_start_single_object(dev); | ||||
| 				atomic_inc(&drv->references); | ||||
| @ -551,7 +575,7 @@ static int acpi_bus_find_driver(struct acpi_device *device) | ||||
| 
 | ||||
| 		atomic_inc(&driver->references); | ||||
| 		spin_unlock(&acpi_device_lock); | ||||
| 		if (!acpi_bus_match(device, driver)) { | ||||
| 		if (!acpi_bus_match(&(device->dev), &(driver->drv))) { | ||||
| 			result = acpi_bus_driver_init(device, driver); | ||||
| 			if (!result) | ||||
| 				goto Done; | ||||
|  | ||||
| @ -82,7 +82,7 @@ MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n"); | ||||
| 
 | ||||
| static int acpi_thermal_add(struct acpi_device *device); | ||||
| static int acpi_thermal_remove(struct acpi_device *device, int type); | ||||
| static int acpi_thermal_resume(struct acpi_device *device, int state); | ||||
| static int acpi_thermal_resume(struct acpi_device *device); | ||||
| static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); | ||||
| static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); | ||||
| static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); | ||||
| @ -1356,7 +1356,7 @@ static int acpi_thermal_remove(struct acpi_device *device, int type) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int acpi_thermal_resume(struct acpi_device *device, int state) | ||||
| static int acpi_thermal_resume(struct acpi_device *device) | ||||
| { | ||||
| 	struct acpi_thermal *tz = NULL; | ||||
| 	int i; | ||||
|  | ||||
| @ -92,13 +92,14 @@ typedef int (*acpi_op_remove) (struct acpi_device * device, int type); | ||||
| typedef int (*acpi_op_lock) (struct acpi_device * device, int type); | ||||
| typedef int (*acpi_op_start) (struct acpi_device * device); | ||||
| typedef int (*acpi_op_stop) (struct acpi_device * device, int type); | ||||
| typedef int (*acpi_op_suspend) (struct acpi_device * device, int state); | ||||
| typedef int (*acpi_op_resume) (struct acpi_device * device, int state); | ||||
| typedef int (*acpi_op_suspend) (struct acpi_device * device, pm_message_t state); | ||||
| typedef int (*acpi_op_resume) (struct acpi_device * device); | ||||
| typedef int (*acpi_op_scan) (struct acpi_device * device); | ||||
| typedef int (*acpi_op_bind) (struct acpi_device * device); | ||||
| typedef int (*acpi_op_unbind) (struct acpi_device * device); | ||||
| typedef int (*acpi_op_match) (struct acpi_device * device, | ||||
| 			      struct acpi_driver * driver); | ||||
| typedef int (*acpi_op_shutdown) (struct acpi_device * device); | ||||
| 
 | ||||
| struct acpi_bus_ops { | ||||
| 	u32 acpi_op_add:1; | ||||
| @ -112,7 +113,8 @@ struct acpi_bus_ops { | ||||
| 	u32 acpi_op_bind:1; | ||||
| 	u32 acpi_op_unbind:1; | ||||
| 	u32 acpi_op_match:1; | ||||
| 	u32 reserved:21; | ||||
| 	u32 acpi_op_shutdown:1; | ||||
| 	u32 reserved:20; | ||||
| }; | ||||
| 
 | ||||
| struct acpi_device_ops { | ||||
| @ -127,6 +129,7 @@ struct acpi_device_ops { | ||||
| 	acpi_op_bind bind; | ||||
| 	acpi_op_unbind unbind; | ||||
| 	acpi_op_match match; | ||||
| 	acpi_op_shutdown shutdown; | ||||
| }; | ||||
| 
 | ||||
| struct acpi_driver { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user