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
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)
11 Signed-off-by: Shaohua Li <shaohua.li@intel.com>
12 Signed-off-by: Holger Macht <hmacht@suse.de>
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;
23 - acpi_notify_handler handler;
24 + struct acpi_dock_ops *ops;
28 @@ -385,8 +385,8 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
29 * First call driver specific hotplug functions
31 list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) {
33 - dd->handler(dd->handle, event, dd->context);
34 + if (dd->ops && dd->ops->handler)
35 + dd->ops->handler(dd->handle, event, dd->context);
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;
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
51 - kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
52 + if (num == DOCK_EVENT)
53 + kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
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);
63 @@ -588,7 +596,7 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier);
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
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.
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,
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);
85 - dd->handler = handler;
87 dd->context = context;
88 dock_add_hotplug_device(dock_station, dd);
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);
98 +static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev,
101 + struct kobject *kobj = NULL;
102 + char event_string[20];
103 + char *envp[] = { event_string, NULL };
107 + kobj = &dev->sdev->sdev_gendev.kobj;
109 + kobj = &ap->dev->kobj;
112 + snprintf(event_string, 20, "BAY_EVENT=%d", event);
113 + kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
117 +static void ata_acpi_ap_uevent(acpi_handle handle, u32 event, void *data)
119 + ata_acpi_uevent(data, NULL, event);
122 +static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data)
124 + struct ata_device *dev = data;
125 + ata_acpi_uevent(dev->link->ap, dev, event);
128 +static struct acpi_dock_ops ata_acpi_dev_dock_ops = {
129 + .handler = ata_acpi_dev_notify_dock,
130 + .uevent = ata_acpi_dev_uevent,
133 +static struct acpi_dock_ops ata_acpi_ap_dock_ops = {
134 + .handler = ata_acpi_ap_notify_dock,
135 + .uevent = ata_acpi_ap_uevent,
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);
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);
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,
168 +static struct acpi_dock_ops acpiphp_dock_ops = {
169 + .handler = handle_hotplug_event_func,
172 /* callback routine to register each ACPI PCI slot object */
174 @@ -285,7 +287,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
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");
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 /*--------------------------------------------------------------------------
190 -------------------------------------------------------------------------- */
191 +struct acpi_dock_ops {
192 + acpi_notify_handler handler;
193 + acpi_notify_handler uevent;
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,
204 extern void unregister_hotplug_dock_device(acpi_handle handle);
206 @@ -136,7 +141,7 @@ static inline void unregister_dock_notifier(struct notifier_block *nb)
209 static inline int register_hotplug_dock_device(acpi_handle handle,
210 - acpi_notify_handler handler,
211 + struct acpi_dock_ops *ops,