aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/glue.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-08-06 08:32:54 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-08-06 08:32:54 -0400
commit007ccfcf89401e764c33965b739310d86a94626d (patch)
tree4d7270405a42bee29537f51e29f1c07b613f9269 /drivers/acpi/glue.c
parent623cf33cb055b1e81fa47e4fc16789b2c129e31e (diff)
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>
Diffstat (limited to 'drivers/acpi/glue.c')
-rw-r--r--drivers/acpi/glue.c34
1 files changed, 19 insertions, 15 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);
31static DECLARE_RWSEM(bus_type_sem); 31static DECLARE_RWSEM(bus_type_sem);
32 32
33#define PHYSICAL_NODE_STRING "physical_node" 33#define PHYSICAL_NODE_STRING "physical_node"
34#define PHYSICAL_NODE_NAME_SIZE (sizeof(PHYSICAL_NODE_STRING) + 10)
34 35
35int register_acpi_bus_type(struct acpi_bus_type *type) 36int register_acpi_bus_type(struct acpi_bus_type *type)
36{ 37{
@@ -112,7 +113,9 @@ int acpi_bind_one(struct device *dev, acpi_handle handle)
112 struct acpi_device *acpi_dev; 113 struct acpi_device *acpi_dev;
113 acpi_status status; 114 acpi_status status;
114 struct acpi_device_physical_node *physical_node, *pn; 115 struct acpi_device_physical_node *physical_node, *pn;
115 char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2]; 116 char physical_node_name[PHYSICAL_NODE_NAME_SIZE];
117 struct list_head *physnode_list;
118 unsigned int node_id;
116 int retval = -EINVAL; 119 int retval = -EINVAL;
117 120
118 if (ACPI_HANDLE(dev)) { 121 if (ACPI_HANDLE(dev)) {
@@ -139,25 +142,27 @@ int acpi_bind_one(struct device *dev, acpi_handle handle)
139 142
140 mutex_lock(&acpi_dev->physical_node_lock); 143 mutex_lock(&acpi_dev->physical_node_lock);
141 144
142 /* Sanity check. */ 145 /*
143 list_for_each_entry(pn, &acpi_dev->physical_node_list, node) 146 * Keep the list sorted by node_id so that the IDs of removed nodes can
147 * be recycled easily.
148 */
149 physnode_list = &acpi_dev->physical_node_list;
150 node_id = 0;
151 list_for_each_entry(pn, &acpi_dev->physical_node_list, node) {
152 /* Sanity check. */
144 if (pn->dev == dev) { 153 if (pn->dev == dev) {
145 dev_warn(dev, "Already associated with ACPI node\n"); 154 dev_warn(dev, "Already associated with ACPI node\n");
146 goto err_free; 155 goto err_free;
147 } 156 }
148 157 if (pn->node_id == node_id) {
149 /* allocate physical node id according to physical_node_id_bitmap */ 158 physnode_list = &pn->node;
150 physical_node->node_id = 159 node_id++;
151 find_first_zero_bit(acpi_dev->physical_node_id_bitmap, 160 }
152 ACPI_MAX_PHYSICAL_NODE);
153 if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {
154 retval = -ENOSPC;
155 goto err_free;
156 } 161 }
157 162
158 set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap); 163 physical_node->node_id = node_id;
159 physical_node->dev = dev; 164 physical_node->dev = dev;
160 list_add_tail(&physical_node->node, &acpi_dev->physical_node_list); 165 list_add(&physical_node->node, physnode_list);
161 acpi_dev->physical_node_count++; 166 acpi_dev->physical_node_count++;
162 167
163 mutex_unlock(&acpi_dev->physical_node_lock); 168 mutex_unlock(&acpi_dev->physical_node_lock);
@@ -208,7 +213,7 @@ int acpi_unbind_one(struct device *dev)
208 213
209 mutex_lock(&acpi_dev->physical_node_lock); 214 mutex_lock(&acpi_dev->physical_node_lock);
210 list_for_each_safe(node, next, &acpi_dev->physical_node_list) { 215 list_for_each_safe(node, next, &acpi_dev->physical_node_list) {
211 char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2]; 216 char physical_node_name[PHYSICAL_NODE_NAME_SIZE];
212 217
213 entry = list_entry(node, struct acpi_device_physical_node, 218 entry = list_entry(node, struct acpi_device_physical_node,
214 node); 219 node);
@@ -216,7 +221,6 @@ int acpi_unbind_one(struct device *dev)
216 continue; 221 continue;
217 222
218 list_del(node); 223 list_del(node);
219 clear_bit(entry->node_id, acpi_dev->physical_node_id_bitmap);
220 224
221 acpi_dev->physical_node_count--; 225 acpi_dev->physical_node_count--;
222 226