Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 331747
b: refs/heads/master
c: 1033f90
h: refs/heads/master
i:
  331745: 3da8dcb
  331743: b7a6f8b
v: v3
  • Loading branch information
Lan Tianyu authored and Len Brown committed Sep 21, 2012
1 parent b3a32a3 commit d950fcd
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 311 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f9240813e61cb3e5838c9ab0237af831c61df7cf
refs/heads/master: 1033f9041d526dd694e2b2e12744e47c41040c4d
135 changes: 86 additions & 49 deletions trunk/drivers/acpi/glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
static LIST_HEAD(bus_type_list);
static DECLARE_RWSEM(bus_type_sem);

#define PHYSICAL_NODE_STRING "physical_node"

int register_acpi_bus_type(struct acpi_bus_type *type)
{
if (acpi_disabled)
Expand Down Expand Up @@ -124,84 +126,119 @@ acpi_handle acpi_get_child(acpi_handle parent, u64 address)

EXPORT_SYMBOL(acpi_get_child);

/* Link ACPI devices with physical devices */
static void acpi_glue_data_handler(acpi_handle handle,
void *context)
{
/* we provide an empty handler */
}

/* Note: a success call will increase reference count by one */
struct device *acpi_get_physical_device(acpi_handle handle)
{
acpi_status status;
struct device *dev;

status = acpi_get_data(handle, acpi_glue_data_handler, (void **)&dev);
if (ACPI_SUCCESS(status))
return get_device(dev);
return NULL;
}

EXPORT_SYMBOL(acpi_get_physical_device);

static int acpi_bind_one(struct device *dev, acpi_handle handle)
{
struct acpi_device *acpi_dev;
acpi_status status;
struct acpi_device_physical_node *physical_node;
char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
int retval = -EINVAL;

if (dev->archdata.acpi_handle) {
dev_warn(dev, "Drivers changed 'acpi_handle'\n");
return -EINVAL;
}

get_device(dev);
status = acpi_attach_data(handle, acpi_glue_data_handler, dev);
if (ACPI_FAILURE(status)) {
put_device(dev);
return -EINVAL;
status = acpi_bus_get_device(handle, &acpi_dev);
if (ACPI_FAILURE(status))
goto err;

physical_node = kzalloc(sizeof(struct acpi_device_physical_node),
GFP_KERNEL);
if (!physical_node) {
retval = -ENOMEM;
goto err;
}
dev->archdata.acpi_handle = handle;

status = acpi_bus_get_device(handle, &acpi_dev);
if (!ACPI_FAILURE(status)) {
int ret;

ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
"firmware_node");
ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
"physical_node");
if (acpi_dev->wakeup.flags.valid)
device_set_wakeup_capable(dev, true);
mutex_lock(&acpi_dev->physical_node_lock);
/* allocate physical node id according to physical_node_id_bitmap */
physical_node->node_id =
find_first_zero_bit(acpi_dev->physical_node_id_bitmap,
ACPI_MAX_PHYSICAL_NODE);
if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {
retval = -ENOSPC;
mutex_unlock(&acpi_dev->physical_node_lock);
goto err;
}

set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap);
physical_node->dev = dev;
list_add_tail(&physical_node->node, &acpi_dev->physical_node_list);
acpi_dev->physical_node_count++;
mutex_unlock(&acpi_dev->physical_node_lock);

dev->archdata.acpi_handle = handle;

if (!physical_node->node_id)
strcpy(physical_node_name, PHYSICAL_NODE_STRING);
else
sprintf(physical_node_name,
"physical_node%d", physical_node->node_id);
retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
physical_node_name);
retval = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
"firmware_node");

if (acpi_dev->wakeup.flags.valid)
device_set_wakeup_capable(dev, true);

return 0;

err:
put_device(dev);
return retval;
}

static int acpi_unbind_one(struct device *dev)
{
struct acpi_device_physical_node *entry;
struct acpi_device *acpi_dev;
acpi_status status;
struct list_head *node, *next;

if (!dev->archdata.acpi_handle)
return 0;
if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) {
struct acpi_device *acpi_dev;

/* acpi_get_physical_device increase refcnt by one */
put_device(dev);
status = acpi_bus_get_device(dev->archdata.acpi_handle,
&acpi_dev);
if (ACPI_FAILURE(status))
goto err;

if (!acpi_bus_get_device(dev->archdata.acpi_handle,
&acpi_dev)) {
sysfs_remove_link(&dev->kobj, "firmware_node");
sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node");
}
mutex_lock(&acpi_dev->physical_node_lock);
list_for_each_safe(node, next, &acpi_dev->physical_node_list) {
char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];

entry = list_entry(node, struct acpi_device_physical_node,
node);
if (entry->dev != dev)
continue;

list_del(node);
clear_bit(entry->node_id, acpi_dev->physical_node_id_bitmap);

acpi_detach_data(dev->archdata.acpi_handle,
acpi_glue_data_handler);
acpi_dev->physical_node_count--;

if (!entry->node_id)
strcpy(physical_node_name, PHYSICAL_NODE_STRING);
else
sprintf(physical_node_name,
"physical_node%d", entry->node_id);

sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name);
sysfs_remove_link(&dev->kobj, "firmware_node");
dev->archdata.acpi_handle = NULL;
/* acpi_bind_one increase refcnt by one */
put_device(dev);
} else {
dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
kfree(entry);
}
mutex_unlock(&acpi_dev->physical_node_lock);

