aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 18:05:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 18:05:40 -0400
commita5e6b135bdff649e4330f98e2e80dbb1984f7e77 (patch)
tree475bfb1163c59d1370fd77415255afba768f9520 /drivers/base
parent971f115a50afbe409825c9f3399d5a3b9aca4381 (diff)
parent9d90c8d9cde929cbc575098e825d7c29d9f45054 (diff)
Merge branch 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
* 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (50 commits) printk: do not mangle valid userspace syslog prefixes efivars: Add Documentation efivars: Expose efivars functionality to external drivers. efivars: Parameterize operations. efivars: Split out variable registration efivars: parameterize efivars efivars: Make efivars bin_attributes dynamic efivars: move efivars globals into struct efivars drivers:misc: ti-st: fix debugging code kref: Fix typo in kref documentation UIO: add PRUSS UIO driver support Fix spelling mistakes in Documentation/zh_CN/SubmittingPatches firmware: Fix unaligned memory accesses in dmi-sysfs firmware: Add documentation for /sys/firmware/dmi firmware: Expose DMI type 15 System Event Log firmware: Break out system_event_log in dmi-sysfs firmware: Basic dmi-sysfs support firmware: Add DMI entry types to the headers Driver core: convert platform_{get,set}_drvdata to static inline functions Translate linux-2.6/Documentation/magic-number.txt into Chinese ...
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/core.c34
-rw-r--r--drivers/base/firmware_class.c7
-rw-r--r--drivers/base/memory.c197
-rw-r--r--drivers/base/node.c12
-rw-r--r--drivers/base/sys.c65
5 files changed, 232 insertions, 83 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 080e9ca11017..81b78ede37c4 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1320,7 +1320,10 @@ struct root_device
1320 struct module *owner; 1320 struct module *owner;
1321}; 1321};
1322 1322
1323#define to_root_device(dev) container_of(dev, struct root_device, dev) 1323inline struct root_device *to_root_device(struct device *d)
1324{
1325 return container_of(d, struct root_device, dev);
1326}
1324 1327
1325static void root_device_release(struct device *dev) 1328static void root_device_release(struct device *dev)
1326{ 1329{
@@ -1551,7 +1554,34 @@ EXPORT_SYMBOL_GPL(device_destroy);
1551 * on the same device to ensure that new_name is valid and 1554 * on the same device to ensure that new_name is valid and
1552 * won't conflict with other devices. 1555 * won't conflict with other devices.
1553 * 1556 *
1554 * "Never use this function, bad things will happen" - gregkh 1557 * Note: Don't call this function. Currently, the networking layer calls this
1558 * function, but that will change. The following text from Kay Sievers offers
1559 * some insight:
1560 *
1561 * Renaming devices is racy at many levels, symlinks and other stuff are not
1562 * replaced atomically, and you get a "move" uevent, but it's not easy to
1563 * connect the event to the old and new device. Device nodes are not renamed at
1564 * all, there isn't even support for that in the kernel now.
1565 *
1566 * In the meantime, during renaming, your target name might be taken by another
1567 * driver, creating conflicts. Or the old name is taken directly after you
1568 * renamed it -- then you get events for the same DEVPATH, before you even see
1569 * the "move" event. It's just a mess, and nothing new should ever rely on
1570 * kernel device renaming. Besides that, it's not even implemented now for
1571 * other things than (driver-core wise very simple) network devices.
1572 *
1573 * We are currently about to change network renaming in udev to completely
1574 * disallow renaming of devices in the same namespace as the kernel uses,
1575 * because we can't solve the problems properly, that arise with swapping names
1576 * of multiple interfaces without races. Means, renaming of eth[0-9]* will only
1577 * be allowed to some other name than eth[0-9]*, for the aforementioned
1578 * reasons.
1579 *
1580 * Make up a "real" name in the driver before you register anything, or add
1581 * some other attributes for userspace to find the device, or use udev to add
1582 * symlinks -- but never rename kernel devices later, it's a complete mess. We
1583 * don't even want to get into that and try to implement the missing pieces in
1584 * the core. We really have other pieces to fix in the driver core mess. :)
1555 */ 1585 */
1556int device_rename(struct device *dev, const char *new_name) 1586int device_rename(struct device *dev, const char *new_name)
1557{ 1587{
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 40af43ebd92d..8c798ef7f13f 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -593,8 +593,7 @@ int
593request_firmware(const struct firmware **firmware_p, const char *name, 593request_firmware(const struct firmware **firmware_p, const char *name,
594 struct device *device) 594 struct device *device)
595{ 595{
596 int uevent = 1; 596 return _request_firmware(firmware_p, name, device, true, false);
597 return _request_firmware(firmware_p, name, device, uevent, false);
598} 597}
599 598
600/** 599/**
@@ -618,7 +617,7 @@ struct firmware_work {
618 struct device *device; 617 struct device *device;
619 void *context; 618 void *context;
620 void (*cont)(const struct firmware *fw, void *context); 619 void (*cont)(const struct firmware *fw, void *context);
621 int uevent; 620 bool uevent;
622}; 621};
623 622
624static int request_firmware_work_func(void *arg) 623static int request_firmware_work_func(void *arg)
@@ -661,7 +660,7 @@ static int request_firmware_work_func(void *arg)
661 **/ 660 **/
662int 661int
663request_firmware_nowait( 662request_firmware_nowait(
664 struct module *module, int uevent, 663 struct module *module, bool uevent,
665 const char *name, struct device *device, gfp_t gfp, void *context, 664 const char *name, struct device *device, gfp_t gfp, void *context,
666 void (*cont)(const struct firmware *fw, void *context)) 665 void (*cont)(const struct firmware *fw, void *context))
667{ 666{
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index cafeaaf0428f..3da6a43b7756 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -30,6 +30,14 @@
30static DEFINE_MUTEX(mem_sysfs_mutex); 30static DEFINE_MUTEX(mem_sysfs_mutex);
31 31
32#define MEMORY_CLASS_NAME "memory" 32#define MEMORY_CLASS_NAME "memory"
33#define MIN_MEMORY_BLOCK_SIZE (1 << SECTION_SIZE_BITS)
34
35static int sections_per_block;
36
37static inline int base_memory_block_id(int section_nr)
38{
39 return section_nr / sections_per_block;
40}
33 41
34static struct sysdev_class memory_sysdev_class = { 42static struct sysdev_class memory_sysdev_class = {
35 .name = MEMORY_CLASS_NAME, 43 .name = MEMORY_CLASS_NAME,
@@ -84,39 +92,72 @@ EXPORT_SYMBOL(unregister_memory_isolate_notifier);
84 * register_memory - Setup a sysfs device for a memory block 92 * register_memory - Setup a sysfs device for a memory block
85 */ 93 */
86static 94static
87int register_memory(struct memory_block *memory, struct mem_section *section) 95int register_memory(struct memory_block *memory)
88{ 96{
89 int error; 97 int error;
90 98
91 memory->sysdev.cls = &memory_sysdev_class; 99 memory->sysdev.cls = &memory_sysdev_class;
92 memory->sysdev.id = __section_nr(section); 100 memory->sysdev.id = memory->start_section_nr / sections_per_block;
93 101
94 error = sysdev_register(&memory->sysdev); 102 error = sysdev_register(&memory->sysdev);
95 return error; 103 return error;
96} 104}
97 105
98static void 106static void
99unregister_memory(struct memory_block *memory, struct mem_section *section) 107unregister_memory(struct memory_block *memory)
100{ 108{
101 BUG_ON(memory->sysdev.cls != &memory_sysdev_class); 109 BUG_ON(memory->sysdev.cls != &memory_sysdev_class);
102 BUG_ON(memory->sysdev.id != __section_nr(section));
103 110
104 /* drop the ref. we got in remove_memory_block() */ 111 /* drop the ref. we got in remove_memory_block() */
105 kobject_put(&memory->sysdev.kobj); 112 kobject_put(&memory->sysdev.kobj);
106 sysdev_unregister(&memory->sysdev); 113 sysdev_unregister(&memory->sysdev);
107} 114}
108 115
116unsigned long __weak memory_block_size_bytes(void)
117{
118 return MIN_MEMORY_BLOCK_SIZE;
119}
120
121static unsigned long get_memory_block_size(void)
122{
123 unsigned long block_sz;
124
125 block_sz = memory_block_size_bytes();
126
127 /* Validate blk_sz is a power of 2 and not less than section size */
128 if ((block_sz & (block_sz - 1)) || (block_sz < MIN_MEMORY_BLOCK_SIZE)) {
129 WARN_ON(1);
130 block_sz = MIN_MEMORY_BLOCK_SIZE;
131 }
132
133 return block_sz;
134}
135
109/* 136/*
110 * use this as the physical section index that this memsection 137 * use this as the physical section index that this memsection
111 * uses. 138 * uses.
112 */ 139 */
113 140
114static ssize_t show_mem_phys_index(struct sys_device *dev, 141static ssize_t show_mem_start_phys_index(struct sys_device *dev,
115 struct sysdev_attribute *attr, char *buf) 142 struct sysdev_attribute *attr, char *buf)
116{ 143{
117 struct memory_block *mem = 144 struct memory_block *mem =
118 container_of(dev, struct memory_block, sysdev); 145 container_of(dev, struct memory_block, sysdev);
119 return sprintf(buf, "%08lx\n", mem->phys_index); 146 unsigned long phys_index;
147
148 phys_index = mem->start_section_nr / sections_per_block;
149 return sprintf(buf, "%08lx\n", phys_index);
150}
151
152static ssize_t show_mem_end_phys_index(struct sys_device *dev,
153 struct sysdev_attribute *attr, char *buf)
154{
155 struct memory_block *mem =
156 container_of(dev, struct memory_block, sysdev);
157 unsigned long phys_index;
158
159 phys_index = mem->end_section_nr / sections_per_block;
160 return sprintf(buf, "%08lx\n", phys_index);
120} 161}
121 162
122/* 163/*
@@ -125,13 +166,16 @@ static ssize_t show_mem_phys_index(struct sys_device *dev,
125static ssize_t show_mem_removable(struct sys_device *dev, 166static ssize_t show_mem_removable(struct sys_device *dev,
126 struct sysdev_attribute *attr, char *buf) 167 struct sysdev_attribute *attr, char *buf)
127{ 168{
128 unsigned long start_pfn; 169 unsigned long i, pfn;
129 int ret; 170 int ret = 1;
130 struct memory_block *mem = 171 struct memory_block *mem =
131 container_of(dev, struct memory_block, sysdev); 172 container_of(dev, struct memory_block, sysdev);
132 173
133 start_pfn = section_nr_to_pfn(mem->phys_index); 174 for (i = 0; i < sections_per_block; i++) {
134 ret = is_mem_section_removable(start_pfn, PAGES_PER_SECTION); 175 pfn = section_nr_to_pfn(mem->start_section_nr + i);
176 ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
177 }
178
135 return sprintf(buf, "%d\n", ret); 179 return sprintf(buf, "%d\n", ret);
136} 180}
137 181
@@ -184,17 +228,14 @@ int memory_isolate_notify(unsigned long val, void *v)
184 * OK to have direct references to sparsemem variables in here. 228 * OK to have direct references to sparsemem variables in here.
185 */ 229 */
186static int 230static int
187memory_block_action(struct memory_block *mem, unsigned long action) 231memory_section_action(unsigned long phys_index, unsigned long action)
188{ 232{
189 int i; 233 int i;
190 unsigned long psection;
191 unsigned long start_pfn, start_paddr; 234 unsigned long start_pfn, start_paddr;
192 struct page *first_page; 235 struct page *first_page;
193 int ret; 236 int ret;
194 int old_state = mem->state;
195 237
196 psection = mem->phys_index; 238 first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT);
197 first_page = pfn_to_page(psection << PFN_SECTION_SHIFT);
198 239
199 /* 240 /*
200 * The probe routines leave the pages reserved, just 241 * The probe routines leave the pages reserved, just
@@ -207,8 +248,8 @@ memory_block_action(struct memory_block *mem, unsigned long action)
207 continue; 248 continue;
208 249
209 printk(KERN_WARNING "section number %ld page number %d " 250 printk(KERN_WARNING "section number %ld page number %d "
210 "not reserved, was it already online? \n", 251 "not reserved, was it already online?\n",
211 psection, i); 252 phys_index, i);
212 return -EBUSY; 253 return -EBUSY;
213 } 254 }
214 } 255 }
@@ -219,18 +260,13 @@ memory_block_action(struct memory_block *mem, unsigned long action)
219 ret = online_pages(start_pfn, PAGES_PER_SECTION); 260 ret = online_pages(start_pfn, PAGES_PER_SECTION);
220 break; 261 break;
221 case MEM_OFFLINE: 262 case MEM_OFFLINE:
222 mem->state = MEM_GOING_OFFLINE;
223 start_paddr = page_to_pfn(first_page) << PAGE_SHIFT; 263 start_paddr = page_to_pfn(first_page) << PAGE_SHIFT;
224 ret = remove_memory(start_paddr, 264 ret = remove_memory(start_paddr,
225 PAGES_PER_SECTION << PAGE_SHIFT); 265 PAGES_PER_SECTION << PAGE_SHIFT);
226 if (ret) {
227 mem->state = old_state;
228 break;
229 }
230 break; 266 break;
231 default: 267 default:
232 WARN(1, KERN_WARNING "%s(%p, %ld) unknown action: %ld\n", 268 WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: "
233 __func__, mem, action, action); 269 "%ld\n", __func__, phys_index, action, action);
234 ret = -EINVAL; 270 ret = -EINVAL;
235 } 271 }
236 272
@@ -240,7 +276,8 @@ memory_block_action(struct memory_block *mem, unsigned long action)
240static int memory_block_change_state(struct memory_block *mem, 276static int memory_block_change_state(struct memory_block *mem,
241 unsigned long to_state, unsigned long from_state_req) 277 unsigned long to_state, unsigned long from_state_req)
242{ 278{
243 int ret = 0; 279 int i, ret = 0;
280
244 mutex_lock(&mem->state_mutex); 281 mutex_lock(&mem->state_mutex);
245 282
246 if (mem->state != from_state_req) { 283 if (mem->state != from_state_req) {
@@ -248,8 +285,23 @@ static int memory_block_change_state(struct memory_block *mem,
248 goto out; 285 goto out;
249 } 286 }
250 287
251 ret = memory_block_action(mem, to_state); 288 if (to_state == MEM_OFFLINE)
252 if (!ret) 289 mem->state = MEM_GOING_OFFLINE;
290
291 for (i = 0; i < sections_per_block; i++) {
292 ret = memory_section_action(mem->start_section_nr + i,
293 to_state);
294 if (ret)
295 break;
296 }
297
298 if (ret) {
299 for (i = 0; i < sections_per_block; i++)
300 memory_section_action(mem->start_section_nr + i,
301 from_state_req);
302
303 mem->state = from_state_req;
304 } else
253 mem->state = to_state; 305 mem->state = to_state;
254 306
255out: 307out:
@@ -262,20 +314,15 @@ store_mem_state(struct sys_device *dev,
262 struct sysdev_attribute *attr, const char *buf, size_t count) 314 struct sysdev_attribute *attr, const char *buf, size_t count)
263{ 315{
264 struct memory_block *mem; 316 struct memory_block *mem;
265 unsigned int phys_section_nr;
266 int ret = -EINVAL; 317 int ret = -EINVAL;
267 318
268 mem = container_of(dev, struct memory_block, sysdev); 319 mem = container_of(dev, struct memory_block, sysdev);
269 phys_section_nr = mem->phys_index;
270
271 if (!present_section_nr(phys_section_nr))
272 goto out;
273 320
274 if (!strncmp(buf, "online", min((int)count, 6))) 321 if (!strncmp(buf, "online", min((int)count, 6)))
275 ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE); 322 ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
276 else if(!strncmp(buf, "offline", min((int)count, 7))) 323 else if(!strncmp(buf, "offline", min((int)count, 7)))
277 ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE); 324 ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
278out: 325
279 if (ret) 326 if (ret)
280 return ret; 327 return ret;
281 return count; 328 return count;
@@ -298,7 +345,8 @@ static ssize_t show_phys_device(struct sys_device *dev,
298 return sprintf(buf, "%d\n", mem->phys_device); 345 return sprintf(buf, "%d\n", mem->phys_device);
299} 346}
300 347
301static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL); 348static SYSDEV_ATTR(phys_index, 0444, show_mem_start_phys_index, NULL);
349static SYSDEV_ATTR(end_phys_index, 0444, show_mem_end_phys_index, NULL);
302static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state); 350static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state);
303static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL); 351static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL);
304static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); 352static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);
@@ -315,7 +363,7 @@ static ssize_t
315print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr, 363print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr,
316 char *buf) 364 char *buf)
317{ 365{
318 return sprintf(buf, "%lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE); 366 return sprintf(buf, "%lx\n", get_memory_block_size());
319} 367}
320 368
321static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); 369static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
@@ -339,12 +387,19 @@ memory_probe_store(struct class *class, struct class_attribute *attr,
339{ 387{
340 u64 phys_addr; 388 u64 phys_addr;
341 int nid; 389 int nid;
342 int ret; 390 int i, ret;
343 391
344 phys_addr = simple_strtoull(buf, NULL, 0); 392 phys_addr = simple_strtoull(buf, NULL, 0);
345 393
346 nid = memory_add_physaddr_to_nid(phys_addr); 394 for (i = 0; i < sections_per_block; i++) {
347 ret = add_memory(nid, phys_addr, PAGES_PER_SECTION << PAGE_SHIFT); 395 nid = memory_add_physaddr_to_nid(phys_addr);
396 ret = add_memory(nid, phys_addr,
397 PAGES_PER_SECTION << PAGE_SHIFT);
398 if (ret)
399 break;
400
401 phys_addr += MIN_MEMORY_BLOCK_SIZE;
402 }
348 403
349 if (ret) 404 if (ret)
350 count = ret; 405 count = ret;
@@ -444,6 +499,7 @@ struct memory_block *find_memory_block_hinted(struct mem_section *section,
444 struct sys_device *sysdev; 499 struct sys_device *sysdev;
445 struct memory_block *mem; 500 struct memory_block *mem;
446 char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1]; 501 char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
502 int block_id = base_memory_block_id(__section_nr(section));
447 503
448 kobj = hint ? &hint->sysdev.kobj : NULL; 504 kobj = hint ? &hint->sysdev.kobj : NULL;
449 505
@@ -451,7 +507,7 @@ struct memory_block *find_memory_block_hinted(struct mem_section *section,
451 * This only works because we know that section == sysdev->id 507 * This only works because we know that section == sysdev->id
452 * slightly redundant with sysdev_register() 508 * slightly redundant with sysdev_register()
453 */ 509 */
454 sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section)); 510 sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, block_id);
455 511
456 kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj); 512 kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj);
457 if (!kobj) 513 if (!kobj)
@@ -476,36 +532,62 @@ struct memory_block *find_memory_block(struct mem_section *section)
476 return find_memory_block_hinted(section, NULL); 532 return find_memory_block_hinted(section, NULL);
477} 533}
478 534
479static int add_memory_block(int nid, struct mem_section *section, 535static int init_memory_block(struct memory_block **memory,
480 unsigned long state, enum mem_add_context context) 536 struct mem_section *section, unsigned long state)
481{ 537{
482 struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL); 538 struct memory_block *mem;
483 unsigned long start_pfn; 539 unsigned long start_pfn;
540 int scn_nr;
484 int ret = 0; 541 int ret = 0;
485 542
543 mem = kzalloc(sizeof(*mem), GFP_KERNEL);
486 if (!mem) 544 if (!mem)
487 return -ENOMEM; 545 return -ENOMEM;
488 546
489 mutex_lock(&mem_sysfs_mutex); 547 scn_nr = __section_nr(section);
490 548 mem->start_section_nr =
491 mem->phys_index = __section_nr(section); 549 base_memory_block_id(scn_nr) * sections_per_block;
550 mem->end_section_nr = mem->start_section_nr + sections_per_block - 1;
492 mem->state = state; 551 mem->state = state;
493 mem->section_count++; 552 mem->section_count++;
494 mutex_init(&mem->state_mutex); 553 mutex_init(&mem->state_mutex);
495 start_pfn = section_nr_to_pfn(mem->phys_index); 554 start_pfn = section_nr_to_pfn(mem->start_section_nr);
496 mem->phys_device = arch_get_memory_phys_device(start_pfn); 555 mem->phys_device = arch_get_memory_phys_device(start_pfn);
497 556
498 ret = register_memory(mem, section); 557 ret = register_memory(mem);
499 if (!ret) 558 if (!ret)
500 ret = mem_create_simple_file(mem, phys_index); 559 ret = mem_create_simple_file(mem, phys_index);
501 if (!ret) 560 if (!ret)
561 ret = mem_create_simple_file(mem, end_phys_index);
562 if (!ret)
502 ret = mem_create_simple_file(mem, state); 563 ret = mem_create_simple_file(mem, state);
503 if (!ret) 564 if (!ret)
504 ret = mem_create_simple_file(mem, phys_device); 565 ret = mem_create_simple_file(mem, phys_device);
505 if (!ret) 566 if (!ret)
506 ret = mem_create_simple_file(mem, removable); 567 ret = mem_create_simple_file(mem, removable);
568
569 *memory = mem;
570 return ret;
571}
572
573static int add_memory_section(int nid, struct mem_section *section,
574 unsigned long state, enum mem_add_context context)
575{
576 struct memory_block *mem;
577 int ret = 0;
578
579 mutex_lock(&mem_sysfs_mutex);
580
581 mem = find_memory_block(section);
582 if (mem) {
583 mem->section_count++;
584 kobject_put(&mem->sysdev.kobj);
585 } else
586 ret = init_memory_block(&mem, section, state);
587
507 if (!ret) { 588 if (!ret) {
508 if (context == HOTPLUG) 589 if (context == HOTPLUG &&
590 mem->section_count == sections_per_block)
509 ret = register_mem_sect_under_node(mem, nid); 591 ret = register_mem_sect_under_node(mem, nid);
510 } 592 }
511 593
@@ -520,16 +602,19 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
520 602
521 mutex_lock(&mem_sysfs_mutex); 603 mutex_lock(&mem_sysfs_mutex);
522 mem = find_memory_block(section); 604 mem = find_memory_block(section);
605 unregister_mem_sect_under_nodes(mem, __section_nr(section));
523 606
524 mem->section_count--; 607 mem->section_count--;
525 if (mem->section_count == 0) { 608 if (mem->section_count == 0) {
526 unregister_mem_sect_under_nodes(mem);
527 mem_remove_simple_file(mem, phys_index); 609 mem_remove_simple_file(mem, phys_index);
610 mem_remove_simple_file(mem, end_phys_index);
528 mem_remove_simple_file(mem, state); 611 mem_remove_simple_file(mem, state);
529 mem_remove_simple_file(mem, phys_device); 612 mem_remove_simple_file(mem, phys_device);
530 mem_remove_simple_file(mem, removable); 613 mem_remove_simple_file(mem, removable);
531 unregister_memory(mem, section); 614 unregister_memory(mem);
532 } 615 kfree(mem);
616 } else
617 kobject_put(&mem->sysdev.kobj);
533 618
534 mutex_unlock(&mem_sysfs_mutex); 619 mutex_unlock(&mem_sysfs_mutex);
535 return 0; 620 return 0;
@@ -541,7 +626,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
541 */ 626 */
542int register_new_memory(int nid, struct mem_section *section) 627int register_new_memory(int nid, struct mem_section *section)
543{ 628{
544 return add_memory_block(nid, section, MEM_OFFLINE, HOTPLUG); 629 return add_memory_section(nid, section, MEM_OFFLINE, HOTPLUG);
545} 630}
546 631
547int unregister_memory_section(struct mem_section *section) 632int unregister_memory_section(struct mem_section *section)
@@ -560,12 +645,16 @@ int __init memory_dev_init(void)
560 unsigned int i; 645 unsigned int i;
561 int ret; 646 int ret;
562 int err; 647 int err;
648 unsigned long block_sz;
563 649
564 memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops; 650 memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops;
565 ret = sysdev_class_register(&memory_sysdev_class); 651 ret = sysdev_class_register(&memory_sysdev_class);
566 if (ret) 652 if (ret)
567 goto out; 653 goto out;
568 654
655 block_sz = get_memory_block_size();
656 sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
657
569 /* 658 /*
570 * Create entries for memory sections that were found 659 * Create entries for memory sections that were found
571 * during boot and have been initialized 660 * during boot and have been initialized
@@ -573,8 +662,8 @@ int __init memory_dev_init(void)
573 for (i = 0; i < NR_MEM_SECTIONS; i++) { 662 for (i = 0; i < NR_MEM_SECTIONS; i++) {
574 if (!present_section_nr(i)) 663 if (!present_section_nr(i))
575 continue; 664 continue;
576 err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 665 err = add_memory_section(0, __nr_to_section(i), MEM_ONLINE,
577 BOOT); 666 BOOT);
578 if (!ret) 667 if (!ret)
579 ret = err; 668 ret = err;
580 } 669 }
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 36b43052001d..b3b72d64e805 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -375,8 +375,10 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid)
375 return -EFAULT; 375 return -EFAULT;
376 if (!node_online(nid)) 376 if (!node_online(nid))
377 return 0; 377 return 0;
378 sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index); 378
379 sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1; 379 sect_start_pfn = section_nr_to_pfn(mem_blk->start_section_nr);
380 sect_end_pfn = section_nr_to_pfn(mem_blk->end_section_nr);
381 sect_end_pfn += PAGES_PER_SECTION - 1;
380 for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { 382 for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
381 int page_nid; 383 int page_nid;
382 384
@@ -400,7 +402,8 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid)
400} 402}
401 403
402/* unregister memory section under all nodes that it spans */ 404/* unregister memory section under all nodes that it spans */
403int unregister_mem_sect_under_nodes(struct memory_block *mem_blk) 405int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
406 unsigned long phys_index)
404{ 407{
405 NODEMASK_ALLOC(nodemask_t, unlinked_nodes, GFP_KERNEL); 408 NODEMASK_ALLOC(nodemask_t, unlinked_nodes, GFP_KERNEL);
406 unsigned long pfn, sect_start_pfn, sect_end_pfn; 409 unsigned long pfn, sect_start_pfn, sect_end_pfn;
@@ -412,7 +415,8 @@ int unregister_mem_sect_under_nodes(struct memory_block *mem_blk)
412 if (!unlinked_nodes) 415 if (!unlinked_nodes)
413 return -ENOMEM; 416 return -ENOMEM;
414 nodes_clear(*unlinked_nodes); 417 nodes_clear(*unlinked_nodes);
415 sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index); 418
419 sect_start_pfn = section_nr_to_pfn(phys_index);
416 sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1; 420 sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1;
417 for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { 421 for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
418 int nid; 422 int nid;
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 1667aaf4fde6..f6fb54741602 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -166,6 +166,36 @@ EXPORT_SYMBOL_GPL(sysdev_class_unregister);
166 166
167static DEFINE_MUTEX(sysdev_drivers_lock); 167static DEFINE_MUTEX(sysdev_drivers_lock);
168 168
169/*
170 * @dev != NULL means that we're unwinding because some drv->add()
171 * failed for some reason. You need to grab sysdev_drivers_lock before
172 * calling this.
173 */
174static void __sysdev_driver_remove(struct sysdev_class *cls,
175 struct sysdev_driver *drv,
176 struct sys_device *from_dev)
177{
178 struct sys_device *dev = from_dev;
179
180 list_del_init(&drv->entry);
181 if (!cls)
182 return;
183
184 if (!drv->remove)
185 goto kset_put;
186
187 if (dev)
188 list_for_each_entry_continue_reverse(dev, &cls->kset.list,
189 kobj.entry)
190 drv->remove(dev);
191 else
192 list_for_each_entry(dev, &cls->kset.list, kobj.entry)
193 drv->remove(dev);
194
195kset_put:
196 kset_put(&cls->kset);
197}
198
169/** 199/**
170 * sysdev_driver_register - Register auxillary driver 200 * sysdev_driver_register - Register auxillary driver
171 * @cls: Device class driver belongs to. 201 * @cls: Device class driver belongs to.
@@ -175,14 +205,14 @@ static DEFINE_MUTEX(sysdev_drivers_lock);
175 * called on each operation on devices of that class. The refcount 205 * called on each operation on devices of that class. The refcount
176 * of @cls is incremented. 206 * of @cls is incremented.
177 */ 207 */
178
179int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv) 208int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
180{ 209{
210 struct sys_device *dev = NULL;
181 int err = 0; 211 int err = 0;
182 212
183 if (!cls) { 213 if (!cls) {
184 WARN(1, KERN_WARNING "sysdev: invalid class passed to " 214 WARN(1, KERN_WARNING "sysdev: invalid class passed to %s!\n",
185 "sysdev_driver_register!\n"); 215 __func__);
186 return -EINVAL; 216 return -EINVAL;
187 } 217 }
188 218
@@ -198,19 +228,27 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
198 228
199 /* If devices of this class already exist, tell the driver */ 229 /* If devices of this class already exist, tell the driver */
200 if (drv->add) { 230 if (drv->add) {
201 struct sys_device *dev; 231 list_for_each_entry(dev, &cls->kset.list, kobj.entry) {
202 list_for_each_entry(dev, &cls->kset.list, kobj.entry) 232 err = drv->add(dev);
203 drv->add(dev); 233 if (err)
234 goto unwind;
235 }
204 } 236 }
205 } else { 237 } else {
206 err = -EINVAL; 238 err = -EINVAL;
207 WARN(1, KERN_ERR "%s: invalid device class\n", __func__); 239 WARN(1, KERN_ERR "%s: invalid device class\n", __func__);
208 } 240 }
241
242 goto unlock;
243
244unwind:
245 __sysdev_driver_remove(cls, drv, dev);
246
247unlock:
209 mutex_unlock(&sysdev_drivers_lock); 248 mutex_unlock(&sysdev_drivers_lock);
210 return err; 249 return err;
211} 250}
212 251
213
214/** 252/**
215 * sysdev_driver_unregister - Remove an auxillary driver. 253 * sysdev_driver_unregister - Remove an auxillary driver.
216 * @cls: Class driver belongs to. 254 * @cls: Class driver belongs to.
@@ -220,23 +258,12 @@ void sysdev_driver_unregister(struct sysdev_class *cls,
220 struct sysdev_driver *drv) 258 struct sysdev_driver *drv)
221{ 259{
222 mutex_lock(&sysdev_drivers_lock); 260 mutex_lock(&sysdev_drivers_lock);
223 list_del_init(&drv->entry); 261 __sysdev_driver_remove(cls, drv, NULL);
224 if (cls) {
225 if (drv->remove) {
226 struct sys_device *dev;
227 list_for_each_entry(dev, &cls->kset.list, kobj.entry)
228 drv->remove(dev);
229 }
230 kset_put(&cls->kset);
231 }
232 mutex_unlock(&sysdev_drivers_lock); 262 mutex_unlock(&sysdev_drivers_lock);
233} 263}
234
235EXPORT_SYMBOL_GPL(sysdev_driver_register); 264EXPORT_SYMBOL_GPL(sysdev_driver_register);
236EXPORT_SYMBOL_GPL(sysdev_driver_unregister); 265EXPORT_SYMBOL_GPL(sysdev_driver_unregister);
237 266
238
239
240/** 267/**
241 * sysdev_register - add a system device to the tree 268 * sysdev_register - add a system device to the tree
242 * @sysdev: device in question 269 * @sysdev: device in question