Commit 007ccfcf authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

ACPI: Drop physical_node_id_bitmap from struct acpi_device

The physical_node_id_bitmap in struct acpi_device is only used for
looking up the first currently unused dependent phyiscal node ID
by acpi_bind_one().  It is not really necessary, however, because
acpi_bind_one() walks the entire physical_node_list of the given
device object for sanity checking anyway and if that list is always
sorted by node_id, it is straightforward to find the first gap
between the currently used node IDs and use that number as the ID
of the new list node.

This also removes the artificial limit of the maximum number of
dependent physical devices per ACPI device object, which now depends
only on the capacity of unsigend int.  As a result, it fixes a
regression introduced by commit e2ff3940 (ACPI / memhotplug: Bind
removable memory blocks to ACPI device nodes) that caused
acpi_memory_enable_device() to fail when the number of 128 MB blocks
within one removable memory module was greater than 32.
Reported-and-tested-by: default avatarYasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: default avatarToshi Kani <toshi.kani@hp.com>
Reviewed-by: default avatarYasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
parent 623cf33c
...@@ -31,6 +31,7 @@ static LIST_HEAD(bus_type_list); ...@@ -31,6 +31,7 @@ static LIST_HEAD(bus_type_list);
static DECLARE_RWSEM(bus_type_sem); static DECLARE_RWSEM(bus_type_sem);
#define PHYSICAL_NODE_STRING "physical_node" #define PHYSICAL_NODE_STRING "physical_node"
#define PHYSICAL_NODE_NAME_SIZE (sizeof(PHYSICAL_NODE_STRING) + 10)
int register_acpi_bus_type(struct acpi_bus_type *type) int register_acpi_bus_type(struct acpi_bus_type *type)
{ {
...@@ -112,7 +113,9 @@ int acpi_bind_one(struct device *dev, acpi_handle handle) ...@@ -112,7 +113,9 @@ int acpi_bind_one(struct device *dev, acpi_handle handle)
struct acpi_device *acpi_dev; struct acpi_device *acpi_dev;
acpi_status status; acpi_status status;
struct acpi_device_physical_node *physical_node, *pn; struct acpi_device_physical_node *physical_node, *pn;
char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2]; char physical_node_name[PHYSICAL_NODE_NAME_SIZE];
struct list_head *physnode_list;
unsigned int node_id;
int retval = -EINVAL; int retval = -EINVAL;
if (ACPI_HANDLE(dev)) { if (ACPI_HANDLE(dev)) {
...@@ -139,25 +142,27 @@ int acpi_bind_one(struct device *dev, acpi_handle handle) ...@@ -139,25 +142,27 @@ int acpi_bind_one(struct device *dev, acpi_handle handle)
mutex_lock(&acpi_dev->physical_node_lock); mutex_lock(&acpi_dev->physical_node_lock);
/* Sanity check. */ /*
list_for_each_entry(pn, &acpi_dev->physical_node_list, node) * Keep the list sorted by node_id so that the IDs of removed nodes can
* be recycled easily.
*/
physnode_list = &acpi_dev->physical_node_list;
node_id = 0;
list_for_each_entry(pn, &acpi_dev->physical_node_list, node) {
/* Sanity check. */
if (pn->dev == dev) { if (pn->dev == dev) {
dev_warn(dev, "Already associated with ACPI node\n"); dev_warn(dev, "Already associated with ACPI node\n");
goto err_free; goto err_free;
} }
if (pn->node_id == node_id) {
/* allocate physical node id according to physical_node_id_bitmap */ physnode_list = &pn->node;
physical_node->node_id = 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;
goto err_free;
} }
set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap); physical_node->node_id = node_id;
physical_node->dev = dev; physical_node->dev = dev;
list_add_tail(&physical_node->node, &acpi_dev->physical_node_list); list_add(&physical_node->node, physnode_list);
acpi_dev->physical_node_count++; acpi_dev->physical_node_count++;
mutex_unlock(&acpi_dev->physical_node_lock); mutex_unlock(&acpi_dev->physical_node_lock);
...@@ -208,7 +213,7 @@ int acpi_unbind_one(struct device *dev) ...@@ -208,7 +213,7 @@ int acpi_unbind_one(struct device *dev)
mutex_lock(&acpi_dev->physical_node_lock); mutex_lock(&acpi_dev->physical_node_lock);
list_for_each_safe(node, next, &acpi_dev->physical_node_list) { list_for_each_safe(node, next, &acpi_dev->physical_node_list) {
char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2]; char physical_node_name[PHYSICAL_NODE_NAME_SIZE];
entry = list_entry(node, struct acpi_device_physical_node, entry = list_entry(node, struct acpi_device_physical_node,
node); node);
...@@ -216,7 +221,6 @@ int acpi_unbind_one(struct device *dev) ...@@ -216,7 +221,6 @@ int acpi_unbind_one(struct device *dev)
continue; continue;
list_del(node); list_del(node);
clear_bit(entry->node_id, acpi_dev->physical_node_id_bitmap);
acpi_dev->physical_node_count--; acpi_dev->physical_node_count--;
......
...@@ -274,15 +274,12 @@ struct acpi_device_wakeup { ...@@ -274,15 +274,12 @@ struct acpi_device_wakeup {
}; };
struct acpi_device_physical_node { struct acpi_device_physical_node {
u8 node_id; unsigned int node_id;
struct list_head node; struct list_head node;
struct device *dev; struct device *dev;
bool put_online:1; bool put_online:1;
}; };
/* set maximum of physical nodes to 32 for expansibility */
#define ACPI_MAX_PHYSICAL_NODE 32
/* Device */ /* Device */
struct acpi_device { struct acpi_device {
int device_type; int device_type;
...@@ -302,10 +299,9 @@ struct acpi_device { ...@@ -302,10 +299,9 @@ struct acpi_device {
struct acpi_driver *driver; struct acpi_driver *driver;
void *driver_data; void *driver_data;
struct device dev; struct device dev;
u8 physical_node_count; unsigned int physical_node_count;
struct list_head physical_node_list; struct list_head physical_node_list;
struct mutex physical_node_lock; struct mutex physical_node_lock;
DECLARE_BITMAP(physical_node_id_bitmap, ACPI_MAX_PHYSICAL_NODE);
struct list_head power_dependent; struct list_head power_dependent;
void (*remove)(struct acpi_device *); void (*remove)(struct acpi_device *);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment