Skip to content

Commit

Permalink
dock: introduce .uevent for devices in dock, eg libata
Browse files Browse the repository at this point in the history
dock's uevent reported itself, not ata. It might be difficult to find an
ata device just according to a dock. This patch introduces docking ops
for each device in a dock. when docking, dock driver can send device
specific uevent. This should help dock station too (not just bay)

Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Acked-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Len Brown <len.brown@intel.com>
  • Loading branch information
Shaohua Li authored and Len Brown committed Sep 24, 2008
1 parent f730ae1 commit 1253f7a
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 13 deletions.
22 changes: 15 additions & 7 deletions drivers/acpi/dock.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ struct dock_dependent_device {
struct list_head list;
struct list_head hotplug_list;
acpi_handle handle;
acpi_notify_handler handler;
struct acpi_dock_ops *ops;
void *context;
};

Expand Down Expand Up @@ -385,8 +385,8 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
* First call driver specific hotplug functions
*/
list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) {
if (dd->handler)
dd->handler(dd->handle, event, dd->context);
if (dd->ops && dd->ops->handler)
dd->ops->handler(dd->handle, event, dd->context);
}

/*
Expand All @@ -409,6 +409,7 @@ static void dock_event(struct dock_station *ds, u32 event, int num)
struct device *dev = &ds->dock_device->dev;
char event_string[13];
char *envp[] = { event_string, NULL };
struct dock_dependent_device *dd;

if (num == UNDOCK_EVENT)
sprintf(event_string, "EVENT=undock");
Expand All @@ -419,7 +420,14 @@ static void dock_event(struct dock_station *ds, u32 event, int num)
* Indicate that the status of the dock station has
* changed.
*/
kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
if (num == DOCK_EVENT)
kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);

list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list)
if (dd->ops && dd->ops->uevent)
dd->ops->uevent(dd->handle, event, dd->context);
if (num != DOCK_EVENT)
kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
}

/**
Expand Down Expand Up @@ -588,15 +596,15 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier);
/**
* register_hotplug_dock_device - register a hotplug function
* @handle: the handle of the device
* @handler: the acpi_notifier_handler to call after docking
* @ops: handlers to call after docking
* @context: device specific data
*
* If a driver would like to perform a hotplug operation after a dock
* event, they can register an acpi_notifiy_handler to be called by
* the dock driver after _DCK is executed.
*/
int
register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler,
register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops,
void *context)
{
struct dock_dependent_device *dd;
Expand All @@ -612,7 +620,7 @@ register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler,
list_for_each_entry(dock_station, &dock_stations, sibiling) {
dd = find_dock_dependent_device(dock_station, handle);
if (dd) {
dd->handler = handler;
dd->ops = ops;
dd->context = context;
dock_add_hotplug_device(dock_station, dd);
return 0;
Expand Down
44 changes: 42 additions & 2 deletions drivers/ata/libata-acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,46 @@ static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data)
ata_acpi_handle_hotplug(ap, NULL, event);
}

static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev,
u32 event)
{
struct kobject *kobj = NULL;
char event_string[20];
char *envp[] = { event_string, NULL };

if (dev) {
if (dev->sdev)
kobj = &dev->sdev->sdev_gendev.kobj;
} else
kobj = &ap->dev->kobj;

if (kobj) {
snprintf(event_string, 20, "BAY_EVENT=%d", event);
kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
}
}

static void ata_acpi_ap_uevent(acpi_handle handle, u32 event, void *data)
{
ata_acpi_uevent(data, NULL, event);
}

static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data)
{
struct ata_device *dev = data;
ata_acpi_uevent(dev->link->ap, dev, event);
}

static struct acpi_dock_ops ata_acpi_dev_dock_ops = {
.handler = ata_acpi_dev_notify_dock,
.uevent = ata_acpi_dev_uevent,
};

static struct acpi_dock_ops ata_acpi_ap_dock_ops = {
.handler = ata_acpi_ap_notify_dock,
.uevent = ata_acpi_ap_uevent,
};

/**
* ata_acpi_associate - associate ATA host with ACPI objects
* @host: target ATA host
Expand Down Expand Up @@ -244,7 +284,7 @@ void ata_acpi_associate(struct ata_host *host)
if (ap->acpi_handle) {
/* we might be on a docking station */
register_hotplug_dock_device(ap->acpi_handle,
ata_acpi_ap_notify_dock, ap);
&ata_acpi_ap_dock_ops, ap);
}

for (j = 0; j < ata_link_max_devices(&ap->link); j++) {
Expand All @@ -253,7 +293,7 @@ void ata_acpi_associate(struct ata_host *host)
if (dev->acpi_handle) {
/* we might be on a docking station */
register_hotplug_dock_device(dev->acpi_handle,
ata_acpi_dev_notify_dock, dev);
&ata_acpi_dev_dock_ops, dev);
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions drivers/pci/hotplug/acpiphp_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,9 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
}



static struct acpi_dock_ops acpiphp_dock_ops = {
.handler = handle_hotplug_event_func,
};

/* callback routine to register each ACPI PCI slot object */
static acpi_status
Expand Down Expand Up @@ -285,7 +287,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
*/
newfunc->flags &= ~FUNC_HAS_EJ0;
if (register_hotplug_dock_device(handle,
handle_hotplug_event_func, newfunc))
&acpiphp_dock_ops, newfunc))
dbg("failed to register dock device\n");

/* we need to be notified when dock events happen
Expand Down
9 changes: 7 additions & 2 deletions include/acpi/acpi_drivers.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,17 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type);
/*--------------------------------------------------------------------------
Dock Station
-------------------------------------------------------------------------- */
struct acpi_dock_ops {
acpi_notify_handler handler;
acpi_notify_handler uevent;
};

#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
extern int is_dock_device(acpi_handle handle);
extern int register_dock_notifier(struct notifier_block *nb);
extern void unregister_dock_notifier(struct notifier_block *nb);
extern int register_hotplug_dock_device(acpi_handle handle,
acpi_notify_handler handler,
struct acpi_dock_ops *ops,
void *context);
extern void unregister_hotplug_dock_device(acpi_handle handle);
#else
Expand All @@ -136,7 +141,7 @@ static inline void unregister_dock_notifier(struct notifier_block *nb)
{
}
static inline int register_hotplug_dock_device(acpi_handle handle,
acpi_notify_handler handler,
struct acpi_dock_ops *ops,
void *context)
{
return -ENODEV;
Expand Down

0 comments on commit 1253f7a

Please sign in to comment.