You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (31 commits) driver core: Display error codes when class suspend fails Driver core: Add section count to memory_block struct Driver core: Add mutex for adding/removing memory blocks Driver core: Move find_memory_block routine hpilo: Despecificate driver from iLO generation driver core: Convert link_mem_sections to use find_memory_block_hinted. driver core: Introduce find_memory_block_hinted which utilizes kset_find_obj_hinted. kobject: Introduce kset_find_obj_hinted. driver core: fix build for CONFIG_BLOCK not enabled driver-core: base: change to new flag variable sysfs: only access bin file vm_ops with the active lock sysfs: Fail bin file mmap if vma close is implemented. FW_LOADER: fix kconfig dependency warning on HOTPLUG uio: Statically allocate uio_class and use class .dev_attrs. uio: Support 2^MINOR_BITS minors uio: Cleanup irq handling. uio: Don't clear driver data uio: Fix lack of locking in init_uio_class SYSFS: Allow boot time switching between deprecated and modern sysfs layout driver core: remove CONFIG_SYSFS_DEPRECATED_V2 but keep it for block devices ...
This commit is contained in:
@@ -71,7 +71,6 @@ config PREVENT_FIRMWARE_BUILD
|
||||
|
||||
config FW_LOADER
|
||||
tristate "Userspace firmware loading support" if EMBEDDED
|
||||
depends on HOTPLUG
|
||||
default y
|
||||
---help---
|
||||
This option is provided for the case where no in-kernel-tree modules
|
||||
|
||||
@@ -19,7 +19,5 @@ obj-$(CONFIG_MODULES) += module.o
|
||||
endif
|
||||
obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
|
||||
|
||||
ifeq ($(CONFIG_DEBUG_DRIVER),y)
|
||||
EXTRA_CFLAGS += -DDEBUG
|
||||
endif
|
||||
ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
|
||||
|
||||
|
||||
@@ -440,22 +440,6 @@ static void device_remove_attrs(struct bus_type *bus, struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
static int make_deprecated_bus_links(struct device *dev)
|
||||
{
|
||||
return sysfs_create_link(&dev->kobj,
|
||||
&dev->bus->p->subsys.kobj, "bus");
|
||||
}
|
||||
|
||||
static void remove_deprecated_bus_links(struct device *dev)
|
||||
{
|
||||
sysfs_remove_link(&dev->kobj, "bus");
|
||||
}
|
||||
#else
|
||||
static inline int make_deprecated_bus_links(struct device *dev) { return 0; }
|
||||
static inline void remove_deprecated_bus_links(struct device *dev) { }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* bus_add_device - add device to bus
|
||||
* @dev: device being added
|
||||
@@ -482,15 +466,10 @@ int bus_add_device(struct device *dev)
|
||||
&dev->bus->p->subsys.kobj, "subsystem");
|
||||
if (error)
|
||||
goto out_subsys;
|
||||
error = make_deprecated_bus_links(dev);
|
||||
if (error)
|
||||
goto out_deprecated;
|
||||
klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
|
||||
}
|
||||
return 0;
|
||||
|
||||
out_deprecated:
|
||||
sysfs_remove_link(&dev->kobj, "subsystem");
|
||||
out_subsys:
|
||||
sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev));
|
||||
out_id:
|
||||
@@ -530,7 +509,6 @@ void bus_remove_device(struct device *dev)
|
||||
{
|
||||
if (dev->bus) {
|
||||
sysfs_remove_link(&dev->kobj, "subsystem");
|
||||
remove_deprecated_bus_links(dev);
|
||||
sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
|
||||
dev_name(dev));
|
||||
device_remove_attrs(dev->bus, dev);
|
||||
|
||||
+2
-21
@@ -184,9 +184,9 @@ int __class_register(struct class *cls, struct lock_class_key *key)
|
||||
if (!cls->dev_kobj)
|
||||
cls->dev_kobj = sysfs_dev_char_kobj;
|
||||
|
||||
#if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK)
|
||||
#if defined(CONFIG_BLOCK)
|
||||
/* let the block class directory show up in the root of sysfs */
|
||||
if (cls != &block_class)
|
||||
if (!sysfs_deprecated || cls != &block_class)
|
||||
cp->class_subsys.kobj.kset = class_kset;
|
||||
#else
|
||||
cp->class_subsys.kobj.kset = class_kset;
|
||||
@@ -276,25 +276,6 @@ void class_destroy(struct class *cls)
|
||||
class_unregister(cls);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
char *make_class_name(const char *name, struct kobject *kobj)
|
||||
{
|
||||
char *class_name;
|
||||
int size;
|
||||
|
||||
size = strlen(name) + strlen(kobject_name(kobj)) + 2;
|
||||
|
||||
class_name = kmalloc(size, GFP_KERNEL);
|
||||
if (!class_name)
|
||||
return NULL;
|
||||
|
||||
strcpy(class_name, name);
|
||||
strcat(class_name, ":");
|
||||
strcat(class_name, kobject_name(kobj));
|
||||
return class_name;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* class_dev_iter_init - initialize class device iterator
|
||||
* @iter: class iterator to initialize
|
||||
|
||||
+44
-174
@@ -26,6 +26,19 @@
|
||||
#include "base.h"
|
||||
#include "power/power.h"
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED_V2
|
||||
long sysfs_deprecated = 1;
|
||||
#else
|
||||
long sysfs_deprecated = 0;
|
||||
#endif
|
||||
static __init int sysfs_deprecated_setup(char *arg)
|
||||
{
|
||||
return strict_strtol(arg, 10, &sysfs_deprecated);
|
||||
}
|
||||
early_param("sysfs.deprecated", sysfs_deprecated_setup);
|
||||
#endif
|
||||
|
||||
int (*platform_notify)(struct device *dev) = NULL;
|
||||
int (*platform_notify_remove)(struct device *dev) = NULL;
|
||||
static struct kobject *dev_kobj;
|
||||
@@ -203,37 +216,6 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
|
||||
if (dev->driver)
|
||||
add_uevent_var(env, "DRIVER=%s", dev->driver->name);
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
if (dev->class) {
|
||||
struct device *parent = dev->parent;
|
||||
|
||||
/* find first bus device in parent chain */
|
||||
while (parent && !parent->bus)
|
||||
parent = parent->parent;
|
||||
if (parent && parent->bus) {
|
||||
const char *path;
|
||||
|
||||
path = kobject_get_path(&parent->kobj, GFP_KERNEL);
|
||||
if (path) {
|
||||
add_uevent_var(env, "PHYSDEVPATH=%s", path);
|
||||
kfree(path);
|
||||
}
|
||||
|
||||
add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name);
|
||||
|
||||
if (parent->driver)
|
||||
add_uevent_var(env, "PHYSDEVDRIVER=%s",
|
||||
parent->driver->name);
|
||||
}
|
||||
} else if (dev->bus) {
|
||||
add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
|
||||
|
||||
if (dev->driver)
|
||||
add_uevent_var(env, "PHYSDEVDRIVER=%s",
|
||||
dev->driver->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* have the bus specific function add its stuff */
|
||||
if (dev->bus && dev->bus->uevent) {
|
||||
retval = dev->bus->uevent(dev, env);
|
||||
@@ -578,24 +560,6 @@ void device_initialize(struct device *dev)
|
||||
set_dev_node(dev, -1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
static struct kobject *get_device_parent(struct device *dev,
|
||||
struct device *parent)
|
||||
{
|
||||
/* class devices without a parent live in /sys/class/<classname>/ */
|
||||
if (dev->class && (!parent || parent->class != dev->class))
|
||||
return &dev->class->p->class_subsys.kobj;
|
||||
/* all other devices keep their parent */
|
||||
else if (parent)
|
||||
return &parent->kobj;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void cleanup_device_parent(struct device *dev) {}
|
||||
static inline void cleanup_glue_dir(struct device *dev,
|
||||
struct kobject *glue_dir) {}
|
||||
#else
|
||||
static struct kobject *virtual_device_parent(struct device *dev)
|
||||
{
|
||||
static struct kobject *virtual_dir = NULL;
|
||||
@@ -666,6 +630,15 @@ static struct kobject *get_device_parent(struct device *dev,
|
||||
struct kobject *parent_kobj;
|
||||
struct kobject *k;
|
||||
|
||||
#ifdef CONFIG_BLOCK
|
||||
/* block disks show up in /sys/block */
|
||||
if (sysfs_deprecated && dev->class == &block_class) {
|
||||
if (parent && parent->class == &block_class)
|
||||
return &parent->kobj;
|
||||
return &block_class.p->class_subsys.kobj;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If we have no parent, we live in "virtual".
|
||||
* Class-devices with a non class-device as parent, live
|
||||
@@ -719,7 +692,6 @@ static void cleanup_device_parent(struct device *dev)
|
||||
{
|
||||
cleanup_glue_dir(dev, dev->kobj.parent);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void setup_parent(struct device *dev, struct device *parent)
|
||||
{
|
||||
@@ -742,70 +714,29 @@ static int device_add_class_symlinks(struct device *dev)
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
/* stacked class devices need a symlink in the class directory */
|
||||
if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
|
||||
device_is_not_partition(dev)) {
|
||||
error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
|
||||
&dev->kobj, dev_name(dev));
|
||||
if (error)
|
||||
goto out_subsys;
|
||||
}
|
||||
|
||||
if (dev->parent && device_is_not_partition(dev)) {
|
||||
struct device *parent = dev->parent;
|
||||
char *class_name;
|
||||
|
||||
/*
|
||||
* stacked class devices have the 'device' link
|
||||
* pointing to the bus device instead of the parent
|
||||
*/
|
||||
while (parent->class && !parent->bus && parent->parent)
|
||||
parent = parent->parent;
|
||||
|
||||
error = sysfs_create_link(&dev->kobj,
|
||||
&parent->kobj,
|
||||
"device");
|
||||
if (error)
|
||||
goto out_busid;
|
||||
|
||||
class_name = make_class_name(dev->class->name,
|
||||
&dev->kobj);
|
||||
if (class_name)
|
||||
error = sysfs_create_link(&dev->parent->kobj,
|
||||
&dev->kobj, class_name);
|
||||
kfree(class_name);
|
||||
if (error)
|
||||
goto out_device;
|
||||
}
|
||||
return 0;
|
||||
|
||||
out_device:
|
||||
if (dev->parent && device_is_not_partition(dev))
|
||||
sysfs_remove_link(&dev->kobj, "device");
|
||||
out_busid:
|
||||
if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
|
||||
device_is_not_partition(dev))
|
||||
sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj,
|
||||
dev_name(dev));
|
||||
#else
|
||||
/* link in the class directory pointing to the device */
|
||||
error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
|
||||
&dev->kobj, dev_name(dev));
|
||||
if (error)
|
||||
goto out_subsys;
|
||||
|
||||
if (dev->parent && device_is_not_partition(dev)) {
|
||||
error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
|
||||
"device");
|
||||
if (error)
|
||||
goto out_busid;
|
||||
goto out_subsys;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLOCK
|
||||
/* /sys/block has directories and does not need symlinks */
|
||||
if (sysfs_deprecated && dev->class == &block_class)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
/* link in the class directory pointing to the device */
|
||||
error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
|
||||
&dev->kobj, dev_name(dev));
|
||||
if (error)
|
||||
goto out_device;
|
||||
|
||||
return 0;
|
||||
|
||||
out_busid:
|
||||
sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
|
||||
#endif
|
||||
out_device:
|
||||
sysfs_remove_link(&dev->kobj, "device");
|
||||
|
||||
out_subsys:
|
||||
sysfs_remove_link(&dev->kobj, "subsystem");
|
||||
@@ -818,30 +749,14 @@ static void device_remove_class_symlinks(struct device *dev)
|
||||
if (!dev->class)
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
if (dev->parent && device_is_not_partition(dev)) {
|
||||
char *class_name;
|
||||
|
||||
class_name = make_class_name(dev->class->name, &dev->kobj);
|
||||
if (class_name) {
|
||||
sysfs_remove_link(&dev->parent->kobj, class_name);
|
||||
kfree(class_name);
|
||||
}
|
||||
sysfs_remove_link(&dev->kobj, "device");
|
||||
}
|
||||
|
||||
if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
|
||||
device_is_not_partition(dev))
|
||||
sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj,
|
||||
dev_name(dev));
|
||||
#else
|
||||
if (dev->parent && device_is_not_partition(dev))
|
||||
sysfs_remove_link(&dev->kobj, "device");
|
||||
|
||||
sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
|
||||
#endif
|
||||
|
||||
sysfs_remove_link(&dev->kobj, "subsystem");
|
||||
#ifdef CONFIG_BLOCK
|
||||
if (sysfs_deprecated && dev->class == &block_class)
|
||||
return;
|
||||
#endif
|
||||
sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1613,41 +1528,23 @@ int device_rename(struct device *dev, const char *new_name)
|
||||
pr_debug("device: '%s': %s: renaming to '%s'\n", dev_name(dev),
|
||||
__func__, new_name);
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
if ((dev->class) && (dev->parent))
|
||||
old_class_name = make_class_name(dev->class->name, &dev->kobj);
|
||||
#endif
|
||||
|
||||
old_device_name = kstrdup(dev_name(dev), GFP_KERNEL);
|
||||
if (!old_device_name) {
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SYSFS_DEPRECATED
|
||||
if (dev->class) {
|
||||
error = sysfs_rename_link(&dev->class->p->class_subsys.kobj,
|
||||
&dev->kobj, old_device_name, new_name);
|
||||
if (error)
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
error = kobject_rename(&dev->kobj, new_name);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
if (old_class_name) {
|
||||
new_class_name = make_class_name(dev->class->name, &dev->kobj);
|
||||
if (new_class_name) {
|
||||
error = sysfs_rename_link(&dev->parent->kobj,
|
||||
&dev->kobj,
|
||||
old_class_name,
|
||||
new_class_name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
out:
|
||||
put_device(dev);
|
||||
|
||||
@@ -1664,40 +1561,13 @@ static int device_move_class_links(struct device *dev,
|
||||
struct device *new_parent)
|
||||
{
|
||||
int error = 0;
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
char *class_name;
|
||||
|
||||
class_name = make_class_name(dev->class->name, &dev->kobj);
|
||||
if (!class_name) {
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (old_parent) {
|
||||
sysfs_remove_link(&dev->kobj, "device");
|
||||
sysfs_remove_link(&old_parent->kobj, class_name);
|
||||
}
|
||||
if (new_parent) {
|
||||
error = sysfs_create_link(&dev->kobj, &new_parent->kobj,
|
||||
"device");
|
||||
if (error)
|
||||
goto out;
|
||||
error = sysfs_create_link(&new_parent->kobj, &dev->kobj,
|
||||
class_name);
|
||||
if (error)
|
||||
sysfs_remove_link(&dev->kobj, "device");
|
||||
} else
|
||||
error = 0;
|
||||
out:
|
||||
kfree(class_name);
|
||||
return error;
|
||||
#else
|
||||
if (old_parent)
|
||||
sysfs_remove_link(&dev->kobj, "device");
|
||||
if (new_parent)
|
||||
error = sysfs_create_link(&dev->kobj, &new_parent->kobj,
|
||||
"device");
|
||||
return error;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+57
-37
@@ -27,6 +27,8 @@
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
static DEFINE_MUTEX(mem_sysfs_mutex);
|
||||
|
||||
#define MEMORY_CLASS_NAME "memory"
|
||||
|
||||
static struct sysdev_class memory_sysdev_class = {
|
||||
@@ -435,6 +437,45 @@ int __weak arch_get_memory_phys_device(unsigned long start_pfn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct memory_block *find_memory_block_hinted(struct mem_section *section,
|
||||
struct memory_block *hint)
|
||||
{
|
||||
struct kobject *kobj;
|
||||
struct sys_device *sysdev;
|
||||
struct memory_block *mem;
|
||||
char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
|
||||
|
||||
kobj = hint ? &hint->sysdev.kobj : NULL;
|
||||
|
||||
/*
|
||||
* This only works because we know that section == sysdev->id
|
||||
* slightly redundant with sysdev_register()
|
||||
*/
|
||||
sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section));
|
||||
|
||||
kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj);
|
||||
if (!kobj)
|
||||
return NULL;
|
||||
|
||||
sysdev = container_of(kobj, struct sys_device, kobj);
|
||||
mem = container_of(sysdev, struct memory_block, sysdev);
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
/*
|
||||
* For now, we have a linear search to go find the appropriate
|
||||
* memory_block corresponding to a particular phys_index. If
|
||||
* this gets to be a real problem, we can always use a radix
|
||||
* tree or something here.
|
||||
*
|
||||
* This could be made generic for all sysdev classes.
|
||||
*/
|
||||
struct memory_block *find_memory_block(struct mem_section *section)
|
||||
{
|
||||
return find_memory_block_hinted(section, NULL);
|
||||
}
|
||||
|
||||
static int add_memory_block(int nid, struct mem_section *section,
|
||||
unsigned long state, enum mem_add_context context)
|
||||
{
|
||||
@@ -445,8 +486,11 @@ static int add_memory_block(int nid, struct mem_section *section,
|
||||
if (!mem)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&mem_sysfs_mutex);
|
||||
|
||||
mem->phys_index = __section_nr(section);
|
||||
mem->state = state;
|
||||
mem->section_count++;
|
||||
mutex_init(&mem->state_mutex);
|
||||
start_pfn = section_nr_to_pfn(mem->phys_index);
|
||||
mem->phys_device = arch_get_memory_phys_device(start_pfn);
|
||||
@@ -465,53 +509,29 @@ static int add_memory_block(int nid, struct mem_section *section,
|
||||
ret = register_mem_sect_under_node(mem, nid);
|
||||
}
|
||||
|
||||
mutex_unlock(&mem_sysfs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* For now, we have a linear search to go find the appropriate
|
||||
* memory_block corresponding to a particular phys_index. If
|
||||
* this gets to be a real problem, we can always use a radix
|
||||
* tree or something here.
|
||||
*
|
||||
* This could be made generic for all sysdev classes.
|
||||
*/
|
||||
struct memory_block *find_memory_block(struct mem_section *section)
|
||||
{
|
||||
struct kobject *kobj;
|
||||
struct sys_device *sysdev;
|
||||
struct memory_block *mem;
|
||||
char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
|
||||
|
||||
/*
|
||||
* This only works because we know that section == sysdev->id
|
||||
* slightly redundant with sysdev_register()
|
||||
*/
|
||||
sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section));
|
||||
|
||||
kobj = kset_find_obj(&memory_sysdev_class.kset, name);
|
||||
if (!kobj)
|
||||
return NULL;
|
||||
|
||||
sysdev = container_of(kobj, struct sys_device, kobj);
|
||||
mem = container_of(sysdev, struct memory_block, sysdev);
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
int remove_memory_block(unsigned long node_id, struct mem_section *section,
|
||||
int phys_device)
|
||||
{
|
||||
struct memory_block *mem;
|
||||
|
||||
mutex_lock(&mem_sysfs_mutex);
|
||||
mem = find_memory_block(section);
|
||||
unregister_mem_sect_under_nodes(mem);
|
||||
mem_remove_simple_file(mem, phys_index);
|
||||
mem_remove_simple_file(mem, state);
|
||||
mem_remove_simple_file(mem, phys_device);
|
||||
mem_remove_simple_file(mem, removable);
|
||||
unregister_memory(mem, section);
|
||||
|
||||
mem->section_count--;
|
||||
if (mem->section_count == 0) {
|
||||
unregister_mem_sect_under_nodes(mem);
|
||||
mem_remove_simple_file(mem, phys_index);
|
||||
mem_remove_simple_file(mem, state);
|
||||
mem_remove_simple_file(mem, phys_device);
|
||||
mem_remove_simple_file(mem, removable);
|
||||
unregister_memory(mem, section);
|
||||
}
|
||||
|
||||
mutex_unlock(&mem_sysfs_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -409,25 +409,27 @@ static int link_mem_sections(int nid)
|
||||
unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn;
|
||||
unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages;
|
||||
unsigned long pfn;
|
||||
struct memory_block *mem_blk = NULL;
|
||||
int err = 0;
|
||||
|
||||
for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
|
||||
unsigned long section_nr = pfn_to_section_nr(pfn);
|
||||
struct mem_section *mem_sect;
|
||||
struct memory_block *mem_blk;
|
||||
int ret;
|
||||
|
||||
if (!present_section_nr(section_nr))
|
||||
continue;
|
||||
mem_sect = __nr_to_section(section_nr);
|
||||
mem_blk = find_memory_block(mem_sect);
|
||||
mem_blk = find_memory_block_hinted(mem_sect, mem_blk);
|
||||
ret = register_mem_sect_under_node(mem_blk, nid);
|
||||
if (!err)
|
||||
err = ret;
|
||||
|
||||
/* discard ref obtained in find_memory_block() */
|
||||
kobject_put(&mem_blk->sysdev.kobj);
|
||||
}
|
||||
|
||||
if (mem_blk)
|
||||
kobject_put(&mem_blk->sysdev.kobj);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
+57
-23
@@ -192,6 +192,9 @@ int platform_device_add_resources(struct platform_device *pdev,
|
||||
{
|
||||
struct resource *r;
|
||||
|
||||
if (!res)
|
||||
return 0;
|
||||
|
||||
r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL);
|
||||
if (r) {
|
||||
pdev->resource = r;
|
||||
@@ -215,8 +218,12 @@ EXPORT_SYMBOL_GPL(platform_device_add_resources);
|
||||
int platform_device_add_data(struct platform_device *pdev, const void *data,
|
||||
size_t size)
|
||||
{
|
||||
void *d = kmemdup(data, size, GFP_KERNEL);
|
||||
void *d;
|
||||
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
d = kmemdup(data, size, GFP_KERNEL);
|
||||
if (d) {
|
||||
pdev->dev.platform_data = d;
|
||||
return 0;
|
||||
@@ -373,17 +380,13 @@ struct platform_device *__init_or_module platform_device_register_resndata(
|
||||
|
||||
pdev->dev.parent = parent;
|
||||
|
||||
if (res) {
|
||||
ret = platform_device_add_resources(pdev, res, num);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
ret = platform_device_add_resources(pdev, res, num);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (data) {
|
||||
ret = platform_device_add_data(pdev, data, size);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
ret = platform_device_add_data(pdev, data, size);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = platform_device_add(pdev);
|
||||
if (ret) {
|
||||
@@ -488,12 +491,12 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,
|
||||
* if the probe was successful, and make sure any forced probes of
|
||||
* new devices fail.
|
||||
*/
|
||||
spin_lock(&platform_bus_type.p->klist_drivers.k_lock);
|
||||
spin_lock(&drv->driver.bus->p->klist_drivers.k_lock);
|
||||
drv->probe = NULL;
|
||||
if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list))
|
||||
retval = -ENODEV;
|
||||
drv->driver.probe = platform_drv_probe_fail;
|
||||
spin_unlock(&platform_bus_type.p->klist_drivers.k_lock);
|
||||
spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock);
|
||||
|
||||
if (code != retval)
|
||||
platform_driver_unregister(drv);
|
||||
@@ -530,17 +533,13 @@ struct platform_device * __init_or_module platform_create_bundle(
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (res) {
|
||||
error = platform_device_add_resources(pdev, res, n_res);
|
||||
if (error)
|
||||
goto err_pdev_put;
|
||||
}
|
||||
error = platform_device_add_resources(pdev, res, n_res);
|
||||
if (error)
|
||||
goto err_pdev_put;
|
||||
|
||||
if (data) {
|
||||
error = platform_device_add_data(pdev, data, size);
|
||||
if (error)
|
||||
goto err_pdev_put;
|
||||
}
|
||||
error = platform_device_add_data(pdev, data, size);
|
||||
if (error)
|
||||
goto err_pdev_put;
|
||||
|
||||
error = platform_device_add(pdev);
|
||||
if (error)
|
||||
@@ -976,6 +975,41 @@ struct bus_type platform_bus_type = {
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(platform_bus_type);
|
||||
|
||||
/**
|
||||
* platform_bus_get_pm_ops() - return pointer to busses dev_pm_ops
|
||||
*
|
||||
* This function can be used by platform code to get the current
|
||||
* set of dev_pm_ops functions used by the platform_bus_type.
|
||||
*/
|
||||
const struct dev_pm_ops * __init platform_bus_get_pm_ops(void)
|
||||
{
|
||||
return platform_bus_type.pm;
|
||||
}
|
||||
|
||||
/**
|
||||
* platform_bus_set_pm_ops() - update dev_pm_ops for the platform_bus_type
|
||||
*
|
||||
* @pm: pointer to new dev_pm_ops struct to be used for platform_bus_type
|
||||
*
|
||||
* Platform code can override the dev_pm_ops methods of
|
||||
* platform_bus_type by using this function. It is expected that
|
||||
* platform code will first do a platform_bus_get_pm_ops(), then
|
||||
* kmemdup it, then customize selected methods and pass a pointer to
|
||||
* the new struct dev_pm_ops to this function.
|
||||
*
|
||||
* Since platform-specific code is customizing methods for *all*
|
||||
* devices (not just platform-specific devices) it is expected that
|
||||
* any custom overrides of these functions will keep existing behavior
|
||||
* and simply extend it. For example, any customization of the
|
||||
* runtime PM methods should continue to call the pm_generic_*
|
||||
* functions as the default ones do in addition to the
|
||||
* platform-specific behavior.
|
||||
*/
|
||||
void __init platform_bus_set_pm_ops(const struct dev_pm_ops *pm)
|
||||
{
|
||||
platform_bus_type.pm = pm;
|
||||
}
|
||||
|
||||
int __init platform_bus_init(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
+4
-4
@@ -432,13 +432,13 @@ int sysdev_suspend(pm_message_t state)
|
||||
/* resume current sysdev */
|
||||
cls_driver:
|
||||
drv = NULL;
|
||||
printk(KERN_ERR "Class suspend failed for %s\n",
|
||||
kobject_name(&sysdev->kobj));
|
||||
printk(KERN_ERR "Class suspend failed for %s: %d\n",
|
||||
kobject_name(&sysdev->kobj), ret);
|
||||
|
||||
aux_driver:
|
||||
if (drv)
|
||||
printk(KERN_ERR "Class driver suspend failed for %s\n",
|
||||
kobject_name(&sysdev->kobj));
|
||||
printk(KERN_ERR "Class driver suspend failed for %s: %d\n",
|
||||
kobject_name(&sysdev->kobj), ret);
|
||||
list_for_each_entry(err_drv, &cls->drivers, entry) {
|
||||
if (err_drv == drv)
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user