aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-10-30 21:37:12 -0500
committerPaul Mackerras <paulus@samba.org>2005-10-30 21:37:12 -0500
commit23fd07750a789a66fe88cf173d52a18f1a387da4 (patch)
tree06fdd6df35fdb835abdaa9b754d62f6b84b97250 /drivers/base
parentbd787d438a59266af3c9f6351644c85ef1dd21fe (diff)
parented28f96ac1960f30f818374d65be71d2fdf811b0 (diff)
Merge ../linux-2.6 by hand
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/Makefile1
-rw-r--r--drivers/base/attribute_container.c2
-rw-r--r--drivers/base/base.h12
-rw-r--r--drivers/base/class.c151
-rw-r--r--drivers/base/core.c21
-rw-r--r--drivers/base/cpu.c17
-rw-r--r--drivers/base/driver.c3
-rw-r--r--drivers/base/firmware.c3
-rw-r--r--drivers/base/firmware_class.c69
-rw-r--r--drivers/base/init.c12
-rw-r--r--drivers/base/memory.c452
-rw-r--r--drivers/base/platform.c23
-rw-r--r--drivers/base/power/main.c26
-rw-r--r--drivers/base/power/power.h13
-rw-r--r--drivers/base/power/runtime.c1
-rw-r--r--drivers/base/power/sysfs.c73
-rw-r--r--drivers/base/sys.c1
17 files changed, 739 insertions, 141 deletions
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 66d9c4643fc1..f12898d53078 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -7,6 +7,7 @@ obj-y := core.o sys.o bus.o dd.o \
7obj-y += power/ 7obj-y += power/
8obj-$(CONFIG_FW_LOADER) += firmware_class.o 8obj-$(CONFIG_FW_LOADER) += firmware_class.o
9obj-$(CONFIG_NUMA) += node.o 9obj-$(CONFIG_NUMA) += node.o
10obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o
10 11
11ifeq ($(CONFIG_DEBUG_DRIVER),y) 12ifeq ($(CONFIG_DEBUG_DRIVER),y)
12EXTRA_CFLAGS += -DDEBUG 13EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index 6b2eb6f39b4d..2a7d7ae83e1e 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -19,6 +19,8 @@
19#include <linux/list.h> 19#include <linux/list.h>
20#include <linux/module.h> 20#include <linux/module.h>
21 21
22#include "base.h"
23
22/* This is a private structure used to tie the classdev and the 24/* This is a private structure used to tie the classdev and the
23 * container .. it should never be visible outside this file */ 25 * container .. it should never be visible outside this file */
24struct internal_container { 26struct internal_container {
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 783752b68a9a..e3b548d46cff 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -1,3 +1,15 @@
1
2/* initialisation functions */
3
4extern int devices_init(void);
5extern int buses_init(void);
6extern int classes_init(void);
7extern int firmware_init(void);
8extern int platform_bus_init(void);
9extern int system_bus_init(void);
10extern int cpu_dev_init(void);
11extern int attribute_container_init(void);
12
1extern int bus_add_device(struct device * dev); 13extern int bus_add_device(struct device * dev);
2extern void bus_remove_device(struct device * dev); 14extern void bus_remove_device(struct device * dev);
3 15
diff --git a/drivers/base/class.c b/drivers/base/class.c
index ce23dc8c18c5..db65fd0babe9 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -17,6 +17,7 @@
17#include <linux/string.h> 17#include <linux/string.h>
18#include <linux/kdev_t.h> 18#include <linux/kdev_t.h>
19#include <linux/err.h> 19#include <linux/err.h>
20#include <linux/slab.h>
20#include "base.h" 21#include "base.h"
21 22
22#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) 23#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
@@ -99,7 +100,8 @@ struct class * class_get(struct class * cls)
99 100
100void class_put(struct class * cls) 101void class_put(struct class * cls)
101{ 102{
102 subsys_put(&cls->subsys); 103 if (cls)
104 subsys_put(&cls->subsys);
103} 105}
104 106
105 107
@@ -165,14 +167,25 @@ void class_unregister(struct class * cls)
165 167
166static void class_create_release(struct class *cls) 168static void class_create_release(struct class *cls)
167{ 169{
170 pr_debug("%s called for %s\n", __FUNCTION__, cls->name);
168 kfree(cls); 171 kfree(cls);
169} 172}
170 173
171static void class_device_create_release(struct class_device *class_dev) 174static void class_device_create_release(struct class_device *class_dev)
172{ 175{
176 pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
173 kfree(class_dev); 177 kfree(class_dev);
174} 178}
175 179
180/* needed to allow these devices to have parent class devices */
181static int class_device_create_hotplug(struct class_device *class_dev,
182 char **envp, int num_envp,
183 char *buffer, int buffer_size)
184{
185 pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
186 return 0;
187}
188
176/** 189/**
177 * class_create - create a struct class structure 190 * class_create - create a struct class structure
178 * @owner: pointer to the module that is to "own" this struct class 191 * @owner: pointer to the module that is to "own" this struct class
@@ -301,10 +314,12 @@ static void class_dev_release(struct kobject * kobj)
301 kfree(cd->devt_attr); 314 kfree(cd->devt_attr);
302 cd->devt_attr = NULL; 315 cd->devt_attr = NULL;
303 316
304 if (cls->release) 317 if (cd->release)
318 cd->release(cd);
319 else if (cls->release)
305 cls->release(cd); 320 cls->release(cd);
306 else { 321 else {
307 printk(KERN_ERR "Device class '%s' does not have a release() function, " 322 printk(KERN_ERR "Class Device '%s' does not have a release() function, "
308 "it is broken and must be fixed.\n", 323 "it is broken and must be fixed.\n",
309 cd->class_id); 324 cd->class_id);
310 WARN_ON(1); 325 WARN_ON(1);
@@ -382,14 +397,18 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
382 buffer = &buffer[length]; 397 buffer = &buffer[length];
383 buffer_size -= length; 398 buffer_size -= length;
384 399
385 if (class_dev->class->hotplug) { 400 if (class_dev->hotplug) {
386 /* have the bus specific function add its stuff */ 401 /* have the class device specific function add its stuff */
387 retval = class_dev->class->hotplug (class_dev, envp, num_envp, 402 retval = class_dev->hotplug(class_dev, envp, num_envp,
388 buffer, buffer_size); 403 buffer, buffer_size);
389 if (retval) { 404 if (retval)
390 pr_debug ("%s - hotplug() returned %d\n", 405 pr_debug("class_dev->hotplug() returned %d\n", retval);
391 __FUNCTION__, retval); 406 } else if (class_dev->class->hotplug) {
392 } 407 /* have the class specific function add its stuff */
408 retval = class_dev->class->hotplug(class_dev, envp, num_envp,
409 buffer, buffer_size);
410 if (retval)
411 pr_debug("class->hotplug() returned %d\n", retval);
393 } 412 }
394 413
395 return retval; 414 return retval;
@@ -442,6 +461,13 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
442 return print_dev_t(buf, class_dev->devt); 461 return print_dev_t(buf, class_dev->devt);
443} 462}
444 463
464static ssize_t store_uevent(struct class_device *class_dev,
465 const char *buf, size_t count)
466{
467 kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
468 return count;
469}
470
445void class_device_initialize(struct class_device *class_dev) 471void class_device_initialize(struct class_device *class_dev)
446{ 472{
447 kobj_set_kset_s(class_dev, class_obj_subsys); 473 kobj_set_kset_s(class_dev, class_obj_subsys);
@@ -469,34 +495,45 @@ static char *make_class_name(struct class_device *class_dev)
469 495
470int class_device_add(struct class_device *class_dev) 496int class_device_add(struct class_device *class_dev)
471{ 497{
472 struct class * parent = NULL; 498 struct class *parent_class = NULL;
473 struct class_interface * class_intf; 499 struct class_device *parent_class_dev = NULL;
500 struct class_interface *class_intf;
474 char *class_name = NULL; 501 char *class_name = NULL;
475 int error; 502 int error = -EINVAL;
476 503
477 class_dev = class_device_get(class_dev); 504 class_dev = class_device_get(class_dev);
478 if (!class_dev) 505 if (!class_dev)
479 return -EINVAL; 506 return -EINVAL;
480 507
481 if (!strlen(class_dev->class_id)) { 508 if (!strlen(class_dev->class_id))
482 error = -EINVAL;
483 goto register_done; 509 goto register_done;
484 }
485 510
486 parent = class_get(class_dev->class); 511 parent_class = class_get(class_dev->class);
512 if (!parent_class)
513 goto register_done;
514 parent_class_dev = class_device_get(class_dev->parent);
487 515
488 pr_debug("CLASS: registering class device: ID = '%s'\n", 516 pr_debug("CLASS: registering class device: ID = '%s'\n",
489 class_dev->class_id); 517 class_dev->class_id);
490 518
491 /* first, register with generic layer. */ 519 /* first, register with generic layer. */
492 kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id); 520 kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
493 if (parent) 521 if (parent_class_dev)
494 class_dev->kobj.parent = &parent->subsys.kset.kobj; 522 class_dev->kobj.parent = &parent_class_dev->kobj;
523 else
524 class_dev->kobj.parent = &parent_class->subsys.kset.kobj;
495 525
496 if ((error = kobject_add(&class_dev->kobj))) 526 error = kobject_add(&class_dev->kobj);
527 if (error)
497 goto register_done; 528 goto register_done;
498 529
499 /* add the needed attributes to this device */ 530 /* add the needed attributes to this device */
531 class_dev->uevent_attr.attr.name = "uevent";
532 class_dev->uevent_attr.attr.mode = S_IWUSR;
533 class_dev->uevent_attr.attr.owner = parent_class->owner;
534 class_dev->uevent_attr.store = store_uevent;
535 class_device_create_file(class_dev, &class_dev->uevent_attr);
536
500 if (MAJOR(class_dev->devt)) { 537 if (MAJOR(class_dev->devt)) {
501 struct class_device_attribute *attr; 538 struct class_device_attribute *attr;
502 attr = kzalloc(sizeof(*attr), GFP_KERNEL); 539 attr = kzalloc(sizeof(*attr), GFP_KERNEL);
@@ -505,12 +542,10 @@ int class_device_add(struct class_device *class_dev)
505 kobject_del(&class_dev->kobj); 542 kobject_del(&class_dev->kobj);
506 goto register_done; 543 goto register_done;
507 } 544 }
508
509 attr->attr.name = "dev"; 545 attr->attr.name = "dev";
510 attr->attr.mode = S_IRUGO; 546 attr->attr.mode = S_IRUGO;
511 attr->attr.owner = parent->owner; 547 attr->attr.owner = parent_class->owner;
512 attr->show = show_dev; 548 attr->show = show_dev;
513 attr->store = NULL;
514 class_device_create_file(class_dev, attr); 549 class_device_create_file(class_dev, attr);
515 class_dev->devt_attr = attr; 550 class_dev->devt_attr = attr;
516 } 551 }
@@ -524,20 +559,23 @@ int class_device_add(struct class_device *class_dev)
524 class_name); 559 class_name);
525 } 560 }
526 561
562 kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
563
527 /* notify any interfaces this device is now here */ 564 /* notify any interfaces this device is now here */
528 if (parent) { 565 if (parent_class) {
529 down(&parent->sem); 566 down(&parent_class->sem);
530 list_add_tail(&class_dev->node, &parent->children); 567 list_add_tail(&class_dev->node, &parent_class->children);
531 list_for_each_entry(class_intf, &parent->interfaces, node) 568 list_for_each_entry(class_intf, &parent_class->interfaces, node)
532 if (class_intf->add) 569 if (class_intf->add)
533 class_intf->add(class_dev); 570 class_intf->add(class_dev, class_intf);
534 up(&parent->sem); 571 up(&parent_class->sem);
535 } 572 }
536 kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
537 573
538 register_done: 574 register_done:
539 if (error && parent) 575 if (error) {
540 class_put(parent); 576 class_put(parent_class);
577 class_device_put(parent_class_dev);
578 }
541 class_device_put(class_dev); 579 class_device_put(class_dev);
542 kfree(class_name); 580 kfree(class_name);
543 return error; 581 return error;
@@ -552,21 +590,28 @@ int class_device_register(struct class_device *class_dev)
552/** 590/**
553 * class_device_create - creates a class device and registers it with sysfs 591 * class_device_create - creates a class device and registers it with sysfs
554 * @cs: pointer to the struct class that this device should be registered to. 592 * @cs: pointer to the struct class that this device should be registered to.
593 * @parent: pointer to the parent struct class_device of this new device, if any.
555 * @dev: the dev_t for the char device to be added. 594 * @dev: the dev_t for the char device to be added.
556 * @device: a pointer to a struct device that is assiociated with this class device. 595 * @device: a pointer to a struct device that is assiociated with this class device.
557 * @fmt: string for the class device's name 596 * @fmt: string for the class device's name
558 * 597 *
559 * This function can be used by char device classes. A struct 598 * This function can be used by char device classes. A struct
560 * class_device will be created in sysfs, registered to the specified 599 * class_device will be created in sysfs, registered to the specified
561 * class. A "dev" file will be created, showing the dev_t for the 600 * class.
562 * device. The pointer to the struct class_device will be returned from 601 * A "dev" file will be created, showing the dev_t for the device, if
563 * the call. Any further sysfs files that might be required can be 602 * the dev_t is not 0,0.
564 * created using this pointer. 603 * If a pointer to a parent struct class_device is passed in, the newly
604 * created struct class_device will be a child of that device in sysfs.
605 * The pointer to the struct class_device will be returned from the
606 * call. Any further sysfs files that might be required can be created
607 * using this pointer.
565 * 608 *
566 * Note: the struct class passed to this function must have previously 609 * Note: the struct class passed to this function must have previously
567 * been created with a call to class_create(). 610 * been created with a call to class_create().
568 */ 611 */
569struct class_device *class_device_create(struct class *cls, dev_t devt, 612struct class_device *class_device_create(struct class *cls,
613 struct class_device *parent,
614 dev_t devt,
570 struct device *device, char *fmt, ...) 615 struct device *device, char *fmt, ...)
571{ 616{
572 va_list args; 617 va_list args;
@@ -585,6 +630,9 @@ struct class_device *class_device_create(struct class *cls, dev_t devt,
585 class_dev->devt = devt; 630 class_dev->devt = devt;
586 class_dev->dev = device; 631 class_dev->dev = device;
587 class_dev->class = cls; 632 class_dev->class = cls;
633 class_dev->parent = parent;
634 class_dev->release = class_device_create_release;
635 class_dev->hotplug = class_device_create_hotplug;
588 636
589 va_start(args, fmt); 637 va_start(args, fmt);
590 vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args); 638 vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
@@ -602,17 +650,18 @@ error:
602 650
603void class_device_del(struct class_device *class_dev) 651void class_device_del(struct class_device *class_dev)
604{ 652{
605 struct class * parent = class_dev->class; 653 struct class *parent_class = class_dev->class;
606 struct class_interface * class_intf; 654 struct class_device *parent_device = class_dev->parent;
655 struct class_interface *class_intf;
607 char *class_name = NULL; 656 char *class_name = NULL;
608 657
609 if (parent) { 658 if (parent_class) {
610 down(&parent->sem); 659 down(&parent_class->sem);
611 list_del_init(&class_dev->node); 660 list_del_init(&class_dev->node);
612 list_for_each_entry(class_intf, &parent->interfaces, node) 661 list_for_each_entry(class_intf, &parent_class->interfaces, node)
613 if (class_intf->remove) 662 if (class_intf->remove)
614 class_intf->remove(class_dev); 663 class_intf->remove(class_dev, class_intf);
615 up(&parent->sem); 664 up(&parent_class->sem);
616 } 665 }
617 666
618 if (class_dev->dev) { 667 if (class_dev->dev) {
@@ -620,6 +669,7 @@ void class_device_del(struct class_device *class_dev)
620 sysfs_remove_link(&class_dev->kobj, "device"); 669 sysfs_remove_link(&class_dev->kobj, "device");
621 sysfs_remove_link(&class_dev->dev->kobj, class_name); 670 sysfs_remove_link(&class_dev->dev->kobj, class_name);
622 } 671 }
672 class_device_remove_file(class_dev, &class_dev->uevent_attr);
623 if (class_dev->devt_attr) 673 if (class_dev->devt_attr)
624 class_device_remove_file(class_dev, class_dev->devt_attr); 674 class_device_remove_file(class_dev, class_dev->devt_attr);
625 class_device_remove_attrs(class_dev); 675 class_device_remove_attrs(class_dev);
@@ -627,8 +677,8 @@ void class_device_del(struct class_device *class_dev)
627 kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE); 677 kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
628 kobject_del(&class_dev->kobj); 678 kobject_del(&class_dev->kobj);
629 679
630 if (parent) 680 class_device_put(parent_device);
631 class_put(parent); 681 class_put(parent_class);
632 kfree(class_name); 682 kfree(class_name);
633} 683}
634 684
@@ -708,7 +758,8 @@ struct class_device * class_device_get(struct class_device *class_dev)
708 758
709void class_device_put(struct class_device *class_dev) 759void class_device_put(struct class_device *class_dev)
710{ 760{
711 kobject_put(&class_dev->kobj); 761 if (class_dev)
762 kobject_put(&class_dev->kobj);
712} 763}
713 764
714 765
@@ -728,7 +779,7 @@ int class_interface_register(struct class_interface *class_intf)
728 list_add_tail(&class_intf->node, &parent->interfaces); 779 list_add_tail(&class_intf->node, &parent->interfaces);
729 if (class_intf->add) { 780 if (class_intf->add) {
730 list_for_each_entry(class_dev, &parent->children, node) 781 list_for_each_entry(class_dev, &parent->children, node)
731 class_intf->add(class_dev); 782 class_intf->add(class_dev, class_intf);
732 } 783 }
733 up(&parent->sem); 784 up(&parent->sem);
734 785
@@ -747,7 +798,7 @@ void class_interface_unregister(struct class_interface *class_intf)
747 list_del_init(&class_intf->node); 798 list_del_init(&class_intf->node);
748 if (class_intf->remove) { 799 if (class_intf->remove) {
749 list_for_each_entry(class_dev, &parent->children, node) 800 list_for_each_entry(class_dev, &parent->children, node)
750 class_intf->remove(class_dev); 801 class_intf->remove(class_dev, class_intf);
751 } 802 }
752 up(&parent->sem); 803 up(&parent->sem);
753 804
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 6ab73f5c799a..8615b42b517a 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -154,6 +154,13 @@ static struct kset_hotplug_ops device_hotplug_ops = {
154 .hotplug = dev_hotplug, 154 .hotplug = dev_hotplug,
155}; 155};
156 156
157static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
158 const char *buf, size_t count)
159{
160 kobject_hotplug(&dev->kobj, KOBJ_ADD);
161 return count;
162}
163
157/** 164/**
158 * device_subsys - structure to be registered with kobject core. 165 * device_subsys - structure to be registered with kobject core.
159 */ 166 */
@@ -225,6 +232,7 @@ void device_initialize(struct device *dev)
225 klist_children_put); 232 klist_children_put);
226 INIT_LIST_HEAD(&dev->dma_pools); 233 INIT_LIST_HEAD(&dev->dma_pools);
227 init_MUTEX(&dev->sem); 234 init_MUTEX(&dev->sem);
235 device_init_wakeup(dev, 0);
228} 236}
229 237
230/** 238/**
@@ -258,6 +266,14 @@ int device_add(struct device *dev)
258 266
259 if ((error = kobject_add(&dev->kobj))) 267 if ((error = kobject_add(&dev->kobj)))
260 goto Error; 268 goto Error;
269
270 dev->uevent_attr.attr.name = "uevent";
271 dev->uevent_attr.attr.mode = S_IWUSR;
272 if (dev->driver)
273 dev->uevent_attr.attr.owner = dev->driver->owner;
274 dev->uevent_attr.store = store_uevent;
275 device_create_file(dev, &dev->uevent_attr);
276
261 kobject_hotplug(&dev->kobj, KOBJ_ADD); 277 kobject_hotplug(&dev->kobj, KOBJ_ADD);
262 if ((error = device_pm_add(dev))) 278 if ((error = device_pm_add(dev)))
263 goto PMError; 279 goto PMError;
@@ -349,6 +365,7 @@ void device_del(struct device * dev)
349 365
350 if (parent) 366 if (parent)
351 klist_del(&dev->knode_parent); 367 klist_del(&dev->knode_parent);
368 device_remove_file(dev, &dev->uevent_attr);
352 369
353 /* Notify the platform of the removal, in case they 370 /* Notify the platform of the removal, in case they
354 * need to do anything... 371 * need to do anything...
@@ -390,11 +407,11 @@ static struct device * next_device(struct klist_iter * i)
390 407
391/** 408/**
392 * device_for_each_child - device child iterator. 409 * device_for_each_child - device child iterator.
393 * @dev: parent struct device. 410 * @parent: parent struct device.
394 * @data: data for the callback. 411 * @data: data for the callback.
395 * @fn: function to be called for each device. 412 * @fn: function to be called for each device.
396 * 413 *
397 * Iterate over @dev's child devices, and call @fn for each, 414 * Iterate over @parent's child devices, and call @fn for each,
398 * passing it @data. 415 * passing it @data.
399 * 416 *
400 * We check the return of @fn each time. If it returns anything 417 * We check the return of @fn each time. If it returns anything
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index b79badd0f158..a95844790f7b 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -9,12 +9,15 @@
9#include <linux/topology.h> 9#include <linux/topology.h>
10#include <linux/device.h> 10#include <linux/device.h>
11 11
12#include "base.h"
12 13
13struct sysdev_class cpu_sysdev_class = { 14struct sysdev_class cpu_sysdev_class = {
14 set_kset_name("cpu"), 15 set_kset_name("cpu"),
15}; 16};
16EXPORT_SYMBOL(cpu_sysdev_class); 17EXPORT_SYMBOL(cpu_sysdev_class);
17 18
19static struct sys_device *cpu_sys_devices[NR_CPUS];
20
18#ifdef CONFIG_HOTPLUG_CPU 21#ifdef CONFIG_HOTPLUG_CPU
19int __attribute__((weak)) smp_prepare_cpu (int cpu) 22int __attribute__((weak)) smp_prepare_cpu (int cpu)
20{ 23{
@@ -63,6 +66,7 @@ static void __devinit register_cpu_control(struct cpu *cpu)
63} 66}
64void unregister_cpu(struct cpu *cpu, struct node *root) 67void unregister_cpu(struct cpu *cpu, struct node *root)
65{ 68{
69 int logical_cpu = cpu->sysdev.id;
66 70
67 if (root) 71 if (root)
68 sysfs_remove_link(&root->sysdev.kobj, 72 sysfs_remove_link(&root->sysdev.kobj,
@@ -70,7 +74,7 @@ void unregister_cpu(struct cpu *cpu, struct node *root)
70 sysdev_remove_file(&cpu->sysdev, &attr_online); 74 sysdev_remove_file(&cpu->sysdev, &attr_online);
71 75
72 sysdev_unregister(&cpu->sysdev); 76 sysdev_unregister(&cpu->sysdev);
73 77 cpu_sys_devices[logical_cpu] = NULL;
74 return; 78 return;
75} 79}
76#else /* ... !CONFIG_HOTPLUG_CPU */ 80#else /* ... !CONFIG_HOTPLUG_CPU */
@@ -102,10 +106,19 @@ int __devinit register_cpu(struct cpu *cpu, int num, struct node *root)
102 kobject_name(&cpu->sysdev.kobj)); 106 kobject_name(&cpu->sysdev.kobj));
103 if (!error && !cpu->no_control) 107 if (!error && !cpu->no_control)
104 register_cpu_control(cpu); 108 register_cpu_control(cpu);
109 if (!error)
110 cpu_sys_devices[num] = &cpu->sysdev;
105 return error; 111 return error;
106} 112}
107 113
108 114struct sys_device *get_cpu_sysdev(int cpu)
115{
116 if (cpu < NR_CPUS)
117 return cpu_sys_devices[cpu];
118 else
119 return NULL;
120}
121EXPORT_SYMBOL_GPL(get_cpu_sysdev);
109 122
110int __init cpu_dev_init(void) 123int __init cpu_dev_init(void)
111{ 124{
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index ef3fe513e398..161f3a390d90 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -28,6 +28,7 @@ static struct device * next_device(struct klist_iter * i)
28/** 28/**
29 * driver_for_each_device - Iterator for devices bound to a driver. 29 * driver_for_each_device - Iterator for devices bound to a driver.
30 * @drv: Driver we're iterating. 30 * @drv: Driver we're iterating.
31 * @start: Device to begin with
31 * @data: Data to pass to the callback. 32 * @data: Data to pass to the callback.
32 * @fn: Function to call for each device. 33 * @fn: Function to call for each device.
33 * 34 *
@@ -57,7 +58,7 @@ EXPORT_SYMBOL_GPL(driver_for_each_device);
57 58
58/** 59/**
59 * driver_find_device - device iterator for locating a particular device. 60 * driver_find_device - device iterator for locating a particular device.
60 * @driver: The device's driver 61 * @drv: The device's driver
61 * @start: Device to begin with 62 * @start: Device to begin with
62 * @data: Data to pass to match function 63 * @data: Data to pass to match function
63 * @match: Callback function to check device 64 * @match: Callback function to check device
diff --git a/drivers/base/firmware.c b/drivers/base/firmware.c
index 88ab044932f2..cb1b98ae0d58 100644
--- a/drivers/base/firmware.c
+++ b/drivers/base/firmware.c
@@ -11,6 +11,9 @@
11#include <linux/kobject.h> 11#include <linux/kobject.h>
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/device.h>
15
16#include "base.h"
14 17
15static decl_subsys(firmware, NULL, NULL); 18static decl_subsys(firmware, NULL, NULL);
16 19
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 4acb2c5733c3..98f6c02d6790 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -62,14 +62,16 @@ firmware_timeout_show(struct class *class, char *buf)
62} 62}
63 63
64/** 64/**
65 * firmware_timeout_store: 65 * firmware_timeout_store - set number of seconds to wait for firmware
66 * Description: 66 * @class: device class pointer
67 * @buf: buffer to scan for timeout value
68 * @count: number of bytes in @buf
69 *
67 * Sets the number of seconds to wait for the firmware. Once 70 * Sets the number of seconds to wait for the firmware. Once
68 * this expires an error will be return to the driver and no 71 * this expires an error will be returned to the driver and no
69 * firmware will be provided. 72 * firmware will be provided.
70 * 73 *
71 * Note: zero means 'wait for ever' 74 * Note: zero means 'wait forever'.
72 *
73 **/ 75 **/
74static ssize_t 76static ssize_t
75firmware_timeout_store(struct class *class, const char *buf, size_t count) 77firmware_timeout_store(struct class *class, const char *buf, size_t count)
@@ -123,12 +125,15 @@ firmware_loading_show(struct class_device *class_dev, char *buf)
123} 125}
124 126
125/** 127/**
126 * firmware_loading_store: - loading control file 128 * firmware_loading_store - set value in the 'loading' control file
127 * Description: 129 * @class_dev: class_device pointer
130 * @buf: buffer to scan for loading control value
131 * @count: number of bytes in @buf
132 *
128 * The relevant values are: 133 * The relevant values are:
129 * 134 *
130 * 1: Start a load, discarding any previous partial load. 135 * 1: Start a load, discarding any previous partial load.
131 * 0: Conclude the load and handle the data to the driver code. 136 * 0: Conclude the load and hand the data to the driver code.
132 * -1: Conclude the load with an error and discard any written data. 137 * -1: Conclude the load with an error and discard any written data.
133 **/ 138 **/
134static ssize_t 139static ssize_t
@@ -201,6 +206,7 @@ out:
201 up(&fw_lock); 206 up(&fw_lock);
202 return ret_count; 207 return ret_count;
203} 208}
209
204static int 210static int
205fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) 211fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
206{ 212{
@@ -227,11 +233,13 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
227} 233}
228 234
229/** 235/**
230 * firmware_data_write: 236 * firmware_data_write - write method for firmware
237 * @kobj: kobject for the class_device
238 * @buffer: buffer being written
239 * @offset: buffer offset for write in total data store area
240 * @count: buffer size
231 * 241 *
232 * Description: 242 * Data written to the 'data' attribute will be later handed to
233 *
234 * Data written to the 'data' attribute will be later handled to
235 * the driver as a firmware image. 243 * the driver as a firmware image.
236 **/ 244 **/
237static ssize_t 245static ssize_t
@@ -264,6 +272,7 @@ out:
264 up(&fw_lock); 272 up(&fw_lock);
265 return retval; 273 return retval;
266} 274}
275
267static struct bin_attribute firmware_attr_data_tmpl = { 276static struct bin_attribute firmware_attr_data_tmpl = {
268 .attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE}, 277 .attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE},
269 .size = 0, 278 .size = 0,
@@ -448,13 +457,16 @@ out:
448 457
449/** 458/**
450 * request_firmware: - request firmware to hotplug and wait for it 459 * request_firmware: - request firmware to hotplug and wait for it
451 * Description: 460 * @firmware_p: pointer to firmware image
452 * @firmware will be used to return a firmware image by the name 461 * @name: name of firmware file
462 * @device: device for which firmware is being loaded
463 *
464 * @firmware_p will be used to return a firmware image by the name
453 * of @name for device @device. 465 * of @name for device @device.
454 * 466 *
455 * Should be called from user context where sleeping is allowed. 467 * Should be called from user context where sleeping is allowed.
456 * 468 *
457 * @name will be use as $FIRMWARE in the hotplug environment and 469 * @name will be used as $FIRMWARE in the hotplug environment and
458 * should be distinctive enough not to be confused with any other 470 * should be distinctive enough not to be confused with any other
459 * firmware image for this or any other device. 471 * firmware image for this or any other device.
460 **/ 472 **/
@@ -468,6 +480,7 @@ request_firmware(const struct firmware **firmware_p, const char *name,
468 480
469/** 481/**
470 * release_firmware: - release the resource associated with a firmware image 482 * release_firmware: - release the resource associated with a firmware image
483 * @fw: firmware resource to release
471 **/ 484 **/
472void 485void
473release_firmware(const struct firmware *fw) 486release_firmware(const struct firmware *fw)
@@ -480,8 +493,10 @@ release_firmware(const struct firmware *fw)
480 493
481/** 494/**
482 * register_firmware: - provide a firmware image for later usage 495 * register_firmware: - provide a firmware image for later usage
496 * @name: name of firmware image file
497 * @data: buffer pointer for the firmware image
498 * @size: size of the data buffer area
483 * 499 *
484 * Description:
485 * Make sure that @data will be available by requesting firmware @name. 500 * Make sure that @data will be available by requesting firmware @name.
486 * 501 *
487 * Note: This will not be possible until some kind of persistence 502 * Note: This will not be possible until some kind of persistence
@@ -526,21 +541,19 @@ request_firmware_work_func(void *arg)
526} 541}
527 542
528/** 543/**
529 * request_firmware_nowait: 544 * request_firmware_nowait: asynchronous version of request_firmware
545 * @module: module requesting the firmware
546 * @hotplug: invokes hotplug event to copy the firmware image if this flag
547 * is non-zero else the firmware copy must be done manually.
548 * @name: name of firmware file
549 * @device: device for which firmware is being loaded
550 * @context: will be passed over to @cont, and
551 * @fw may be %NULL if firmware request fails.
552 * @cont: function will be called asynchronously when the firmware
553 * request is over.
530 * 554 *
531 * Description:
532 * Asynchronous variant of request_firmware() for contexts where 555 * Asynchronous variant of request_firmware() for contexts where
533 * it is not possible to sleep. 556 * it is not possible to sleep.
534 *
535 * @hotplug invokes hotplug event to copy the firmware image if this flag
536 * is non-zero else the firmware copy must be done manually.
537 *
538 * @cont will be called asynchronously when the firmware request is over.
539 *
540 * @context will be passed over to @cont.
541 *
542 * @fw may be %NULL if firmware request fails.
543 *
544 **/ 557 **/
545int 558int
546request_firmware_nowait( 559request_firmware_nowait(
diff --git a/drivers/base/init.c b/drivers/base/init.c
index a76ae5a221f3..c648914b9cde 100644
--- a/drivers/base/init.c
+++ b/drivers/base/init.c
@@ -9,15 +9,10 @@
9 9
10#include <linux/device.h> 10#include <linux/device.h>
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/memory.h>
13
14#include "base.h"
12 15
13extern int devices_init(void);
14extern int buses_init(void);
15extern int classes_init(void);
16extern int firmware_init(void);
17extern int platform_bus_init(void);
18extern int system_bus_init(void);
19extern int cpu_dev_init(void);
20extern int attribute_container_init(void);
21/** 16/**
22 * driver_init - initialize driver model. 17 * driver_init - initialize driver model.
23 * 18 *
@@ -39,5 +34,6 @@ void __init driver_init(void)
39 platform_bus_init(); 34 platform_bus_init();
40 system_bus_init(); 35 system_bus_init();
41 cpu_dev_init(); 36 cpu_dev_init();
37 memory_dev_init();
42 attribute_container_init(); 38 attribute_container_init();
43} 39}
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
new file mode 100644
index 000000000000..b7ddd651d664
--- /dev/null
+++ b/drivers/base/memory.c
@@ -0,0 +1,452 @@
1/*
2 * drivers/base/memory.c - basic Memory class support
3 *
4 * Written by Matt Tolentino <matthew.e.tolentino@intel.com>
5 * Dave Hansen <haveblue@us.ibm.com>
6 *
7 * This file provides the necessary infrastructure to represent
8 * a SPARSEMEM-memory-model system's physical memory in /sysfs.
9 * All arch-independent code that assumes MEMORY_HOTPLUG requires
10 * SPARSEMEM should be contained here, or in mm/memory_hotplug.c.
11 */
12
13#include <linux/sysdev.h>
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/sched.h> /* capable() */
17#include <linux/topology.h>
18#include <linux/device.h>
19#include <linux/memory.h>
20#include <linux/kobject.h>
21#include <linux/memory_hotplug.h>
22#include <linux/mm.h>
23#include <asm/atomic.h>
24#include <asm/uaccess.h>
25
26#define MEMORY_CLASS_NAME "memory"
27
28static struct sysdev_class memory_sysdev_class = {
29 set_kset_name(MEMORY_CLASS_NAME),
30};
31EXPORT_SYMBOL(memory_sysdev_class);
32
33static char *memory_hotplug_name(struct kset *kset, struct kobject *kobj)
34{
35 return MEMORY_CLASS_NAME;
36}
37
38static int memory_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
39 int num_envp, char *buffer, int buffer_size)
40{
41 int retval = 0;
42
43 return retval;
44}
45
46static struct kset_hotplug_ops memory_hotplug_ops = {
47 .name = memory_hotplug_name,
48 .hotplug = memory_hotplug,
49};
50
51static struct notifier_block *memory_chain;
52
53static int register_memory_notifier(struct notifier_block *nb)
54{
55 return notifier_chain_register(&memory_chain, nb);
56}
57
58static void unregister_memory_notifier(struct notifier_block *nb)
59{
60 notifier_chain_unregister(&memory_chain, nb);
61}
62
63/*
64 * register_memory - Setup a sysfs device for a memory block
65 */
66static int
67register_memory(struct memory_block *memory, struct mem_section *section,
68 struct node *root)
69{
70 int error;
71
72 memory->sysdev.cls = &memory_sysdev_class;
73 memory->sysdev.id = __section_nr(section);
74
75 error = sysdev_register(&memory->sysdev);
76
77 if (root && !error)
78 error = sysfs_create_link(&root->sysdev.kobj,
79 &memory->sysdev.kobj,
80 kobject_name(&memory->sysdev.kobj));
81
82 return error;
83}
84
85static void
86unregister_memory(struct memory_block *memory, struct mem_section *section,
87 struct node *root)
88{
89 BUG_ON(memory->sysdev.cls != &memory_sysdev_class);
90 BUG_ON(memory->sysdev.id != __section_nr(section));
91
92 sysdev_unregister(&memory->sysdev);
93 if (root)
94 sysfs_remove_link(&root->sysdev.kobj,
95 kobject_name(&memory->sysdev.kobj));
96}
97
98/*
99 * use this as the physical section index that this memsection
100 * uses.
101 */
102
103static ssize_t show_mem_phys_index(struct sys_device *dev, char *buf)
104{
105 struct memory_block *mem =
106 container_of(dev, struct memory_block, sysdev);
107 return sprintf(buf, "%08lx\n", mem->phys_index);
108}
109
110/*
111 * online, offline, going offline, etc.
112 */
113static ssize_t show_mem_state(struct sys_device *dev, char *buf)
114{
115 struct memory_block *mem =
116 container_of(dev, struct memory_block, sysdev);
117 ssize_t len = 0;
118
119 /*
120 * We can probably put these states in a nice little array
121 * so that they're not open-coded
122 */
123 switch (mem->state) {
124 case MEM_ONLINE:
125 len = sprintf(buf, "online\n");
126 break;
127 case MEM_OFFLINE:
128 len = sprintf(buf, "offline\n");
129 break;
130 case MEM_GOING_OFFLINE:
131 len = sprintf(buf, "going-offline\n");
132 break;
133 default:
134 len = sprintf(buf, "ERROR-UNKNOWN-%ld\n",
135 mem->state);
136 WARN_ON(1);
137 break;
138 }
139
140 return len;
141}
142
143static inline int memory_notify(unsigned long val, void *v)
144{
145 return notifier_call_chain(&memory_chain, val, v);
146}
147
148/*
149 * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is
150 * OK to have direct references to sparsemem variables in here.
151 */
152static int
153memory_block_action(struct memory_block *mem, unsigned long action)
154{
155 int i;
156 unsigned long psection;
157 unsigned long start_pfn, start_paddr;
158 struct page *first_page;
159 int ret;
160 int old_state = mem->state;
161
162 psection = mem->phys_index;
163 first_page = pfn_to_page(psection << PFN_SECTION_SHIFT);
164
165 /*
166 * The probe routines leave the pages reserved, just
167 * as the bootmem code does. Make sure they're still
168 * that way.
169 */
170 if (action == MEM_ONLINE) {
171 for (i = 0; i < PAGES_PER_SECTION; i++) {
172 if (PageReserved(first_page+i))
173 continue;
174
175 printk(KERN_WARNING "section number %ld page number %d "
176 "not reserved, was it already online? \n",
177 psection, i);
178 return -EBUSY;
179 }
180 }
181
182 switch (action) {
183 case MEM_ONLINE:
184 start_pfn = page_to_pfn(first_page);
185 ret = online_pages(start_pfn, PAGES_PER_SECTION);
186 break;
187 case MEM_OFFLINE:
188 mem->state = MEM_GOING_OFFLINE;
189 memory_notify(MEM_GOING_OFFLINE, NULL);
190 start_paddr = page_to_pfn(first_page) << PAGE_SHIFT;
191 ret = remove_memory(start_paddr,
192 PAGES_PER_SECTION << PAGE_SHIFT);
193 if (ret) {
194 mem->state = old_state;
195 break;
196 }
197 memory_notify(MEM_MAPPING_INVALID, NULL);
198 break;
199 default:
200 printk(KERN_WARNING "%s(%p, %ld) unknown action: %ld\n",
201 __FUNCTION__, mem, action, action);
202 WARN_ON(1);
203 ret = -EINVAL;
204 }
205 /*
206 * For now, only notify on successful memory operations
207 */
208 if (!ret)
209 memory_notify(action, NULL);
210
211 return ret;
212}
213
214static int memory_block_change_state(struct memory_block *mem,
215 unsigned long to_state, unsigned long from_state_req)
216{
217 int ret = 0;
218 down(&mem->state_sem);
219
220 if (mem->state != from_state_req) {
221 ret = -EINVAL;
222 goto out;
223 }
224
225 ret = memory_block_action(mem, to_state);
226 if (!ret)
227 mem->state = to_state;
228
229out:
230 up(&mem->state_sem);
231 return ret;
232}
233
234static ssize_t
235store_mem_state(struct sys_device *dev, const char *buf, size_t count)
236{
237 struct memory_block *mem;
238 unsigned int phys_section_nr;
239 int ret = -EINVAL;
240
241 mem = container_of(dev, struct memory_block, sysdev);
242 phys_section_nr = mem->phys_index;
243
244 if (!valid_section_nr(phys_section_nr))
245 goto out;
246
247 if (!strncmp(buf, "online", min((int)count, 6)))
248 ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
249 else if(!strncmp(buf, "offline", min((int)count, 7)))
250 ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
251out:
252 if (ret)
253 return ret;
254 return count;
255}
256
257/*
258 * phys_device is a bad name for this. What I really want
259 * is a way to differentiate between memory ranges that
260 * are part of physical devices that constitute
261 * a complete removable unit or fru.
262 * i.e. do these ranges belong to the same physical device,
263 * s.t. if I offline all of these sections I can then
264 * remove the physical device?
265 */
266static ssize_t show_phys_device(struct sys_device *dev, char *buf)
267{
268 struct memory_block *mem =
269 container_of(dev, struct memory_block, sysdev);
270 return sprintf(buf, "%d\n", mem->phys_device);
271}
272
273static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL);
274static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state);
275static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL);
276
277#define mem_create_simple_file(mem, attr_name) \
278 sysdev_create_file(&mem->sysdev, &attr_##attr_name)
279#define mem_remove_simple_file(mem, attr_name) \
280 sysdev_remove_file(&mem->sysdev, &attr_##attr_name)
281
282/*
283 * Block size attribute stuff
284 */
285static ssize_t
286print_block_size(struct class *class, char *buf)
287{
288 return sprintf(buf, "%lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE);
289}
290
291static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
292
293static int block_size_init(void)
294{
295 sysfs_create_file(&memory_sysdev_class.kset.kobj,
296 &class_attr_block_size_bytes.attr);
297 return 0;
298}
299
300/*
301 * Some architectures will have custom drivers to do this, and
302 * will not need to do it from userspace. The fake hot-add code
303 * as well as ppc64 will do all of their discovery in userspace
304 * and will require this interface.
305 */
306#ifdef CONFIG_ARCH_MEMORY_PROBE
307static ssize_t
308memory_probe_store(struct class *class, const char __user *buf, size_t count)
309{
310 u64 phys_addr;
311 int ret;
312
313 phys_addr = simple_strtoull(buf, NULL, 0);
314
315 ret = add_memory(phys_addr, PAGES_PER_SECTION << PAGE_SHIFT);
316
317 if (ret)
318 count = ret;
319
320 return count;
321}
322static CLASS_ATTR(probe, 0700, NULL, memory_probe_store);
323
324static int memory_probe_init(void)
325{
326 sysfs_create_file(&memory_sysdev_class.kset.kobj,
327 &class_attr_probe.attr);
328 return 0;
329}
330#else
331#define memory_probe_init(...) do {} while (0)
332#endif
333
334/*
335 * Note that phys_device is optional. It is here to allow for
336 * differentiation between which *physical* devices each
337 * section belongs to...
338 */
339
340static int add_memory_block(unsigned long node_id, struct mem_section *section,
341 unsigned long state, int phys_device)
342{
343 struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL);
344 int ret = 0;
345
346 if (!mem)
347 return -ENOMEM;
348
349 mem->phys_index = __section_nr(section);
350 mem->state = state;
351 init_MUTEX(&mem->state_sem);
352 mem->phys_device = phys_device;
353
354 ret = register_memory(mem, section, NULL);
355 if (!ret)
356 ret = mem_create_simple_file(mem, phys_index);
357 if (!ret)
358 ret = mem_create_simple_file(mem, state);
359 if (!ret)
360 ret = mem_create_simple_file(mem, phys_device);
361
362 return ret;
363}
364
365/*
366 * For now, we have a linear search to go find the appropriate
367 * memory_block corresponding to a particular phys_index. If
368 * this gets to be a real problem, we can always use a radix
369 * tree or something here.
370 *
371 * This could be made generic for all sysdev classes.
372 */
373static struct memory_block *find_memory_block(struct mem_section *section)
374{
375 struct kobject *kobj;
376 struct sys_device *sysdev;
377 struct memory_block *mem;
378 char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
379
380 /*
381 * This only works because we know that section == sysdev->id
382 * slightly redundant with sysdev_register()
383 */
384 sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section));
385
386 kobj = kset_find_obj(&memory_sysdev_class.kset, name);
387 if (!kobj)
388 return NULL;
389
390 sysdev = container_of(kobj, struct sys_device, kobj);
391 mem = container_of(sysdev, struct memory_block, sysdev);
392
393 return mem;
394}
395
396int remove_memory_block(unsigned long node_id, struct mem_section *section,
397 int phys_device)
398{
399 struct memory_block *mem;
400
401 mem = find_memory_block(section);
402 mem_remove_simple_file(mem, phys_index);
403 mem_remove_simple_file(mem, state);
404 mem_remove_simple_file(mem, phys_device);
405 unregister_memory(mem, section, NULL);
406
407 return 0;
408}
409
410/*
411 * need an interface for the VM to add new memory regions,
412 * but without onlining it.
413 */
414int register_new_memory(struct mem_section *section)
415{
416 return add_memory_block(0, section, MEM_OFFLINE, 0);
417}
418
419int unregister_memory_section(struct mem_section *section)
420{
421 if (!valid_section(section))
422 return -EINVAL;
423
424 return remove_memory_block(0, section, 0);
425}
426
427/*
428 * Initialize the sysfs support for memory devices...
429 */
430int __init memory_dev_init(void)
431{
432 unsigned int i;
433 int ret;
434
435 memory_sysdev_class.kset.hotplug_ops = &memory_hotplug_ops;
436 ret = sysdev_class_register(&memory_sysdev_class);
437
438 /*
439 * Create entries for memory sections that were found
440 * during boot and have been initialized
441 */
442 for (i = 0; i < NR_MEM_SECTIONS; i++) {
443 if (!valid_section_nr(i))
444 continue;
445 add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 0);
446 }
447
448 memory_probe_init();
449 block_size_init();
450
451 return ret;
452}
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 361e204209eb..08d9cc99c7de 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -16,6 +16,9 @@
16#include <linux/dma-mapping.h> 16#include <linux/dma-mapping.h>
17#include <linux/bootmem.h> 17#include <linux/bootmem.h>
18#include <linux/err.h> 18#include <linux/err.h>
19#include <linux/slab.h>
20
21#include "base.h"
19 22
20struct device platform_bus = { 23struct device platform_bus = {
21 .bus_id = "platform", 24 .bus_id = "platform",
@@ -279,13 +282,9 @@ static int platform_suspend(struct device * dev, pm_message_t state)
279{ 282{
280 int ret = 0; 283 int ret = 0;
281 284
282 if (dev->driver && dev->driver->suspend) { 285 if (dev->driver && dev->driver->suspend)
283 ret = dev->driver->suspend(dev, state, SUSPEND_DISABLE); 286 ret = dev->driver->suspend(dev, state);
284 if (ret == 0) 287
285 ret = dev->driver->suspend(dev, state, SUSPEND_SAVE_STATE);
286 if (ret == 0)
287 ret = dev->driver->suspend(dev, state, SUSPEND_POWER_DOWN);
288 }
289 return ret; 288 return ret;
290} 289}
291 290
@@ -293,13 +292,9 @@ static int platform_resume(struct device * dev)
293{ 292{
294 int ret = 0; 293 int ret = 0;
295 294
296 if (dev->driver && dev->driver->resume) { 295 if (dev->driver && dev->driver->resume)
297 ret = dev->driver->resume(dev, RESUME_POWER_ON); 296 ret = dev->driver->resume(dev);
298 if (ret == 0) 297
299 ret = dev->driver->resume(dev, RESUME_RESTORE_STATE);
300 if (ret == 0)
301 ret = dev->driver->resume(dev, RESUME_ENABLE);
302 }
303 return ret; 298 return ret;
304} 299}
305 300
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 15e6a8f951f1..0d2e101e4f15 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -30,23 +30,6 @@ LIST_HEAD(dpm_off_irq);
30DECLARE_MUTEX(dpm_sem); 30DECLARE_MUTEX(dpm_sem);
31DECLARE_MUTEX(dpm_list_sem); 31DECLARE_MUTEX(dpm_list_sem);
32 32
33/*
34 * PM Reference Counting.
35 */
36
37static inline void device_pm_hold(struct device * dev)
38{
39 if (dev)
40 atomic_inc(&dev->power.pm_users);
41}
42
43static inline void device_pm_release(struct device * dev)
44{
45 if (dev)
46 atomic_dec(&dev->power.pm_users);
47}
48
49
50/** 33/**
51 * device_pm_set_parent - Specify power dependency. 34 * device_pm_set_parent - Specify power dependency.
52 * @dev: Device who needs power. 35 * @dev: Device who needs power.
@@ -62,10 +45,8 @@ static inline void device_pm_release(struct device * dev)
62 45
63void device_pm_set_parent(struct device * dev, struct device * parent) 46void device_pm_set_parent(struct device * dev, struct device * parent)
64{ 47{
65 struct device * old_parent = dev->power.pm_parent; 48 put_device(dev->power.pm_parent);
66 device_pm_release(old_parent); 49 dev->power.pm_parent = get_device(parent);
67 dev->power.pm_parent = parent;
68 device_pm_hold(parent);
69} 50}
70EXPORT_SYMBOL_GPL(device_pm_set_parent); 51EXPORT_SYMBOL_GPL(device_pm_set_parent);
71 52
@@ -75,7 +56,6 @@ int device_pm_add(struct device * dev)
75 56
76 pr_debug("PM: Adding info for %s:%s\n", 57 pr_debug("PM: Adding info for %s:%s\n",
77 dev->bus ? dev->bus->name : "No Bus", dev->kobj.name); 58 dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
78 atomic_set(&dev->power.pm_users, 0);
79 down(&dpm_list_sem); 59 down(&dpm_list_sem);
80 list_add_tail(&dev->power.entry, &dpm_active); 60 list_add_tail(&dev->power.entry, &dpm_active);
81 device_pm_set_parent(dev, dev->parent); 61 device_pm_set_parent(dev, dev->parent);
@@ -91,7 +71,7 @@ void device_pm_remove(struct device * dev)
91 dev->bus ? dev->bus->name : "No Bus", dev->kobj.name); 71 dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
92 down(&dpm_list_sem); 72 down(&dpm_list_sem);
93 dpm_sysfs_remove(dev); 73 dpm_sysfs_remove(dev);
94 device_pm_release(dev->power.pm_parent); 74 put_device(dev->power.pm_parent);
95 list_del_init(&dev->power.entry); 75 list_del_init(&dev->power.entry);
96 up(&dpm_list_sem); 76 up(&dpm_list_sem);
97} 77}
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 2e700d795cf1..fb3d35a9e101 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -67,9 +67,6 @@ extern int suspend_device(struct device *, pm_message_t);
67 * runtime.c 67 * runtime.c
68 */ 68 */
69 69
70extern int dpm_runtime_suspend(struct device *, pm_message_t);
71extern void dpm_runtime_resume(struct device *);
72
73#else /* CONFIG_PM */ 70#else /* CONFIG_PM */
74 71
75 72
@@ -82,14 +79,4 @@ static inline void device_pm_remove(struct device * dev)
82 79
83} 80}
84 81
85static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state)
86{
87 return 0;
88}
89
90static inline void dpm_runtime_resume(struct device * dev)
91{
92
93}
94
95#endif 82#endif
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index e8f0519f5dfa..adbc3148c039 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -36,6 +36,7 @@ void dpm_runtime_resume(struct device * dev)
36 runtime_resume(dev); 36 runtime_resume(dev);
37 up(&dpm_sem); 37 up(&dpm_sem);
38} 38}
39EXPORT_SYMBOL(dpm_runtime_resume);
39 40
40 41
41/** 42/**
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 8d04fb435c17..89c57875f3e5 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -48,8 +48,81 @@ static ssize_t state_store(struct device * dev, struct device_attribute *attr, c
48static DEVICE_ATTR(state, 0644, state_show, state_store); 48static DEVICE_ATTR(state, 0644, state_show, state_store);
49 49
50 50
51/*
52 * wakeup - Report/change current wakeup option for device
53 *
54 * Some devices support "wakeup" events, which are hardware signals
55 * used to activate devices from suspended or low power states. Such
56 * devices have one of three values for the sysfs power/wakeup file:
57 *
58 * + "enabled\n" to issue the events;
59 * + "disabled\n" not to do so; or
60 * + "\n" for temporary or permanent inability to issue wakeup.
61 *
62 * (For example, unconfigured USB devices can't issue wakeups.)
63 *
64 * Familiar examples of devices that can issue wakeup events include
65 * keyboards and mice (both PS2 and USB styles), power buttons, modems,
66 * "Wake-On-LAN" Ethernet links, GPIO lines, and more. Some events
67 * will wake the entire system from a suspend state; others may just
68 * wake up the device (if the system as a whole is already active).
69 * Some wakeup events use normal IRQ lines; other use special out
70 * of band signaling.
71 *
72 * It is the responsibility of device drivers to enable (or disable)
73 * wakeup signaling as part of changing device power states, respecting
74 * the policy choices provided through the driver model.
75 *
76 * Devices may not be able to generate wakeup events from all power
77 * states. Also, the events may be ignored in some configurations;
78 * for example, they might need help from other devices that aren't
79 * active, or which may have wakeup disabled. Some drivers rely on
80 * wakeup events internally (unless they are disabled), keeping
81 * their hardware in low power modes whenever they're unused. This
82 * saves runtime power, without requiring system-wide sleep states.
83 */
84
85static const char enabled[] = "enabled";
86static const char disabled[] = "disabled";
87
88static ssize_t
89wake_show(struct device * dev, struct device_attribute *attr, char * buf)
90{
91 return sprintf(buf, "%s\n", device_can_wakeup(dev)
92 ? (device_may_wakeup(dev) ? enabled : disabled)
93 : "");
94}
95
96static ssize_t
97wake_store(struct device * dev, struct device_attribute *attr,
98 const char * buf, size_t n)
99{
100 char *cp;
101 int len = n;
102
103 if (!device_can_wakeup(dev))
104 return -EINVAL;
105
106 cp = memchr(buf, '\n', n);
107 if (cp)
108 len = cp - buf;
109 if (len == sizeof enabled - 1
110 && strncmp(buf, enabled, sizeof enabled - 1) == 0)
111 device_set_wakeup_enable(dev, 1);
112 else if (len == sizeof disabled - 1
113 && strncmp(buf, disabled, sizeof disabled - 1) == 0)
114 device_set_wakeup_enable(dev, 0);
115 else
116 return -EINVAL;
117 return n;
118}
119
120static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
121
122
51static struct attribute * power_attrs[] = { 123static struct attribute * power_attrs[] = {
52 &dev_attr_state.attr, 124 &dev_attr_state.attr,
125 &dev_attr_wakeup.attr,
53 NULL, 126 NULL,
54}; 127};
55static struct attribute_group pm_attr_group = { 128static struct attribute_group pm_attr_group = {
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 3431eb6004c3..66ed8f2fece5 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -21,6 +21,7 @@
21#include <linux/slab.h> 21#include <linux/slab.h>
22#include <linux/string.h> 22#include <linux/string.h>
23#include <linux/pm.h> 23#include <linux/pm.h>
24#include <asm/semaphore.h>
24 25
25extern struct subsystem devices_subsys; 26extern struct subsystem devices_subsys;
26 27