diff options
Diffstat (limited to 'include/acpi/acpi_bus.h')
| -rw-r--r-- | include/acpi/acpi_bus.h | 339 | 
1 files changed, 261 insertions, 78 deletions
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 359ef11725a..b5714580801 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -28,8 +28,6 @@  #include <linux/device.h> -#include <acpi/acpi.h> -  /* TBD: Make dynamic */  #define ACPI_MAX_HANDLES	10  struct acpi_handle_list { @@ -50,6 +48,47 @@ acpi_evaluate_reference(acpi_handle handle,  			acpi_string pathname,  			struct acpi_object_list *arguments,  			struct acpi_handle_list *list); +acpi_status +acpi_evaluate_ost(acpi_handle handle, u32 source_event, u32 status_code, +		  struct acpi_buffer *status_buf); + +acpi_status +acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld); + +bool acpi_has_method(acpi_handle handle, char *name); +acpi_status acpi_execute_simple_method(acpi_handle handle, char *method, +				       u64 arg); +acpi_status acpi_evaluate_ej0(acpi_handle handle); +acpi_status acpi_evaluate_lck(acpi_handle handle, int lock); +bool acpi_ata_match(acpi_handle handle); +bool acpi_bay_match(acpi_handle handle); +bool acpi_dock_match(acpi_handle handle); + +bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs); +union acpi_object *acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, +			int rev, int func, union acpi_object *argv4); + +static inline union acpi_object * +acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, int rev, int func, +			union acpi_object *argv4, acpi_object_type type) +{ +	union acpi_object *obj; + +	obj = acpi_evaluate_dsm(handle, uuid, rev, func, argv4); +	if (obj && obj->type != type) { +		ACPI_FREE(obj); +		obj = NULL; +	} + +	return obj; +} + +#define	ACPI_INIT_DSM_ARGV4(cnt, eles)			\ +	{						\ +	  .package.type = ACPI_TYPE_PACKAGE,		\ +	  .package.count = (cnt),			\ +	  .package.elements = (eles)			\ +	}  #ifdef CONFIG_ACPI @@ -58,13 +97,6 @@ acpi_evaluate_reference(acpi_handle handle,  #define ACPI_BUS_FILE_ROOT	"acpi"  extern struct proc_dir_entry *acpi_root_dir; -enum acpi_bus_removal_type { -	ACPI_BUS_REMOVAL_NORMAL = 0, -	ACPI_BUS_REMOVAL_EJECT, -	ACPI_BUS_REMOVAL_SUPRISE, -	ACPI_BUS_REMOVAL_TYPE_COUNT -}; -  enum acpi_bus_device_type {  	ACPI_BUS_TYPE_DEVICE = 0,  	ACPI_BUS_TYPE_POWER, @@ -79,33 +111,58 @@ struct acpi_driver;  struct acpi_device;  /* + * ACPI Scan Handler + * ----------------- + */ + +struct acpi_hotplug_profile { +	struct kobject kobj; +	int (*scan_dependent)(struct acpi_device *adev); +	bool enabled:1; +	bool demand_offline:1; +}; + +static inline struct acpi_hotplug_profile *to_acpi_hotplug_profile( +						struct kobject *kobj) +{ +	return container_of(kobj, struct acpi_hotplug_profile, kobj); +} + +struct acpi_scan_handler { +	const struct acpi_device_id *ids; +	struct list_head list_node; +	bool (*match)(char *idstr, const struct acpi_device_id **matchid); +	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id); +	void (*detach)(struct acpi_device *dev); +	void (*bind)(struct device *phys_dev); +	void (*unbind)(struct device *phys_dev); +	struct acpi_hotplug_profile hotplug; +}; + +/* + * ACPI Hotplug Context + * -------------------- + */ + +struct acpi_hotplug_context { +	struct acpi_device *self; +	int (*notify)(struct acpi_device *, u32); +	void (*uevent)(struct acpi_device *, u32); +	void (*fixup)(struct acpi_device *); +}; + +/*   * ACPI Driver   * -----------   */  typedef int (*acpi_op_add) (struct acpi_device * device); -typedef int (*acpi_op_remove) (struct acpi_device * device, int type); -typedef int (*acpi_op_start) (struct acpi_device * device); -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_bind) (struct acpi_device * device); -typedef int (*acpi_op_unbind) (struct acpi_device * device); +typedef int (*acpi_op_remove) (struct acpi_device * device);  typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event); -struct acpi_bus_ops { -	u32 acpi_op_add:1; -	u32 acpi_op_start:1; -}; -  struct acpi_device_ops {  	acpi_op_add add;  	acpi_op_remove remove; -	acpi_op_start start; -	acpi_op_suspend suspend; -	acpi_op_resume resume; -	acpi_op_bind bind; -	acpi_op_unbind unbind;  	acpi_op_notify notify;  }; @@ -141,15 +198,15 @@ struct acpi_device_status {  struct acpi_device_flags {  	u32 dynamic_status:1; -	u32 bus_address:1;  	u32 removable:1;  	u32 ejectable:1; -	u32 lockable:1; -	u32 suprise_removal_ok:1;  	u32 power_manageable:1; -	u32 performance_manageable:1; -	u32 wake_capable:1;	/* Wakeup(_PRW) supported? */ -	u32 force_power_state:1; +	u32 match_driver:1; +	u32 initialized:1; +	u32 visited:1; +	u32 no_hotplug:1; +	u32 hotplug_notify:1; +	u32 is_dock_station:1;  	u32 reserved:22;  }; @@ -173,13 +230,23 @@ struct acpi_hardware_id {  	char *id;  }; +struct acpi_pnp_type { +	u32 hardware_id:1; +	u32 bus_address:1; +	u32 platform_id:1; +	u32 reserved:29; +}; +  struct acpi_device_pnp { -	acpi_bus_id bus_id;	/* Object name */ +	acpi_bus_id bus_id;		/* Object name */ +	struct acpi_pnp_type type;	/* ID type */  	acpi_bus_address bus_address;	/* _ADR */ -	char *unique_id;	/* _UID */ +	char *unique_id;		/* _UID */  	struct list_head ids;		/* _HID and _CIDs */  	acpi_device_name device_name;	/* Driver-determined */  	acpi_device_class device_class;	/*        "          */ +	union acpi_object *str_obj;	/* unicode string for _STR method */ +	unsigned long sun;		/* _SUN */  };  #define acpi_device_bid(d)	((d)->pnp.bus_id) @@ -195,24 +262,27 @@ struct acpi_device_power_flags {  	u32 power_resources:1;	/* Power resources */  	u32 inrush_current:1;	/* Serialize Dx->D0 */  	u32 power_removed:1;	/* Optimize Dx->D0 */ -	u32 reserved:28; +	u32 ignore_parent:1;	/* Power is independent of parent power state */ +	u32 dsw_present:1;	/* _DSW present? */ +	u32 reserved:26;  };  struct acpi_device_power_state {  	struct {  		u8 valid:1; +		u8 os_accessible:1;  		u8 explicit_set:1;	/* _PSx present? */  		u8 reserved:6;  	} flags;  	int power;		/* % Power (compared to D0) */  	int latency;		/* Dx->D0 time (microseconds) */ -	struct acpi_handle_list resources;	/* Power resources referenced */ +	struct list_head resources;	/* Power resources referenced */  };  struct acpi_device_power {  	int state;		/* Current state */  	struct acpi_device_power_flags flags; -	struct acpi_device_power_state states[4];	/* Power states (D0-D3) */ +	struct acpi_device_power_state states[ACPI_D_STATE_COUNT];	/* Power states (D0-D3Cold) */  };  /* Performance Management */ @@ -242,27 +312,26 @@ struct acpi_device_perf {  struct acpi_device_wakeup_flags {  	u8 valid:1;		/* Can successfully enable wakeup? */  	u8 run_wake:1;		/* Run-Wake GPE devices */ -	u8 always_enabled:1;	/* Run-wake devices that are always enabled */  	u8 notifier_present:1;  /* Wake-up notify handler has been installed */  }; -struct acpi_device_wakeup_state { -	u8 enabled:1; -}; -  struct acpi_device_wakeup {  	acpi_handle gpe_device;  	u64 gpe_number;  	u64 sleep_state; -	struct acpi_handle_list resources; -	struct acpi_device_wakeup_state state; +	struct list_head resources;  	struct acpi_device_wakeup_flags flags;  	int prepare_count; -	int run_wake_count;  }; -/* Device */ +struct acpi_device_physical_node { +	unsigned int node_id; +	struct list_head node; +	struct device *dev; +	bool put_online:1; +}; +/* Device */  struct acpi_device {  	int device_type;  	acpi_handle handle;		/* no handle for fixed hardware */ @@ -270,6 +339,7 @@ struct acpi_device {  	struct list_head children;  	struct list_head node;  	struct list_head wakeup_list; +	struct list_head del_list;  	struct acpi_device_status status;  	struct acpi_device_flags flags;  	struct acpi_device_pnp pnp; @@ -277,12 +347,15 @@ struct acpi_device {  	struct acpi_device_wakeup wakeup;  	struct acpi_device_perf performance;  	struct acpi_device_dir dir; -	struct acpi_device_ops ops; +	struct acpi_scan_handler *handler; +	struct acpi_hotplug_context *hp;  	struct acpi_driver *driver;  	void *driver_data;  	struct device dev; -	struct acpi_bus_ops bus_ops;	/* workaround for different code path for hotplug */ -	enum acpi_bus_removal_type removal_type;	/* indicate for different removal type */ +	unsigned int physical_node_count; +	struct list_head physical_node_list; +	struct mutex physical_node_lock; +	void (*remove)(struct acpi_device *);  };  static inline void *acpi_driver_data(struct acpi_device *d) @@ -293,6 +366,29 @@ static inline void *acpi_driver_data(struct acpi_device *d)  #define to_acpi_device(d)	container_of(d, struct acpi_device, dev)  #define to_acpi_driver(d)	container_of(d, struct acpi_driver, drv) +static inline void acpi_set_device_status(struct acpi_device *adev, u32 sta) +{ +	*((u32 *)&adev->status) = sta; +} + +static inline void acpi_set_hp_context(struct acpi_device *adev, +				       struct acpi_hotplug_context *hp, +				       int (*notify)(struct acpi_device *, u32), +				       void (*uevent)(struct acpi_device *, u32), +				       void (*fixup)(struct acpi_device *)) +{ +	hp->self = adev; +	hp->notify = notify; +	hp->uevent = uevent; +	hp->fixup = fixup; +	adev->hp = hp; +} + +void acpi_initialize_hp_context(struct acpi_device *adev, +				struct acpi_hotplug_context *hp, +				int (*notify)(struct acpi_device *, u32), +				void (*uevent)(struct acpi_device *, u32)); +  /* acpi_device.dev.bus == &acpi_bus_type */  extern struct bus_type acpi_bus_type; @@ -313,102 +409,189 @@ extern struct kobject *acpi_kobj;  extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);  void acpi_bus_private_data_handler(acpi_handle, void *);  int acpi_bus_get_private_data(acpi_handle, void **); +int acpi_bus_attach_private_data(acpi_handle, void *); +void acpi_bus_detach_private_data(acpi_handle); +void acpi_bus_no_hotplug(acpi_handle handle);  extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);  extern int register_acpi_notifier(struct notifier_block *);  extern int unregister_acpi_notifier(struct notifier_block *); -extern int register_acpi_bus_notifier(struct notifier_block *nb); -extern void unregister_acpi_bus_notifier(struct notifier_block *nb);  /*   * External Functions   */  int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device); -void acpi_bus_data_handler(acpi_handle handle, void *context); +struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle); +void acpi_bus_put_acpi_device(struct acpi_device *adev);  acpi_status acpi_bus_get_status_handle(acpi_handle handle,  				       unsigned long long *sta);  int acpi_bus_get_status(struct acpi_device *device); -int acpi_bus_get_power(acpi_handle handle, int *state); +  int acpi_bus_set_power(acpi_handle handle, int state); +const char *acpi_power_state_string(int state); +int acpi_device_get_power(struct acpi_device *device, int *state); +int acpi_device_set_power(struct acpi_device *device, int state); +int acpi_bus_init_power(struct acpi_device *device); +int acpi_device_fix_up_power(struct acpi_device *device); +int acpi_bus_update_power(acpi_handle handle, int *state_p);  bool acpi_bus_power_manageable(acpi_handle handle); + +#ifdef CONFIG_PM  bool acpi_bus_can_wakeup(acpi_handle handle); -#ifdef CONFIG_ACPI_PROC_EVENT -int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data); -int acpi_bus_generate_proc_event4(const char *class, const char *bid, u8 type, int data); -int acpi_bus_receive_event(struct acpi_bus_event *event);  #else -static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) -	{ return 0; } +static inline bool acpi_bus_can_wakeup(acpi_handle handle) { return false; }  #endif + +void acpi_scan_lock_acquire(void); +void acpi_scan_lock_release(void); +void acpi_lock_hp_context(void); +void acpi_unlock_hp_context(void); +int acpi_scan_add_handler(struct acpi_scan_handler *handler);  int acpi_bus_register_driver(struct acpi_driver *driver);  void acpi_bus_unregister_driver(struct acpi_driver *driver); -int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, -		 acpi_handle handle, int type); -int acpi_bus_trim(struct acpi_device *start, int rmdevice); -int acpi_bus_start(struct acpi_device *device); +int acpi_bus_scan(acpi_handle handle); +void acpi_bus_trim(struct acpi_device *start);  acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd);  int acpi_match_device_ids(struct acpi_device *device,  			  const struct acpi_device_id *ids);  int acpi_create_dir(struct acpi_device *);  void acpi_remove_dir(struct acpi_device *); +static inline bool acpi_device_enumerated(struct acpi_device *adev) +{ +	return adev && adev->flags.initialized && adev->flags.visited; +} + +/** + * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver + * @__acpi_driver: acpi_driver struct + * + * Helper macro for ACPI drivers which do not do anything special in module + * init/exit. This eliminates a lot of boilerplate. Each module may only + * use this macro once, and calling it replaces module_init() and module_exit() + */ +#define module_acpi_driver(__acpi_driver) \ +	module_driver(__acpi_driver, acpi_bus_register_driver, \ +		      acpi_bus_unregister_driver) +  /*   * Bind physical devices with ACPI devices   */  struct acpi_bus_type {  	struct list_head list; -	struct bus_type *bus; -	/* For general devices under the bus */ -	int (*find_device) (struct device *, acpi_handle *); -	/* For bridges, such as PCI root bridge, IDE controller */ -	int (*find_bridge) (struct device *, acpi_handle *); +	const char *name; +	bool (*match)(struct device *dev); +	struct acpi_device * (*find_companion)(struct device *); +	void (*setup)(struct device *); +	void (*cleanup)(struct device *);  };  int register_acpi_bus_type(struct acpi_bus_type *);  int unregister_acpi_bus_type(struct acpi_bus_type *); -struct device *acpi_get_physical_device(acpi_handle);  struct acpi_pci_root { -	struct list_head node;  	struct acpi_device * device; -	struct acpi_pci_id id;  	struct pci_bus *bus;  	u16 segment;  	struct resource secondary;	/* downstream bus range */  	u32 osc_support_set;	/* _OSC state of support bits */  	u32 osc_control_set;	/* _OSC state of control bits */ +	phys_addr_t mcfg_addr;  };  /* helper */ -acpi_handle acpi_get_child(acpi_handle, u64); + +struct acpi_device *acpi_find_child_device(struct acpi_device *parent, +					   u64 address, bool check_children);  int acpi_is_root_bridge(acpi_handle); -acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);  struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); -#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle))  int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);  int acpi_disable_wakeup_device_power(struct acpi_device *dev); -#ifdef CONFIG_PM_OPS -int acpi_pm_device_sleep_state(struct device *, int *); +#ifdef CONFIG_PM +acpi_status acpi_add_pm_notifier(struct acpi_device *adev, +				 acpi_notify_handler handler, void *context); +acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, +				    acpi_notify_handler handler); +int acpi_pm_device_sleep_state(struct device *, int *, int);  #else -static inline int acpi_pm_device_sleep_state(struct device *d, int *p) +static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev, +					       acpi_notify_handler handler, +					       void *context) +{ +	return AE_SUPPORT; +} +static inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, +						  acpi_notify_handler handler) +{ +	return AE_SUPPORT; +} +static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)  {  	if (p)  		*p = ACPI_STATE_D0; -	return ACPI_STATE_D3; + +	return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3_COLD) ? +		m : ACPI_STATE_D0; +} +#endif + +#ifdef CONFIG_PM_RUNTIME +int __acpi_device_run_wake(struct acpi_device *, bool); +int acpi_pm_device_run_wake(struct device *, bool); +#else +static inline int __acpi_device_run_wake(struct acpi_device *adev, bool en) +{ +	return -ENODEV; +} +static inline int acpi_pm_device_run_wake(struct device *dev, bool enable) +{ +	return -ENODEV;  }  #endif  #ifdef CONFIG_PM_SLEEP +int __acpi_device_sleep_wake(struct acpi_device *, u32, bool);  int acpi_pm_device_sleep_wake(struct device *, bool);  #else +static inline int __acpi_device_sleep_wake(struct acpi_device *adev, +					   u32 target_state, bool enable) +{ +	return -ENODEV; +}  static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable)  {  	return -ENODEV;  }  #endif +#ifdef CONFIG_ACPI_SLEEP +u32 acpi_target_system_state(void); +#else +static inline u32 acpi_target_system_state(void) { return ACPI_STATE_S0; } +#endif + +static inline bool acpi_device_power_manageable(struct acpi_device *adev) +{ +	return adev->flags.power_manageable; +} + +static inline bool acpi_device_can_wakeup(struct acpi_device *adev) +{ +	return adev->wakeup.flags.valid; +} + +static inline bool acpi_device_can_poweroff(struct acpi_device *adev) +{ +	return adev->power.states[ACPI_STATE_D3_COLD].flags.os_accessible; +} + +#else	/* CONFIG_ACPI */ + +static inline int register_acpi_bus_type(void *bus) { return 0; } +static inline int unregister_acpi_bus_type(void *bus) { return 0; } +  #endif				/* CONFIG_ACPI */  #endif /*__ACPI_BUS_H__*/  | 
