Blame view

drivers/acpi/acpi_memhotplug.c 10.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
2
3
4
   * Copyright (C) 2004, 2013 Intel Corporation
   * Author: Naveen B S <naveen.b.s@intel.com>
   * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
10
11
12
13
14
15
16
17
18
   *
   * All rights reserved.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or (at
   * your option) any later version.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
   * NON INFRINGEMENT.  See the GNU General Public License for more
   * details.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
   * ACPI based HotPlug driver that supports Memory Hotplug
c7060d9e9   Nick Andrew   trivial: Fix miss...
20
   * This driver fields notifications from firmware for memory add
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
   * and remove operations and alerts the VM of the affected memory
   * ranges.
   */
ab6c57099   Toshi Kani   ACPI: Update Memo...
24
  #include <linux/acpi.h>
e2ff39400   Rafael J. Wysocki   ACPI / memhotplug...
25
  #include <linux/memory.h>
0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
26
27
28
  #include <linux/memory_hotplug.h>
  
  #include "internal.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
  #define ACPI_MEMORY_DEVICE_CLASS		"memory"
  #define ACPI_MEMORY_DEVICE_HID			"PNP0C80"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
  #define ACPI_MEMORY_DEVICE_NAME			"Hotplug Mem Device"
  
  #define _COMPONENT		ACPI_MEMORY_DEVICE_COMPONENT
aa7b2b2e9   Zhao Yakui   ACPI: Don't treat...
35
36
  #undef PREFIX
  #define 	PREFIX		"ACPI:memory_hp:"
f52fd66d2   Len Brown   ACPI: clean up AC...
37
  ACPI_MODULE_NAME("acpi_memhotplug");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38

cccd42085   Rafael J. Wysocki   ACPI / scan: alwa...
39
40
41
42
43
44
  static const struct acpi_device_id memory_device_ids[] = {
  	{ACPI_MEMORY_DEVICE_HID, 0},
  	{"", 0},
  };
  
  #ifdef CONFIG_ACPI_HOTPLUG_MEMORY
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
  /* Memory Device States */
  #define MEMORY_INVALID_STATE	0
  #define MEMORY_POWER_ON_STATE	1
  #define MEMORY_POWER_OFF_STATE	2
