summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-08-06 14:32:54 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-08-06 14:32:54 +0200
commit007ccfcf89401e764c33965b739310d86a94626d (patch)
tree4d7270405a42bee29537f51e29f1c07b613f9269
parent623cf33cb055b1e81fa47e4fc16789b2c129e31e (diff)
downloadlinux-stable-007ccfcf89401e764c33965b739310d86a94626d.tar.gz
linux-stable-007ccfcf89401e764c33965b739310d86a94626d.tar.bz2
linux-stable-007ccfcf89401e764c33965b739310d86a94626d.zip
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 e2ff394 (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: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Toshi Kani <toshi.kani@hp.com> Reviewed-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
-rw-r--r--drivers/acpi/glue.c34
-rw-r--r--include/acpi/acpi_bus.h8
2 files changed, 21 insertions, 21 deletions
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index f68095756fb7..17e15d11bd39 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -31,6 +31,7 @@ static LIST_HEAD(bus_type_list);
static DECLARE_RWSEM(bus_type_sem);
#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)
{
@@ -112,7 +113,9 @@ 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, *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;
if (ACPI_HANDLE(dev)) {
@@ -139,25 +142,27 @@ int acpi_bind_one(struct device *dev, acpi_handle handle)
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) {
dev_warn(dev, "Already associated with ACPI node\n");
goto err_free;
}
-
- /* 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;
- goto err_free;
+ if (pn->node_id == node_id) {
+ physnode_list = &pn->node;
+ node_id++;
+ }
}
- set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap);
+ physical_node->node_id = node_id;
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++;
mutex_unlock(&acpi_dev->physical_node_lock);
@@ -208,7 +213,7 @@ int acpi_unbind_one(struct device *dev)
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];
+ char physical_node_name[PHYSICAL_NODE_NAME_SIZE];
entry = list_entry(node, struct acpi_device_physical_node,
node);
@@ -216,7 +221,6 @@ int acpi_unbind_one(struct device *dev)
continue;
list_del(node);
- clear_bit(entry->node_id, acpi_dev->physical_node_id_bitmap);
acpi_dev->physical_node_count--;
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 56e6b68c8d2f..5026aaa35133 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -274,15 +274,12 @@ struct acpi_device_wakeup {
};
struct acpi_device_physical_node {
- u8 node_id;
+ unsigned int node_id;
struct list_head node;
struct device *dev;
bool put_online:1;
};
-/* set maximum of physical nodes to 32 for expansibility */
-#define ACPI_MAX_PHYSICAL_NODE 32
-
/* Device */
struct acpi_device {
int device_type;
@@ -302,10 +299,9 @@ struct acpi_device {
struct acpi_driver *driver;
void *driver_data;
struct device dev;
- u8 physical_node_count;
+ unsigned int physical_node_count;
struct list_head physical_node_list;
struct mutex physical_node_lock;
- DECLARE_BITMAP(physical_node_id_bitmap, ACPI_MAX_PHYSICAL_NODE);
struct list_head power_dependent;
void (*remove)(struct acpi_device *);
};