return 0;

err:
dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
return -EINVAL;
}

static int acpi_platform_notify(struct device *dev)
Expand Down
57 changes: 37 additions & 20 deletions trunk/drivers/acpi/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,39 +302,56 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
struct acpi_device *dev =
container_of(node, struct acpi_device, wakeup_list);
struct device *ldev;
struct acpi_device_physical_node *entry;

if (!dev->wakeup.flags.valid)
continue;

ldev = acpi_get_physical_device(dev->handle);
seq_printf(seq, "%s\t S%d\t%c%-8s ",
seq_printf(seq, "%s\t S%d\t",
dev->pnp.bus_id,
(u32) dev->wakeup.sleep_state,
dev->wakeup.flags.run_wake ? '*' : ' ',
(device_may_wakeup(&dev->dev)
|| (ldev && device_may_wakeup(ldev))) ?
"enabled" : "disabled");
if (ldev)
seq_printf(seq, "%s:%s",
ldev->bus ? ldev->bus->name : "no-bus",
dev_name(ldev));
seq_printf(seq, "\n");
put_device(ldev);

(u32) dev->wakeup.sleep_state);

if (!dev->physical_node_count)
seq_printf(seq, "%c%-8s\n",
dev->wakeup.flags.run_wake ?
'*' : ' ', "disabled");
else {
struct device *ldev;
list_for_each_entry(entry, &dev->physical_node_list,
node) {
ldev = get_device(entry->dev);
if (!ldev)
continue;

if (&entry->node !=
dev->physical_node_list.next)
seq_printf(seq, "\t\t");

seq_printf(seq, "%c%-8s %s:%s\n",
dev->wakeup.flags.run_wake ? '*' : ' ',
(device_may_wakeup(&dev->dev) ||
(ldev && device_may_wakeup(ldev))) ?
"enabled" : "disabled",
ldev->bus ? ldev->bus->name :
"no-bus", dev_name(ldev));
put_device(ldev);
}
}
}
mutex_unlock(&acpi_device_lock);
return 0;
}

static void physical_device_enable_wakeup(struct acpi_device *adev)
{
struct device *dev = acpi_get_physical_device(adev->handle);
struct acpi_device_physical_node *entry;

if (dev && device_can_wakeup(dev)) {
bool enable = !device_may_wakeup(dev);
device_set_wakeup_enable(dev, enable);
}
list_for_each_entry(entry,
&adev->physical_node_list, node)
if (entry->dev && device_can_wakeup(entry->dev)) {
bool enable = !device_may_wakeup(entry->dev);
device_set_wakeup_enable(entry->dev, enable);
}
}

static ssize_t
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/acpi/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,8 @@ static int acpi_device_register(struct acpi_device *device)
INIT_LIST_HEAD(&device->children);
INIT_LIST_HEAD(&device->node);
INIT_LIST_HEAD(&device->wakeup_list);
INIT_LIST_HEAD(&device->physical_node_list);
mutex_init(&device->physical_node_lock);

new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
if (!new_bus_id) {
Expand Down
7 changes: 1 addition & 6 deletions trunk/drivers/pnp/pnpacpi/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,14 +321,9 @@ static int __init acpi_pnp_match(struct device *dev, void *_pnp)
{
struct acpi_device *acpi = to_acpi_device(dev);
struct pnp_dev *pnp = _pnp;
struct device *physical_device;

physical_device = acpi_get_physical_device(acpi->handle);
if (physical_device)
put_device(physical_device);

/* true means it matched */
return !physical_device
return !acpi->physical_node_count
&& compare_pnp_id(pnp->id, acpi_device_hid(acpi));
}

Expand Down
15 changes: 13 additions & 2 deletions trunk/include/acpi/acpi_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,16 @@ struct acpi_device_wakeup {
int prepare_count;
};

/* Device */
struct acpi_device_physical_node {
u8 node_id;
struct list_head node;
struct device *dev;
};

/* set maximum of physical nodes to 32 for expansibility */
#define ACPI_MAX_PHYSICAL_NODE 32

/* Device */
struct acpi_device {
int device_type;
acpi_handle handle; /* no handle for fixed hardware */
Expand All @@ -304,6 +312,10 @@ struct acpi_device {
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 */
u8 physical_node_count;
struct list_head physical_node_list;
struct mutex physical_node_lock;
DECLARE_BITMAP(physical_node_id_bitmap, ACPI_MAX_PHYSICAL_NODE);
};

static inline void *acpi_driver_data(struct acpi_device *d)
Expand Down Expand Up @@ -394,7 +406,6 @@ struct acpi_bus_type {
};
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;
Expand Down
Loading

0 comments on commit d950fcd

Please sign in to comment.