0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
49
50
51
  static int acpi_memory_device_add(struct acpi_device *device,
  				  const struct acpi_device_id *not_used);
  static void acpi_memory_device_remove(struct acpi_device *device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52

0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
53
  static struct acpi_scan_handler memory_device_handler = {
1ba90e3a8   Thomas Renninger   ACPI: autoload mo...
54
  	.ids = memory_device_ids,
0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
55
56
57
58
59
  	.attach = acpi_memory_device_add,
  	.detach = acpi_memory_device_remove,
  	.hotplug = {
  		.enabled = true,
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
  };
9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
61
62
63
64
65
66
67
68
  struct acpi_memory_info {
  	struct list_head list;
  	u64 start_addr;		/* Memory Range start physical addr */
  	u64 length;		/* Memory Range length */
  	unsigned short caching;	/* memory cache attribute */
  	unsigned short write_protect;	/* memory read/write attribute */
  	unsigned int enabled:1;
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
  struct acpi_memory_device {
3b74863df   Patrick Mochel   ACPI: acpi_memhot...
70
  	struct acpi_device * device;
4be44fcd3   Len Brown   [ACPI] Lindent al...
71
  	unsigned int state;	/* State of the memory device */
9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
72
  	struct list_head res_list;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
  };
9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
  static acpi_status
  acpi_memory_get_resource(struct acpi_resource *resource, void *context)
  {
  	struct acpi_memory_device *mem_device = context;
  	struct acpi_resource_address64 address64;
  	struct acpi_memory_info *info, *new;
  	acpi_status status;
  
  	status = acpi_resource_to_address64(resource, &address64);
  	if (ACPI_FAILURE(status) ||
  	    (address64.resource_type != ACPI_MEMORY_RANGE))
  		return AE_OK;
  
  	list_for_each_entry(info, &mem_device->res_list, list) {
  		/* Can we combine the resource range information? */
  		if ((info->caching == address64.info.mem.caching) &&
  		    (info->write_protect == address64.info.mem.write_protect) &&
a45de93eb   Lv Zheng   ACPICA: Resources...
91
92
  		    (info->start_addr + info->length == address64.address.minimum)) {
  			info->length += address64.address.address_length;
9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
93
94
95
96
97
98
99
100
101
102
103
  			return AE_OK;
  		}
  	}
  
  	new = kzalloc(sizeof(struct acpi_memory_info), GFP_KERNEL);
  	if (!new)
  		return AE_ERROR;
  
  	INIT_LIST_HEAD(&new->list);
  	new->caching = address64.info.mem.caching;
  	new->write_protect = address64.info.mem.write_protect;
a45de93eb   Lv Zheng   ACPICA: Resources...
104
105
  	new->start_addr = address64.address.minimum;
  	new->length = address64.address.address_length;
9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
106
107
108
109
  	list_add_tail(&new->list, &mem_device->res_list);
  
  	return AE_OK;
  }
386e52b95   Wen Congyang   ACPI / memhotplug...
110
111
112
113
114
115
116
117
118
  static void
  acpi_memory_free_device_resources(struct acpi_memory_device *mem_device)
  {
  	struct acpi_memory_info *info, *n;
  
  	list_for_each_entry_safe(info, n, &mem_device->res_list, list)
  		kfree(info);
  	INIT_LIST_HEAD(&mem_device->res_list);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
120
121
122
  static int
  acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
  {
  	acpi_status status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123

5d2870faa   KAMEZAWA Hiroyuki   [PATCH] memory ho...
124
125
  	if (!list_empty(&mem_device->res_list))
  		return 0;
b86327852   Patrick Mochel   ACPI: acpi_memhot...
126
  	status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS,
9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
127
128
  				     acpi_memory_get_resource, mem_device);
  	if (ACPI_FAILURE(status)) {
386e52b95   Wen Congyang   ACPI / memhotplug...
129
  		acpi_memory_free_device_resources(mem_device);
d550d98d3   Patrick Mochel   ACPI: delete trac...
130
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
  	}
d550d98d3   Patrick Mochel   ACPI: delete trac...
132
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
134
  static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
  {
27663c585   Matthew Wilcox   ACPI: Change acpi...
136
  	unsigned long long current_status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
  
  	/* Get device present/absent information from the _STA */
16ff816d3   Zhang Yanfei   ACPI / memhotplug...
139
140
141
  	if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle,
  					       METHOD_NAME__STA, NULL,
  					       &current_status)))
d550d98d3   Patrick Mochel   ACPI: delete trac...
142
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
146
  	/*
  	 * Check for device status. Device should be
  	 * present/enabled/functioning.
  	 */
a0bd4ac49   Bjorn Helgaas   ACPI: Remove dupl...
147
148
149
  	if (!((current_status & ACPI_STA_DEVICE_PRESENT)
  	      && (current_status & ACPI_STA_DEVICE_ENABLED)
  	      && (current_status & ACPI_STA_DEVICE_FUNCTIONING)))
d550d98d3   Patrick Mochel   ACPI: delete trac...
150
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151

d550d98d3   Patrick Mochel   ACPI: delete trac...
152
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
  }
e2ff39400   Rafael J. Wysocki   ACPI / memhotplug...
154
155
156
157
158
159
160
161
162
163
164
165
  static unsigned long acpi_meminfo_start_pfn(struct acpi_memory_info *info)
  {
  	return PFN_DOWN(info->start_addr);
  }
  
  static unsigned long acpi_meminfo_end_pfn(struct acpi_memory_info *info)
  {
  	return PFN_UP(info->start_addr + info->length-1);
  }
  
  static int acpi_bind_memblk(struct memory_block *mem, void *arg)
  {
24dee1fc9   Rafael J. Wysocki   ACPI / bind: Pass...
166
  	return acpi_bind_one(&mem->dev, arg);
e2ff39400   Rafael J. Wysocki   ACPI / memhotplug...
167
168
169
  }
  
  static int acpi_bind_memory_blocks(struct acpi_memory_info *info,
24dee1fc9   Rafael J. Wysocki   ACPI / bind: Pass...
170
  				   struct acpi_device *adev)
e2ff39400   Rafael J. Wysocki   ACPI / memhotplug...
171
172
  {
  	return walk_memory_range(acpi_meminfo_start_pfn(info),
24dee1fc9   Rafael J. Wysocki   ACPI / bind: Pass...
173
  				 acpi_meminfo_end_pfn(info), adev,
e2ff39400   Rafael J. Wysocki   ACPI / memhotplug...
174
175
176
177
178
179
180
181
  				 acpi_bind_memblk);
  }
  
  static int acpi_unbind_memblk(struct memory_block *mem, void *arg)
  {
  	acpi_unbind_one(&mem->dev);
  	return 0;
  }
24dee1fc9   Rafael J. Wysocki   ACPI / bind: Pass...
182
  static void acpi_unbind_memory_blocks(struct acpi_memory_info *info)
e2ff39400   Rafael J. Wysocki   ACPI / memhotplug...
183
184
185
186
  {
  	walk_memory_range(acpi_meminfo_start_pfn(info),
  			  acpi_meminfo_end_pfn(info), NULL, acpi_unbind_memblk);
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
187
  static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  {
e2ff39400   Rafael J. Wysocki   ACPI / memhotplug...
189
  	acpi_handle handle = mem_device->device->handle;
9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
190
191
  	int result, num_enabled = 0;
  	struct acpi_memory_info *info;
1e3590e2e   Yasunori Goto   [PATCH] pgdat all...
192
  	int node;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193

e2ff39400   Rafael J. Wysocki   ACPI / memhotplug...
194
  	node = acpi_get_node(handle);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
197
  	/*
  	 * Tell the VM there is more memory here...
  	 * Note: Assume that this function returns zero on success
9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
198
199
  	 * We don't have memory-hot-add rollback function,now.
  	 * (i.e. memory-hot-remove function)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  	 */
9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
201
  	list_for_each_entry(info, &mem_device->res_list, list) {
fa25d8d6d   KAMEZAWA Hiroyuki   [PATCH] memory ho...
202
  		if (info->enabled) { /* just sanity check...*/
dd56a8e36   Yasunori Goto   [PATCH] Catch not...
203
204
205
  			num_enabled++;
  			continue;
  		}
5d2619fca   Zhao Yakui   ACPI: Ingore the ...
206
207
208
209
210
211
  		/*
  		 * If the memory block size is zero, please ignore it.
  		 * Don't try to do the following memory hotplug flowchart.
  		 */
  		if (!info->length)
  			continue;
8c2676a58   Keith Mannthey   [PATCH] hot-add-m...
212
213
  		if (node < 0)
  			node = memory_add_physaddr_to_nid(info->start_addr);
bc02af93d   Yasunori Goto   [PATCH] pgdat all...
214
  		result = add_memory(node, info->start_addr, info->length);
654794725   Wen Congyang   ACPI / memhotplug...
215
216
217
218
219
220
  
  		/*
  		 * If the memory block has been used by the kernel, add_memory()
  		 * returns -EEXIST. If add_memory() returns the other error, it
  		 * means that this memory block is not used by the kernel.
  		 */
fd4655c25   Yasuaki Ishimatsu   ACPI / memhotplug...
221
  		if (result && result != -EEXIST)
9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
222
  			continue;
654794725   Wen Congyang   ACPI / memhotplug...
223

24dee1fc9   Rafael J. Wysocki   ACPI / bind: Pass...
224
  		result = acpi_bind_memory_blocks(info, mem_device->device);
e2ff39400   Rafael J. Wysocki   ACPI / memhotplug...
225
  		if (result) {
24dee1fc9   Rafael J. Wysocki   ACPI / bind: Pass...
226
  			acpi_unbind_memory_blocks(info);
e2ff39400   Rafael J. Wysocki   ACPI / memhotplug...
227
228
  			return -ENODEV;
  		}
bb49d82dd   Yasuaki Ishimatsu   ACPI / memhotplug...
229
  		info->enabled = 1;
654794725   Wen Congyang   ACPI / memhotplug...
230
231
232
233
  		/*
  		 * Add num_enable even if add_memory() returns -EEXIST, so the
  		 * device is bound to this driver.
  		 */
9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
234
235
236
  		num_enabled++;
  	}
  	if (!num_enabled) {
ab6c57099   Toshi Kani   ACPI: Update Memo...
237
238
  		dev_err(&mem_device->device->dev, "add_memory failed
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
  		mem_device->state = MEMORY_INVALID_STATE;
9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
240
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
  	}
5d2619fca   Zhao Yakui   ACPI: Ingore the ...
242
243
244
245
246
247
248
249
250
  	/*
  	 * Sometimes the memory device will contain several memory blocks.
  	 * When one memory block is hot-added to the system memory, it will
  	 * be regarded as a success.
  	 * Otherwise if the last memory block can't be hot-added to the system
  	 * memory, it will be failure and the memory device can't be bound with
  	 * driver.
  	 */
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
  }
242831eb1   Rafael J. Wysocki   Memory hotplug / ...
252
  static void acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
  {
e2ff39400   Rafael J. Wysocki   ACPI / memhotplug...
254
  	acpi_handle handle = mem_device->device->handle;
9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
255
  	struct acpi_memory_info *info, *n;
242831eb1   Rafael J. Wysocki   Memory hotplug / ...
256
  	int nid = acpi_get_node(handle);
60a5a19e7   Tang Chen   memory-hotplug: r...
257

9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
258
  	list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
654794725   Wen Congyang   ACPI / memhotplug...
259
  		if (!info->enabled)
fd4655c25   Yasuaki Ishimatsu   ACPI / memhotplug...
260
  			continue;
654794725   Wen Congyang   ACPI / memhotplug...
261

1bb25df0f   Jianguo Wu   ACPI / mm: use NU...
262
  		if (nid == NUMA_NO_NODE)
60a5a19e7   Tang Chen   memory-hotplug: r...
263
  			nid = memory_add_physaddr_to_nid(info->start_addr);
e2ff39400   Rafael J. Wysocki   ACPI / memhotplug...
264

24dee1fc9   Rafael J. Wysocki   ACPI / bind: Pass...
265
  		acpi_unbind_memory_blocks(info);
242831eb1   Rafael J. Wysocki   Memory hotplug / ...
266
  		remove_memory(nid, info->start_addr, info->length);
19387b27e   Yasuaki Ishimatsu   ACPI / memory-hot...
267
  		list_del(&info->list);
9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
268
  		kfree(info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  	}
19387b27e   Yasuaki Ishimatsu   ACPI / memory-hot...
270
  }
386e52b95   Wen Congyang   ACPI / memhotplug...
271
272
273
274
275
276
  static void acpi_memory_device_free(struct acpi_memory_device *mem_device)
  {
  	if (!mem_device)
  		return;
  
  	acpi_memory_free_device_resources(mem_device);
0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
277
  	mem_device->device->driver_data = NULL;
386e52b95   Wen Congyang   ACPI / memhotplug...
278
279
  	kfree(mem_device);
  }
0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
280
281
  static int acpi_memory_device_add(struct acpi_device *device,
  				  const struct acpi_device_id *not_used)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
  {
0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
283
  	struct acpi_memory_device *mem_device;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
  	int result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
  
  	if (!device)
d550d98d3   Patrick Mochel   ACPI: delete trac...
287
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288

36bcbec7c   Burman Yan   ACPI: replace kma...
289
  	mem_device = kzalloc(sizeof(struct acpi_memory_device), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
  	if (!mem_device)
d550d98d3   Patrick Mochel   ACPI: delete trac...
291
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292

9ac023989   KAMEZAWA Hiroyuki   [PATCH] acpi memo...
293
  	INIT_LIST_HEAD(&mem_device->res_list);
3b74863df   Patrick Mochel   ACPI: acpi_memhot...
294
  	mem_device->device = device;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
296
  	sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME);
  	sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS);
db89b4f0d   Pavel Machek   ACPI: catch calls...
297
  	device->driver_data = mem_device;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
299
300
301
  
  	/* Get the range from the _CRS */
  	result = acpi_memory_get_device_resources(mem_device);
  	if (result) {
d19f503e2   Toshi Kani   ACPI / memhotplug...
302
  		device->driver_data = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
  		kfree(mem_device);
d550d98d3   Patrick Mochel   ACPI: delete trac...
304
  		return result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
306
307
308
  	}
  
  	/* Set the device state */
  	mem_device->state = MEMORY_POWER_ON_STATE;
0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
309
310
311
312
313
  	result = acpi_memory_check_device(mem_device);
  	if (result) {
  		acpi_memory_device_free(mem_device);
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314

0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
315
316
317
318
319
  	result = acpi_memory_enable_device(mem_device);
  	if (result) {
  		dev_err(&device->dev, "acpi_memory_enable_device() error
  ");
  		acpi_memory_device_free(mem_device);
e2ff39400   Rafael J. Wysocki   ACPI / memhotplug...
320
  		return result;
1f425994f   Yasunori Goto   [PATCH] Catch not...
321
  	}
0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
322
323
324
325
  
  	dev_dbg(&device->dev, "Memory device configured by ACPI
  ");
  	return 1;
1f425994f   Yasunori Goto   [PATCH] Catch not...
326
  }
0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
327
  static void acpi_memory_device_remove(struct acpi_device *device)
80f20fef6   Bjorn Helgaas   ACPI: memory hotp...
328
  {
0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
329
  	struct acpi_memory_device *mem_device;
80f20fef6   Bjorn Helgaas   ACPI: memory hotp...
330
331
  
  	if (!device || !acpi_driver_data(device))
0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
332
  		return;
80f20fef6   Bjorn Helgaas   ACPI: memory hotp...
333
334
  
  	mem_device = acpi_driver_data(device);
0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
335
  	acpi_memory_remove_memory(mem_device);
386e52b95   Wen Congyang   ACPI / memhotplug...
336
  	acpi_memory_device_free(mem_device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
  }
00159a201   Prarit Bhargava   ACPI / memhotplug...
338
  static bool __initdata acpi_no_memhotplug;
0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
339
  void __init acpi_memory_hotplug_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
  {
cccd42085   Rafael J. Wysocki   ACPI / scan: alwa...
341
342
343
  	if (acpi_no_memhotplug) {
  		memory_device_handler.attach = NULL;
  		acpi_scan_add_handler(&memory_device_handler);
00159a201   Prarit Bhargava   ACPI / memhotplug...
344
  		return;
cccd42085   Rafael J. Wysocki   ACPI / scan: alwa...
345
  	}
0a3476441   Rafael J. Wysocki   ACPI / scan: Make...
346
  	acpi_scan_add_handler_with_hotplug(&memory_device_handler, "memory");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
  }
00159a201   Prarit Bhargava   ACPI / memhotplug...
348
349
350
351
352
353
354
  
  static int __init disable_acpi_memory_hotplug(char *str)
  {
  	acpi_no_memhotplug = true;
  	return 1;
  }
  __setup("acpi_no_memhotplug", disable_acpi_memory_hotplug);
cccd42085   Rafael J. Wysocki   ACPI / scan: alwa...
355
356
357
358
359
360
361
362
363
364
365
366
367
  
  #else
  
  static struct acpi_scan_handler memory_device_handler = {
  	.ids = memory_device_ids,
  };
  
  void __init acpi_memory_hotplug_init(void)
  {
  	acpi_scan_add_handler(&memory_device_handler);
  }
  
  #endif /* CONFIG_ACPI_HOTPLUG_MEMORY */