]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: Shaohua Li <shaohua.li@intel.com> |
2 | Subject: introduce .uevent for devices in dock | |
3 | Patch-mainline: submitted 2008-08-28 | |
4 | References: fate#304731,bnc#401740 | |
5 | ||
6 | dock's uevent reported itself, not ata. It might be difficult to find an | |
7 | ata device just according to a dock. This patch introduces docking ops | |
8 | for each device in a dock. when docking, dock driver can send device | |
9 | specific uevent. This should help dock station too (not just bay) | |
10 | ||
11 | Signed-off-by: Shaohua Li <shaohua.li@intel.com> | |
12 | Signed-off-by: Holger Macht <hmacht@suse.de> | |
13 | --- | |
14 | ||
15 | diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c | |
16 | index f19f643..ac7dfef 100644 | |
17 | --- a/drivers/acpi/dock.c | |
18 | +++ b/drivers/acpi/dock.c | |
19 | @@ -75,7 +75,7 @@ struct dock_dependent_device { | |
20 | struct list_head list; | |
21 | struct list_head hotplug_list; | |
22 | acpi_handle handle; | |
23 | - acpi_notify_handler handler; | |
24 | + struct acpi_dock_ops *ops; | |
25 | void *context; | |
26 | }; | |
27 | ||
28 | @@ -385,8 +385,8 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) | |
29 | * First call driver specific hotplug functions | |
30 | */ | |
31 | list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) { | |
32 | - if (dd->handler) | |
33 | - dd->handler(dd->handle, event, dd->context); | |
34 | + if (dd->ops && dd->ops->handler) | |
35 | + dd->ops->handler(dd->handle, event, dd->context); | |
36 | } | |
37 | ||
38 | /* | |
39 | @@ -409,6 +409,7 @@ static void dock_event(struct dock_station *ds, u32 event, int num) | |
40 | struct device *dev = &ds->dock_device->dev; | |
41 | char event_string[13]; | |
42 | char *envp[] = { event_string, NULL }; | |
43 | + struct dock_dependent_device *dd; | |
44 | ||
45 | if (num == UNDOCK_EVENT) | |
46 | sprintf(event_string, "EVENT=undock"); | |
47 | @@ -419,7 +420,14 @@ static void dock_event(struct dock_station *ds, u32 event, int num) | |
48 | * Indicate that the status of the dock station has | |
49 | * changed. | |
50 | */ | |
51 | - kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); | |
52 | + if (num == DOCK_EVENT) | |
53 | + kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); | |
54 | + | |
55 | + list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) | |
56 | + if (dd->ops && dd->ops->uevent) | |
57 | + dd->ops->uevent(dd->handle, event, dd->context); | |
58 | + if (num != DOCK_EVENT) | |
59 | + kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); | |
60 | } | |
61 | ||
62 | /** | |
63 | @@ -588,7 +596,7 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier); | |
64 | /** | |
65 | * register_hotplug_dock_device - register a hotplug function | |
66 | * @handle: the handle of the device | |
67 | - * @handler: the acpi_notifier_handler to call after docking | |
68 | + * @ops: handlers to call after docking | |
69 | * @context: device specific data | |
70 | * | |
71 | * If a driver would like to perform a hotplug operation after a dock | |
72 | @@ -596,7 +604,7 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier); | |
73 | * the dock driver after _DCK is executed. | |
74 | */ | |
75 | int | |
76 | -register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler, | |
77 | +register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops, | |
78 | void *context) | |
79 | { | |
80 | struct dock_dependent_device *dd; | |
81 | @@ -612,7 +620,7 @@ register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler, | |
82 | list_for_each_entry(dock_station, &dock_stations, sibiling) { | |
83 | dd = find_dock_dependent_device(dock_station, handle); | |
84 | if (dd) { | |
85 | - dd->handler = handler; | |
86 | + dd->ops = ops; | |
87 | dd->context = context; | |
88 | dock_add_hotplug_device(dock_station, dd); | |
89 | return 0; | |
90 | diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c | |
91 | index 97727be..c012307 100644 | |
92 | --- a/drivers/ata/libata-acpi.c | |
93 | +++ b/drivers/ata/libata-acpi.c | |
94 | @@ -209,6 +209,46 @@ static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data) | |
95 | ata_acpi_handle_hotplug(ap, NULL, event); | |
96 | } | |
97 | ||
98 | +static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev, | |
99 | + u32 event) | |
100 | +{ | |
101 | + struct kobject *kobj = NULL; | |
102 | + char event_string[20]; | |
103 | + char *envp[] = { event_string, NULL }; | |
104 | + | |
105 | + if (dev) { | |
106 | + if (dev->sdev) | |
107 | + kobj = &dev->sdev->sdev_gendev.kobj; | |
108 | + } else | |
109 | + kobj = &ap->dev->kobj; | |
110 | + | |
111 | + if (kobj) { | |
112 | + snprintf(event_string, 20, "BAY_EVENT=%d", event); | |
113 | + kobject_uevent_env(kobj, KOBJ_CHANGE, envp); | |
114 | + } | |
115 | +} | |
116 | + | |
117 | +static void ata_acpi_ap_uevent(acpi_handle handle, u32 event, void *data) | |
118 | +{ | |
119 | + ata_acpi_uevent(data, NULL, event); | |
120 | +} | |
121 | + | |
122 | +static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data) | |
123 | +{ | |
124 | + struct ata_device *dev = data; | |
125 | + ata_acpi_uevent(dev->link->ap, dev, event); | |
126 | +} | |
127 | + | |
128 | +static struct acpi_dock_ops ata_acpi_dev_dock_ops = { | |
129 | + .handler = ata_acpi_dev_notify_dock, | |
130 | + .uevent = ata_acpi_dev_uevent, | |
131 | +}; | |
132 | + | |
133 | +static struct acpi_dock_ops ata_acpi_ap_dock_ops = { | |
134 | + .handler = ata_acpi_ap_notify_dock, | |
135 | + .uevent = ata_acpi_ap_uevent, | |
136 | +}; | |
137 | + | |
138 | /** | |
139 | * ata_acpi_associate - associate ATA host with ACPI objects | |
140 | * @host: target ATA host | |
141 | @@ -244,7 +284,7 @@ void ata_acpi_associate(struct ata_host *host) | |
142 | if (ap->acpi_handle) { | |
143 | /* we might be on a docking station */ | |
144 | register_hotplug_dock_device(ap->acpi_handle, | |
145 | - ata_acpi_ap_notify_dock, ap); | |
146 | + &ata_acpi_ap_dock_ops, ap); | |
147 | } | |
148 | ||
149 | for (j = 0; j < ata_link_max_devices(&ap->link); j++) { | |
150 | @@ -253,7 +293,7 @@ void ata_acpi_associate(struct ata_host *host) | |
151 | if (dev->acpi_handle) { | |
152 | /* we might be on a docking station */ | |
153 | register_hotplug_dock_device(dev->acpi_handle, | |
154 | - ata_acpi_dev_notify_dock, dev); | |
155 | + &ata_acpi_dev_dock_ops, dev); | |
156 | } | |
157 | } | |
158 | } | |
159 | diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c | |
160 | index a3e4705..db54c5e 100644 | |
161 | --- a/drivers/pci/hotplug/acpiphp_glue.c | |
162 | +++ b/drivers/pci/hotplug/acpiphp_glue.c | |
163 | @@ -169,7 +169,9 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val, | |
164 | } | |
165 | ||
166 | ||
167 | - | |
168 | +static struct acpi_dock_ops acpiphp_dock_ops = { | |
169 | + .handler = handle_hotplug_event_func, | |
170 | +}; | |
171 | ||
172 | /* callback routine to register each ACPI PCI slot object */ | |
173 | static acpi_status | |
174 | @@ -285,7 +287,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |
175 | */ | |
176 | newfunc->flags &= ~FUNC_HAS_EJ0; | |
177 | if (register_hotplug_dock_device(handle, | |
178 | - handle_hotplug_event_func, newfunc)) | |
179 | + &acpiphp_dock_ops, newfunc)) | |
180 | dbg("failed to register dock device\n"); | |
181 | ||
182 | /* we need to be notified when dock events happen | |
183 | diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h | |
184 | index e5f38e5..4f5042a 100644 | |
185 | --- a/include/acpi/acpi_drivers.h | |
186 | +++ b/include/acpi/acpi_drivers.h | |
187 | @@ -115,12 +115,17 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type); | |
188 | /*-------------------------------------------------------------------------- | |
189 | Dock Station | |
190 | -------------------------------------------------------------------------- */ | |
191 | +struct acpi_dock_ops { | |
192 | + acpi_notify_handler handler; | |
193 | + acpi_notify_handler uevent; | |
194 | +}; | |
195 | + | |
196 | #if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE) | |
197 | extern int is_dock_device(acpi_handle handle); | |
198 | extern int register_dock_notifier(struct notifier_block *nb); | |
199 | extern void unregister_dock_notifier(struct notifier_block *nb); | |
200 | extern int register_hotplug_dock_device(acpi_handle handle, | |
201 | - acpi_notify_handler handler, | |
202 | + struct acpi_dock_ops *ops, | |
203 | void *context); | |
204 | extern void unregister_hotplug_dock_device(acpi_handle handle); | |
205 | #else | |
206 | @@ -136,7 +141,7 @@ static inline void unregister_dock_notifier(struct notifier_block *nb) | |
207 | { | |
208 | } | |
209 | static inline int register_hotplug_dock_device(acpi_handle handle, | |
210 | - acpi_notify_handler handler, | |
211 | + struct acpi_dock_ops *ops, | |
212 | void *context) | |
213 | { | |
214 | return -ENODEV; |