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 branch 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
* 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (73 commits) arm: fix up some samsung merge sysdev conversion problems firmware: Fix an oops on reading fw_priv->fw in sysfs loading file Drivers:hv: Fix a bug in vmbus_driver_unregister() driver core: remove __must_check from device_create_file debugfs: add missing #ifdef HAS_IOMEM arm: time.h: remove device.h #include driver-core: remove sysdev.h usage. clockevents: remove sysdev.h arm: convert sysdev_class to a regular subsystem arm: leds: convert sysdev_class to a regular subsystem kobject: remove kset_find_obj_hinted() m86k: gpio - convert sysdev_class to a regular subsystem mips: txx9_sram - convert sysdev_class to a regular subsystem mips: 7segled - convert sysdev_class to a regular subsystem sh: dma - convert sysdev_class to a regular subsystem sh: intc - convert sysdev_class to a regular subsystem power: suspend - convert sysdev_class to a regular subsystem power: qe_ic - convert sysdev_class to a regular subsystem power: cmm - convert sysdev_class to a regular subsystem s390: time - convert sysdev_class to a regular subsystem ... Fix up conflicts with 'struct sysdev' removal from various platform drivers that got changed: - arch/arm/mach-exynos/cpu.c - arch/arm/mach-exynos/irq-eint.c - arch/arm/mach-s3c64xx/common.c - arch/arm/mach-s3c64xx/cpu.c - arch/arm/mach-s5p64x0/cpu.c - arch/arm/mach-s5pv210/common.c - arch/arm/plat-samsung/include/plat/cpu.h - arch/powerpc/kernel/sysfs.c and fix up cpu_is_hotpluggable() as per Greg in include/linux/cpu.h
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
obj-y := core.o sys.o bus.o dd.o syscore.o \
|
||||
driver.o class.o platform.o \
|
||||
cpu.o firmware.o init.o map.o devres.o \
|
||||
attribute_container.o transport_class.o
|
||||
attribute_container.o transport_class.o \
|
||||
topology.o
|
||||
obj-$(CONFIG_DEVTMPFS) += devtmpfs.o
|
||||
obj-y += power/
|
||||
obj-$(CONFIG_HAS_DMA) += dma-mapping.o
|
||||
@@ -12,7 +13,6 @@ obj-$(CONFIG_ISA) += isa.o
|
||||
obj-$(CONFIG_FW_LOADER) += firmware_class.o
|
||||
obj-$(CONFIG_NUMA) += node.o
|
||||
obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
|
||||
obj-$(CONFIG_SMP) += topology.o
|
||||
ifeq ($(CONFIG_SYSFS),y)
|
||||
obj-$(CONFIG_MODULES) += module.o
|
||||
endif
|
||||
|
||||
+6
-6
@@ -4,7 +4,9 @@
|
||||
* struct subsys_private - structure to hold the private to the driver core portions of the bus_type/class structure.
|
||||
*
|
||||
* @subsys - the struct kset that defines this subsystem
|
||||
* @devices_kset - the list of devices associated
|
||||
* @devices_kset - the subsystem's 'devices' directory
|
||||
* @interfaces - list of subsystem interfaces associated
|
||||
* @mutex - protect the devices, and interfaces lists.
|
||||
*
|
||||
* @drivers_kset - the list of drivers associated
|
||||
* @klist_devices - the klist to iterate over the @devices_kset
|
||||
@@ -14,10 +16,8 @@
|
||||
* @bus - pointer back to the struct bus_type that this structure is associated
|
||||
* with.
|
||||
*
|
||||
* @class_interfaces - list of class_interfaces associated
|
||||
* @glue_dirs - "glue" directory to put in-between the parent device to
|
||||
* avoid namespace conflicts
|
||||
* @class_mutex - mutex to protect the children, devices, and interfaces lists.
|
||||
* @class - pointer back to the struct class that this structure is associated
|
||||
* with.
|
||||
*
|
||||
@@ -28,6 +28,8 @@
|
||||
struct subsys_private {
|
||||
struct kset subsys;
|
||||
struct kset *devices_kset;
|
||||
struct list_head interfaces;
|
||||
struct mutex mutex;
|
||||
|
||||
struct kset *drivers_kset;
|
||||
struct klist klist_devices;
|
||||
@@ -36,9 +38,7 @@ struct subsys_private {
|
||||
unsigned int drivers_autoprobe:1;
|
||||
struct bus_type *bus;
|
||||
|
||||
struct list_head class_interfaces;
|
||||
struct kset glue_dirs;
|
||||
struct mutex class_mutex;
|
||||
struct class *class;
|
||||
};
|
||||
#define to_subsys_private(obj) container_of(obj, struct subsys_private, subsys.kobj)
|
||||
@@ -94,7 +94,6 @@ extern int hypervisor_init(void);
|
||||
static inline int hypervisor_init(void) { return 0; }
|
||||
#endif
|
||||
extern int platform_bus_init(void);
|
||||
extern int system_bus_init(void);
|
||||
extern int cpu_dev_init(void);
|
||||
|
||||
extern int bus_add_device(struct device *dev);
|
||||
@@ -116,6 +115,7 @@ extern char *make_class_name(const char *name, struct kobject *kobj);
|
||||
|
||||
extern int devres_release_all(struct device *dev);
|
||||
|
||||
/* /sys/devices directory */
|
||||
extern struct kset *devices_kset;
|
||||
|
||||
#if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS)
|
||||
|
||||
+273
-18
@@ -16,9 +16,14 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mutex.h>
|
||||
#include "base.h"
|
||||
#include "power/power.h"
|
||||
|
||||
/* /sys/devices/system */
|
||||
/* FIXME: make static after drivers/base/sys.c is deleted */
|
||||
struct kset *system_kset;
|
||||
|
||||
#define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
|
||||
|
||||
/*
|
||||
@@ -360,6 +365,47 @@ struct device *bus_find_device_by_name(struct bus_type *bus,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bus_find_device_by_name);
|
||||
|
||||
/**
|
||||
* subsys_find_device_by_id - find a device with a specific enumeration number
|
||||
* @subsys: subsystem
|
||||
* @id: index 'id' in struct device
|
||||
* @hint: device to check first
|
||||
*
|
||||
* Check the hint's next object and if it is a match return it directly,
|
||||
* otherwise, fall back to a full list search. Either way a reference for
|
||||
* the returned object is taken.
|
||||
*/
|
||||
struct device *subsys_find_device_by_id(struct bus_type *subsys, unsigned int id,
|
||||
struct device *hint)
|
||||
{
|
||||
struct klist_iter i;
|
||||
struct device *dev;
|
||||
|
||||
if (!subsys)
|
||||
return NULL;
|
||||
|
||||
if (hint) {
|
||||
klist_iter_init_node(&subsys->p->klist_devices, &i, &hint->p->knode_bus);
|
||||
dev = next_device(&i);
|
||||
if (dev && dev->id == id && get_device(dev)) {
|
||||
klist_iter_exit(&i);
|
||||
return dev;
|
||||
}
|
||||
klist_iter_exit(&i);
|
||||
}
|
||||
|
||||
klist_iter_init_node(&subsys->p->klist_devices, &i, NULL);
|
||||
while ((dev = next_device(&i))) {
|
||||
if (dev->id == id && get_device(dev)) {
|
||||
klist_iter_exit(&i);
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
klist_iter_exit(&i);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(subsys_find_device_by_id);
|
||||
|
||||
static struct device_driver *next_driver(struct klist_iter *i)
|
||||
{
|
||||
struct klist_node *n = klist_next(i);
|
||||
@@ -487,38 +533,59 @@ out_put:
|
||||
void bus_probe_device(struct device *dev)
|
||||
{
|
||||
struct bus_type *bus = dev->bus;
|
||||
struct subsys_interface *sif;
|
||||
int ret;
|
||||
|
||||
if (bus && bus->p->drivers_autoprobe) {
|
||||
if (!bus)
|
||||
return;
|
||||
|
||||
if (bus->p->drivers_autoprobe) {
|
||||
ret = device_attach(dev);
|
||||
WARN_ON(ret < 0);
|
||||
}
|
||||
|
||||
mutex_lock(&bus->p->mutex);
|
||||
list_for_each_entry(sif, &bus->p->interfaces, node)
|
||||
if (sif->add_dev)
|
||||
sif->add_dev(dev, sif);
|
||||
mutex_unlock(&bus->p->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* bus_remove_device - remove device from bus
|
||||
* @dev: device to be removed
|
||||
*
|
||||
* - Remove symlink from bus's directory.
|
||||
* - Remove device from all interfaces.
|
||||
* - Remove symlink from bus' directory.
|
||||
* - Delete device from bus's list.
|
||||
* - Detach from its driver.
|
||||
* - Drop reference taken in bus_add_device().
|
||||
*/
|
||||
void bus_remove_device(struct device *dev)
|
||||
{
|
||||
if (dev->bus) {
|
||||
sysfs_remove_link(&dev->kobj, "subsystem");
|
||||
sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
|
||||
dev_name(dev));
|
||||
device_remove_attrs(dev->bus, dev);
|
||||
if (klist_node_attached(&dev->p->knode_bus))
|
||||
klist_del(&dev->p->knode_bus);
|
||||
struct bus_type *bus = dev->bus;
|
||||
struct subsys_interface *sif;
|
||||
|
||||
pr_debug("bus: '%s': remove device %s\n",
|
||||
dev->bus->name, dev_name(dev));
|
||||
device_release_driver(dev);
|
||||
bus_put(dev->bus);
|
||||
}
|
||||
if (!bus)
|
||||
return;
|
||||
|
||||
mutex_lock(&bus->p->mutex);
|
||||
list_for_each_entry(sif, &bus->p->interfaces, node)
|
||||
if (sif->remove_dev)
|
||||
sif->remove_dev(dev, sif);
|
||||
mutex_unlock(&bus->p->mutex);
|
||||
|
||||
sysfs_remove_link(&dev->kobj, "subsystem");
|
||||
sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
|
||||
dev_name(dev));
|
||||
device_remove_attrs(dev->bus, dev);
|
||||
if (klist_node_attached(&dev->p->knode_bus))
|
||||
klist_del(&dev->p->knode_bus);
|
||||
|
||||
pr_debug("bus: '%s': remove device %s\n",
|
||||
dev->bus->name, dev_name(dev));
|
||||
device_release_driver(dev);
|
||||
bus_put(dev->bus);
|
||||
}
|
||||
|
||||
static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv)
|
||||
@@ -847,14 +914,14 @@ static ssize_t bus_uevent_store(struct bus_type *bus,
|
||||
static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
|
||||
|
||||
/**
|
||||
* bus_register - register a bus with the system.
|
||||
* __bus_register - register a driver-core subsystem
|
||||
* @bus: bus.
|
||||
*
|
||||
* Once we have that, we registered the bus with the kobject
|
||||
* infrastructure, then register the children subsystems it has:
|
||||
* the devices and drivers that belong to the bus.
|
||||
* the devices and drivers that belong to the subsystem.
|
||||
*/
|
||||
int bus_register(struct bus_type *bus)
|
||||
int __bus_register(struct bus_type *bus, struct lock_class_key *key)
|
||||
{
|
||||
int retval;
|
||||
struct subsys_private *priv;
|
||||
@@ -898,6 +965,8 @@ int bus_register(struct bus_type *bus)
|
||||
goto bus_drivers_fail;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&priv->interfaces);
|
||||
__mutex_init(&priv->mutex, "subsys mutex", key);
|
||||
klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
|
||||
klist_init(&priv->klist_drivers, NULL, NULL);
|
||||
|
||||
@@ -927,7 +996,7 @@ out:
|
||||
bus->p = NULL;
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bus_register);
|
||||
EXPORT_SYMBOL_GPL(__bus_register);
|
||||
|
||||
/**
|
||||
* bus_unregister - remove a bus from the system
|
||||
@@ -939,6 +1008,8 @@ EXPORT_SYMBOL_GPL(bus_register);
|
||||
void bus_unregister(struct bus_type *bus)
|
||||
{
|
||||
pr_debug("bus: '%s': unregistering\n", bus->name);
|
||||
if (bus->dev_root)
|
||||
device_unregister(bus->dev_root);
|
||||
bus_remove_attrs(bus);
|
||||
remove_probe_files(bus);
|
||||
kset_unregister(bus->p->drivers_kset);
|
||||
@@ -1028,10 +1099,194 @@ void bus_sort_breadthfirst(struct bus_type *bus,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bus_sort_breadthfirst);
|
||||
|
||||
/**
|
||||
* subsys_dev_iter_init - initialize subsys device iterator
|
||||
* @iter: subsys iterator to initialize
|
||||
* @subsys: the subsys we wanna iterate over
|
||||
* @start: the device to start iterating from, if any
|
||||
* @type: device_type of the devices to iterate over, NULL for all
|
||||
*
|
||||
* Initialize subsys iterator @iter such that it iterates over devices
|
||||
* of @subsys. If @start is set, the list iteration will start there,
|
||||
* otherwise if it is NULL, the iteration starts at the beginning of
|
||||
* the list.
|
||||
*/
|
||||
void subsys_dev_iter_init(struct subsys_dev_iter *iter, struct bus_type *subsys,
|
||||
struct device *start, const struct device_type *type)
|
||||
{
|
||||
struct klist_node *start_knode = NULL;
|
||||
|
||||
if (start)
|
||||
start_knode = &start->p->knode_bus;
|
||||
klist_iter_init_node(&subsys->p->klist_devices, &iter->ki, start_knode);
|
||||
iter->type = type;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(subsys_dev_iter_init);
|
||||
|
||||
/**
|
||||
* subsys_dev_iter_next - iterate to the next device
|
||||
* @iter: subsys iterator to proceed
|
||||
*
|
||||
* Proceed @iter to the next device and return it. Returns NULL if
|
||||
* iteration is complete.
|
||||
*
|
||||
* The returned device is referenced and won't be released till
|
||||
* iterator is proceed to the next device or exited. The caller is
|
||||
* free to do whatever it wants to do with the device including
|
||||
* calling back into subsys code.
|
||||
*/
|
||||
struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter)
|
||||
{
|
||||
struct klist_node *knode;
|
||||
struct device *dev;
|
||||
|
||||
for (;;) {
|
||||
knode = klist_next(&iter->ki);
|
||||
if (!knode)
|
||||
return NULL;
|
||||
dev = container_of(knode, struct device_private, knode_bus)->device;
|
||||
if (!iter->type || iter->type == dev->type)
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(subsys_dev_iter_next);
|
||||
|
||||
/**
|
||||
* subsys_dev_iter_exit - finish iteration
|
||||
* @iter: subsys iterator to finish
|
||||
*
|
||||
* Finish an iteration. Always call this function after iteration is
|
||||
* complete whether the iteration ran till the end or not.
|
||||
*/
|
||||
void subsys_dev_iter_exit(struct subsys_dev_iter *iter)
|
||||
{
|
||||
klist_iter_exit(&iter->ki);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(subsys_dev_iter_exit);
|
||||
|
||||
int subsys_interface_register(struct subsys_interface *sif)
|
||||
{
|
||||
struct bus_type *subsys;
|
||||
struct subsys_dev_iter iter;
|
||||
struct device *dev;
|
||||
|
||||
if (!sif || !sif->subsys)
|
||||
return -ENODEV;
|
||||
|
||||
subsys = bus_get(sif->subsys);
|
||||
if (!subsys)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&subsys->p->mutex);
|
||||
list_add_tail(&sif->node, &subsys->p->interfaces);
|
||||
if (sif->add_dev) {
|
||||
subsys_dev_iter_init(&iter, subsys, NULL, NULL);
|
||||
while ((dev = subsys_dev_iter_next(&iter)))
|
||||
sif->add_dev(dev, sif);
|
||||
subsys_dev_iter_exit(&iter);
|
||||
}
|
||||
mutex_unlock(&subsys->p->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(subsys_interface_register);
|
||||
|
||||
void subsys_interface_unregister(struct subsys_interface *sif)
|
||||
{
|
||||
struct bus_type *subsys = sif->subsys;
|
||||
struct subsys_dev_iter iter;
|
||||
struct device *dev;
|
||||
|
||||
if (!sif)
|
||||
return;
|
||||
|
||||
mutex_lock(&subsys->p->mutex);
|
||||
list_del_init(&sif->node);
|
||||
if (sif->remove_dev) {
|
||||
subsys_dev_iter_init(&iter, subsys, NULL, NULL);
|
||||
while ((dev = subsys_dev_iter_next(&iter)))
|
||||
sif->remove_dev(dev, sif);
|
||||
subsys_dev_iter_exit(&iter);
|
||||
}
|
||||
mutex_unlock(&subsys->p->mutex);
|
||||
|
||||
bus_put(subsys);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(subsys_interface_unregister);
|
||||
|
||||
static void system_root_device_release(struct device *dev)
|
||||
{
|
||||
kfree(dev);
|
||||
}
|
||||
/**
|
||||
* subsys_system_register - register a subsystem at /sys/devices/system/
|
||||
* @subsys - system subsystem
|
||||
* @groups - default attributes for the root device
|
||||
*
|
||||
* All 'system' subsystems have a /sys/devices/system/<name> root device
|
||||
* with the name of the subsystem. The root device can carry subsystem-
|
||||
* wide attributes. All registered devices are below this single root
|
||||
* device and are named after the subsystem with a simple enumeration
|
||||
* number appended. The registered devices are not explicitely named;
|
||||
* only 'id' in the device needs to be set.
|
||||
*
|
||||
* Do not use this interface for anything new, it exists for compatibility
|
||||
* with bad ideas only. New subsystems should use plain subsystems; and
|
||||
* add the subsystem-wide attributes should be added to the subsystem
|
||||
* directory itself and not some create fake root-device placed in
|
||||
* /sys/devices/system/<name>.
|
||||
*/
|
||||
int subsys_system_register(struct bus_type *subsys,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
struct device *dev;
|
||||
int err;
|
||||
|
||||
err = bus_register(subsys);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
dev = kzalloc(sizeof(struct device), GFP_KERNEL);
|
||||
if (!dev) {
|
||||
err = -ENOMEM;
|
||||
goto err_dev;
|
||||
}
|
||||
|
||||
err = dev_set_name(dev, "%s", subsys->name);
|
||||
if (err < 0)
|
||||
goto err_name;
|
||||
|
||||
dev->kobj.parent = &system_kset->kobj;
|
||||
dev->groups = groups;
|
||||
dev->release = system_root_device_release;
|
||||
|
||||
err = device_register(dev);
|
||||
if (err < 0)
|
||||
goto err_dev_reg;
|
||||
|
||||
subsys->dev_root = dev;
|
||||
return 0;
|
||||
|
||||
err_dev_reg:
|
||||
put_device(dev);
|
||||
dev = NULL;
|
||||
err_name:
|
||||
kfree(dev);
|
||||
err_dev:
|
||||
bus_unregister(subsys);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(subsys_system_register);
|
||||
|
||||
int __init buses_init(void)
|
||||
{
|
||||
bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
|
||||
if (!bus_kset)
|
||||
return -ENOMEM;
|
||||
|
||||
system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj);
|
||||
if (!system_kset)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -184,9 +184,9 @@ int __class_register(struct class *cls, struct lock_class_key *key)
|
||||
if (!cp)
|
||||
return -ENOMEM;
|
||||
klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);
|
||||
INIT_LIST_HEAD(&cp->class_interfaces);
|
||||
INIT_LIST_HEAD(&cp->interfaces);
|
||||
kset_init(&cp->glue_dirs);
|
||||
__mutex_init(&cp->class_mutex, "struct class mutex", key);
|
||||
__mutex_init(&cp->mutex, "subsys mutex", key);
|
||||
error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);
|
||||
if (error) {
|
||||
kfree(cp);
|
||||
@@ -460,15 +460,15 @@ int class_interface_register(struct class_interface *class_intf)
|
||||
if (!parent)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&parent->p->class_mutex);
|
||||
list_add_tail(&class_intf->node, &parent->p->class_interfaces);
|
||||
mutex_lock(&parent->p->mutex);
|
||||
list_add_tail(&class_intf->node, &parent->p->interfaces);
|
||||
if (class_intf->add_dev) {
|
||||
class_dev_iter_init(&iter, parent, NULL, NULL);
|
||||
while ((dev = class_dev_iter_next(&iter)))
|
||||
class_intf->add_dev(dev, class_intf);
|
||||
class_dev_iter_exit(&iter);
|
||||
}
|
||||
mutex_unlock(&parent->p->class_mutex);
|
||||
mutex_unlock(&parent->p->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -482,7 +482,7 @@ void class_interface_unregister(struct class_interface *class_intf)
|
||||
if (!parent)
|
||||
return;
|
||||
|
||||
mutex_lock(&parent->p->class_mutex);
|
||||
mutex_lock(&parent->p->mutex);
|
||||
list_del_init(&class_intf->node);
|
||||
if (class_intf->remove_dev) {
|
||||
class_dev_iter_init(&iter, parent, NULL, NULL);
|
||||
@@ -490,7 +490,7 @@ void class_interface_unregister(struct class_interface *class_intf)
|
||||
class_intf->remove_dev(dev, class_intf);
|
||||
class_dev_iter_exit(&iter);
|
||||
}
|
||||
mutex_unlock(&parent->p->class_mutex);
|
||||
mutex_unlock(&parent->p->mutex);
|
||||
|
||||
class_put(parent);
|
||||
}
|
||||
|
||||
+69
-16
@@ -118,6 +118,56 @@ static const struct sysfs_ops dev_sysfs_ops = {
|
||||
.store = dev_attr_store,
|
||||
};
|
||||
|
||||
#define to_ext_attr(x) container_of(x, struct dev_ext_attribute, attr)
|
||||
|
||||
ssize_t device_store_ulong(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct dev_ext_attribute *ea = to_ext_attr(attr);
|
||||
char *end;
|
||||
unsigned long new = simple_strtoul(buf, &end, 0);
|
||||
if (end == buf)
|
||||
return -EINVAL;
|
||||
*(unsigned long *)(ea->var) = new;
|
||||
/* Always return full write size even if we didn't consume all */
|
||||
return size;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_store_ulong);
|
||||
|
||||
ssize_t device_show_ulong(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct dev_ext_attribute *ea = to_ext_attr(attr);
|
||||
return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_show_ulong);
|
||||
|
||||
ssize_t device_store_int(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct dev_ext_attribute *ea = to_ext_attr(attr);
|
||||
char *end;
|
||||
long new = simple_strtol(buf, &end, 0);
|
||||
if (end == buf || new > INT_MAX || new < INT_MIN)
|
||||
return -EINVAL;
|
||||
*(int *)(ea->var) = new;
|
||||
/* Always return full write size even if we didn't consume all */
|
||||
return size;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_store_int);
|
||||
|
||||
ssize_t device_show_int(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct dev_ext_attribute *ea = to_ext_attr(attr);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_show_int);
|
||||
|
||||
/**
|
||||
* device_release - free device structure.
|
||||
@@ -464,7 +514,7 @@ static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
|
||||
static struct device_attribute devt_attr =
|
||||
__ATTR(dev, S_IRUGO, show_dev, NULL);
|
||||
|
||||
/* kset to create /sys/devices/ */
|
||||
/* /sys/devices/ */
|
||||
struct kset *devices_kset;
|
||||
|
||||
/**
|
||||
@@ -711,6 +761,10 @@ static struct kobject *get_device_parent(struct device *dev,
|
||||
return k;
|
||||
}
|
||||
|
||||
/* subsystems can specify a default root directory for their devices */
|
||||
if (!parent && dev->bus && dev->bus->dev_root)
|
||||
return &dev->bus->dev_root->kobj;
|
||||
|
||||
if (parent)
|
||||
return &parent->kobj;
|
||||
return NULL;
|
||||
@@ -731,14 +785,6 @@ static void cleanup_device_parent(struct device *dev)
|
||||
cleanup_glue_dir(dev, dev->kobj.parent);
|
||||
}
|
||||
|
||||
static void setup_parent(struct device *dev, struct device *parent)
|
||||
{
|
||||
struct kobject *kobj;
|
||||
kobj = get_device_parent(dev, parent);
|
||||
if (kobj)
|
||||
dev->kobj.parent = kobj;
|
||||
}
|
||||
|
||||
static int device_add_class_symlinks(struct device *dev)
|
||||
{
|
||||
int error;
|
||||
@@ -891,6 +937,7 @@ int device_private_init(struct device *dev)
|
||||
int device_add(struct device *dev)
|
||||
{
|
||||
struct device *parent = NULL;
|
||||
struct kobject *kobj;
|
||||
struct class_interface *class_intf;
|
||||
int error = -EINVAL;
|
||||
|
||||
@@ -914,6 +961,10 @@ int device_add(struct device *dev)
|
||||
dev->init_name = NULL;
|
||||
}
|
||||
|
||||
/* subsystems can specify simple device enumeration */
|
||||
if (!dev_name(dev) && dev->bus && dev->bus->dev_name)
|
||||
dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);
|
||||
|
||||
if (!dev_name(dev)) {
|
||||
error = -EINVAL;
|
||||
goto name_error;
|
||||
@@ -922,7 +973,9 @@ int device_add(struct device *dev)
|
||||
pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
|
||||
|
||||
parent = get_device(dev->parent);
|
||||
setup_parent(dev, parent);
|
||||
kobj = get_device_parent(dev, parent);
|
||||
if (kobj)
|
||||
dev->kobj.parent = kobj;
|
||||
|
||||
/* use parent numa_node */
|
||||
if (parent)
|
||||
@@ -982,17 +1035,17 @@ int device_add(struct device *dev)
|
||||
&parent->p->klist_children);
|
||||
|
||||
if (dev->class) {
|
||||
mutex_lock(&dev->class->p->class_mutex);
|
||||
mutex_lock(&dev->class->p->mutex);
|
||||
/* tie the class to the device */
|
||||
klist_add_tail(&dev->knode_class,
|
||||
&dev->class->p->klist_devices);
|
||||
|
||||
/* notify any interfaces that the device is here */
|
||||
list_for_each_entry(class_intf,
|
||||
&dev->class->p->class_interfaces, node)
|
||||
&dev->class->p->interfaces, node)
|
||||
if (class_intf->add_dev)
|
||||
class_intf->add_dev(dev, class_intf);
|
||||
mutex_unlock(&dev->class->p->class_mutex);
|
||||
mutex_unlock(&dev->class->p->mutex);
|
||||
}
|
||||
done:
|
||||
put_device(dev);
|
||||
@@ -1107,15 +1160,15 @@ void device_del(struct device *dev)
|
||||
if (dev->class) {
|
||||
device_remove_class_symlinks(dev);
|
||||
|
||||
mutex_lock(&dev->class->p->class_mutex);
|
||||
mutex_lock(&dev->class->p->mutex);
|
||||
/* notify any interfaces that the device is now gone */
|
||||
list_for_each_entry(class_intf,
|
||||
&dev->class->p->class_interfaces, node)
|
||||
&dev->class->p->interfaces, node)
|
||||
if (class_intf->remove_dev)
|
||||
class_intf->remove_dev(dev, class_intf);
|
||||
/* remove the device from the class list */
|
||||
klist_del(&dev->knode_class);
|
||||
mutex_unlock(&dev->class->p->class_mutex);
|
||||
mutex_unlock(&dev->class->p->mutex);
|
||||
}
|
||||
device_remove_file(dev, &uevent_attr);
|
||||
device_remove_attrs(dev);
|
||||
|
||||
+80
-72
@@ -1,8 +1,7 @@
|
||||
/*
|
||||
* drivers/base/cpu.c - basic CPU class support
|
||||
* CPU subsystem support
|
||||
*/
|
||||
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
@@ -14,40 +13,40 @@
|
||||
|
||||
#include "base.h"
|
||||
|
||||
static struct sysdev_class_attribute *cpu_sysdev_class_attrs[];
|
||||
|
||||
struct sysdev_class cpu_sysdev_class = {
|
||||
struct bus_type cpu_subsys = {
|
||||
.name = "cpu",
|
||||
.attrs = cpu_sysdev_class_attrs,
|
||||
.dev_name = "cpu",
|
||||
};
|
||||
EXPORT_SYMBOL(cpu_sysdev_class);
|
||||
EXPORT_SYMBOL_GPL(cpu_subsys);
|
||||
|
||||
static DEFINE_PER_CPU(struct sys_device *, cpu_sys_devices);
|
||||
static DEFINE_PER_CPU(struct device *, cpu_sys_devices);
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static ssize_t show_online(struct sys_device *dev, struct sysdev_attribute *attr,
|
||||
static ssize_t show_online(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
|
||||
struct cpu *cpu = container_of(dev, struct cpu, dev);
|
||||
|
||||
return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id));
|
||||
return sprintf(buf, "%u\n", !!cpu_online(cpu->dev.id));
|
||||
}
|
||||
|
||||
static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t __ref store_online(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
|
||||
struct cpu *cpu = container_of(dev, struct cpu, dev);
|
||||
ssize_t ret;
|
||||
|
||||
cpu_hotplug_driver_lock();
|
||||
switch (buf[0]) {
|
||||
case '0':
|
||||
ret = cpu_down(cpu->sysdev.id);
|
||||
ret = cpu_down(cpu->dev.id);
|
||||
if (!ret)
|
||||
kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
|
||||
break;
|
||||
case '1':
|
||||
ret = cpu_up(cpu->sysdev.id);
|
||||
ret = cpu_up(cpu->dev.id);
|
||||
if (!ret)
|
||||
kobject_uevent(&dev->kobj, KOBJ_ONLINE);
|
||||
break;
|
||||
@@ -60,44 +59,44 @@ static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribut
|
||||
ret = count;
|
||||
return ret;
|
||||
}
|
||||
static SYSDEV_ATTR(online, 0644, show_online, store_online);
|
||||
static DEVICE_ATTR(online, 0644, show_online, store_online);
|
||||
|
||||
static void __cpuinit register_cpu_control(struct cpu *cpu)
|
||||
{
|
||||
sysdev_create_file(&cpu->sysdev, &attr_online);
|
||||
device_create_file(&cpu->dev, &dev_attr_online);
|
||||
}
|
||||
void unregister_cpu(struct cpu *cpu)
|
||||
{
|
||||
int logical_cpu = cpu->sysdev.id;
|
||||
int logical_cpu = cpu->dev.id;
|
||||
|
||||
unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu));
|
||||
|
||||
sysdev_remove_file(&cpu->sysdev, &attr_online);
|
||||
device_remove_file(&cpu->dev, &dev_attr_online);
|
||||
|
||||
sysdev_unregister(&cpu->sysdev);
|
||||
device_unregister(&cpu->dev);
|
||||
per_cpu(cpu_sys_devices, logical_cpu) = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
|
||||
static ssize_t cpu_probe_store(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *attr,
|
||||
static ssize_t cpu_probe_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
return arch_cpu_probe(buf, count);
|
||||
}
|
||||
|
||||
static ssize_t cpu_release_store(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *attr,
|
||||
static ssize_t cpu_release_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
return arch_cpu_release(buf, count);
|
||||
}
|
||||
|
||||
static SYSDEV_CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
|
||||
static SYSDEV_CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store);
|
||||
static DEVICE_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
|
||||
static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store);
|
||||
#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
|
||||
|
||||
#else /* ... !CONFIG_HOTPLUG_CPU */
|
||||
@@ -109,15 +108,15 @@ static inline void register_cpu_control(struct cpu *cpu)
|
||||
#ifdef CONFIG_KEXEC
|
||||
#include <linux/kexec.h>
|
||||
|
||||
static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute *attr,
|
||||
static ssize_t show_crash_notes(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
|
||||
struct cpu *cpu = container_of(dev, struct cpu, dev);
|
||||
ssize_t rc;
|
||||
unsigned long long addr;
|
||||
int cpunum;
|
||||
|
||||
cpunum = cpu->sysdev.id;
|
||||
cpunum = cpu->dev.id;
|
||||
|
||||
/*
|
||||
* Might be reading other cpu's data based on which cpu read thread
|
||||
@@ -129,7 +128,7 @@ static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute
|
||||
rc = sprintf(buf, "%Lx\n", addr);
|
||||
return rc;
|
||||
}
|
||||
static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
|
||||
static DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -137,12 +136,12 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
|
||||
*/
|
||||
|
||||
struct cpu_attr {
|
||||
struct sysdev_class_attribute attr;
|
||||
struct device_attribute attr;
|
||||
const struct cpumask *const * const map;
|
||||
};
|
||||
|
||||
static ssize_t show_cpus_attr(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *attr,
|
||||
static ssize_t show_cpus_attr(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr);
|
||||
@@ -153,10 +152,10 @@ static ssize_t show_cpus_attr(struct sysdev_class *class,
|
||||
return n;
|
||||
}
|
||||
|
||||
#define _CPU_ATTR(name, map) \
|
||||
{ _SYSDEV_CLASS_ATTR(name, 0444, show_cpus_attr, NULL), map }
|
||||
#define _CPU_ATTR(name, map) \
|
||||
{ __ATTR(name, 0444, show_cpus_attr, NULL), map }
|
||||
|
||||
/* Keep in sync with cpu_sysdev_class_attrs */
|
||||
/* Keep in sync with cpu_subsys_attrs */
|
||||
static struct cpu_attr cpu_attrs[] = {
|
||||
_CPU_ATTR(online, &cpu_online_mask),
|
||||
_CPU_ATTR(possible, &cpu_possible_mask),
|
||||
@@ -166,19 +165,19 @@ static struct cpu_attr cpu_attrs[] = {
|
||||
/*
|
||||
* Print values for NR_CPUS and offlined cpus
|
||||
*/
|
||||
static ssize_t print_cpus_kernel_max(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *attr, char *buf)
|
||||
static ssize_t print_cpus_kernel_max(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1);
|
||||
return n;
|
||||
}
|
||||
static SYSDEV_CLASS_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL);
|
||||
static DEVICE_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL);
|
||||
|
||||
/* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */
|
||||
unsigned int total_cpus;
|
||||
|
||||
static ssize_t print_cpus_offline(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *attr, char *buf)
|
||||
static ssize_t print_cpus_offline(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int n = 0, len = PAGE_SIZE-2;
|
||||
cpumask_var_t offline;
|
||||
@@ -205,7 +204,7 @@ static ssize_t print_cpus_offline(struct sysdev_class *class,
|
||||
n += snprintf(&buf[n], len - n, "\n");
|
||||
return n;
|
||||
}
|
||||
static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL);
|
||||
static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL);
|
||||
|
||||
/*
|
||||
* register_cpu - Setup a sysfs device for a CPU.
|
||||
@@ -218,39 +217,60 @@ static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL);
|
||||
int __cpuinit register_cpu(struct cpu *cpu, int num)
|
||||
{
|
||||
int error;
|
||||
|
||||
cpu->node_id = cpu_to_node(num);
|
||||
cpu->sysdev.id = num;
|
||||
cpu->sysdev.cls = &cpu_sysdev_class;
|
||||
|
||||
error = sysdev_register(&cpu->sysdev);
|
||||
|
||||
cpu->dev.id = num;
|
||||
cpu->dev.bus = &cpu_subsys;
|
||||
error = device_register(&cpu->dev);
|
||||
if (!error && cpu->hotpluggable)
|
||||
register_cpu_control(cpu);
|
||||
if (!error)
|
||||
per_cpu(cpu_sys_devices, num) = &cpu->sysdev;
|
||||
per_cpu(cpu_sys_devices, num) = &cpu->dev;
|
||||
if (!error)
|
||||
register_cpu_under_node(num, cpu_to_node(num));
|
||||
|
||||
#ifdef CONFIG_KEXEC
|
||||
if (!error)
|
||||
error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes);
|
||||
error = device_create_file(&cpu->dev, &dev_attr_crash_notes);
|
||||
#endif
|
||||
return error;
|
||||
}
|
||||
|
||||
struct sys_device *get_cpu_sysdev(unsigned cpu)
|
||||
struct device *get_cpu_device(unsigned cpu)
|
||||
{
|
||||
if (cpu < nr_cpu_ids && cpu_possible(cpu))
|
||||
return per_cpu(cpu_sys_devices, cpu);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(get_cpu_sysdev);
|
||||
EXPORT_SYMBOL_GPL(get_cpu_device);
|
||||
|
||||
static struct attribute *cpu_root_attrs[] = {
|
||||
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
|
||||
&dev_attr_probe.attr,
|
||||
&dev_attr_release.attr,
|
||||
#endif
|
||||
&cpu_attrs[0].attr.attr,
|
||||
&cpu_attrs[1].attr.attr,
|
||||
&cpu_attrs[2].attr.attr,
|
||||
&dev_attr_kernel_max.attr,
|
||||
&dev_attr_offline.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group cpu_root_attr_group = {
|
||||
.attrs = cpu_root_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *cpu_root_attr_groups[] = {
|
||||
&cpu_root_attr_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
bool cpu_is_hotpluggable(unsigned cpu)
|
||||
{
|
||||
struct sys_device *dev = get_cpu_sysdev(cpu);
|
||||
return dev && container_of(dev, struct cpu, sysdev)->hotpluggable;
|
||||
struct device *dev = get_cpu_device(cpu);
|
||||
return dev && container_of(dev, struct cpu, dev)->hotpluggable;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpu_is_hotpluggable);
|
||||
|
||||
@@ -258,24 +278,12 @@ int __init cpu_dev_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = sysdev_class_register(&cpu_sysdev_class);
|
||||
#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
|
||||
if (!err)
|
||||
err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class);
|
||||
#endif
|
||||
err = subsys_system_register(&cpu_subsys, cpu_root_attr_groups);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
|
||||
err = sched_create_sysfs_power_savings_entries(cpu_subsys.dev_root);
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct sysdev_class_attribute *cpu_sysdev_class_attrs[] = {
|
||||
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
|
||||
&attr_probe,
|
||||
&attr_release,
|
||||
#endif
|
||||
&cpu_attrs[0].attr,
|
||||
&cpu_attrs[1].attr,
|
||||
&cpu_attrs[2].attr,
|
||||
&attr_kernel_max,
|
||||
&attr_offline,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -413,10 +413,9 @@ static int devtmpfsd(void *p)
|
||||
}
|
||||
spin_lock(&req_lock);
|
||||
}
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
__set_current_state(TASK_INTERRUPTIBLE);
|
||||
spin_unlock(&req_lock);
|
||||
schedule();
|
||||
__set_current_state(TASK_RUNNING);
|
||||
}
|
||||
return 0;
|
||||
out:
|
||||
|
||||
@@ -226,13 +226,13 @@ static ssize_t firmware_loading_store(struct device *dev,
|
||||
int loading = simple_strtol(buf, NULL, 10);
|
||||
int i;
|
||||
|
||||
mutex_lock(&fw_lock);
|
||||
|
||||
if (!fw_priv->fw)
|
||||
goto out;
|
||||
|
||||
switch (loading) {
|
||||
case 1:
|
||||
mutex_lock(&fw_lock);
|
||||
if (!fw_priv->fw) {
|
||||
mutex_unlock(&fw_lock);
|
||||
break;
|
||||
}
|
||||
firmware_free_data(fw_priv->fw);
|
||||
memset(fw_priv->fw, 0, sizeof(struct firmware));
|
||||
/* If the pages are not owned by 'struct firmware' */
|
||||
@@ -243,7 +243,6 @@ static ssize_t firmware_loading_store(struct device *dev,
|
||||
fw_priv->page_array_size = 0;
|
||||
fw_priv->nr_pages = 0;
|
||||
set_bit(FW_STATUS_LOADING, &fw_priv->status);
|
||||
mutex_unlock(&fw_lock);
|
||||
break;
|
||||
case 0:
|
||||
if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) {
|
||||
@@ -274,7 +273,8 @@ static ssize_t firmware_loading_store(struct device *dev,
|
||||
fw_load_abort(fw_priv);
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&fw_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ void __init driver_init(void)
|
||||
* core core pieces.
|
||||
*/
|
||||
platform_bus_init();
|
||||
system_bus_init();
|
||||
cpu_dev_init();
|
||||
memory_dev_init();
|
||||
}
|
||||
|
||||
+66
-94
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* drivers/base/memory.c - basic Memory class support
|
||||
* Memory subsystem support
|
||||
*
|
||||
* Written by Matt Tolentino <matthew.e.tolentino@intel.com>
|
||||
* Dave Hansen <haveblue@us.ibm.com>
|
||||
@@ -10,7 +10,6 @@
|
||||
* SPARSEMEM should be contained here, or in mm/memory_hotplug.c.
|
||||
*/
|
||||
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/topology.h>
|
||||
@@ -38,26 +37,9 @@ static inline int base_memory_block_id(int section_nr)
|
||||
return section_nr / sections_per_block;
|
||||
}
|
||||
|
||||
static struct sysdev_class memory_sysdev_class = {
|
||||
static struct bus_type memory_subsys = {
|
||||
.name = MEMORY_CLASS_NAME,
|
||||
};
|
||||
|
||||
static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj)
|
||||
{
|
||||
return MEMORY_CLASS_NAME;
|
||||
}
|
||||
|
||||
static int memory_uevent(struct kset *kset, struct kobject *obj,
|
||||
struct kobj_uevent_env *env)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static const struct kset_uevent_ops memory_uevent_ops = {
|
||||
.name = memory_uevent_name,
|
||||
.uevent = memory_uevent,
|
||||
.dev_name = MEMORY_CLASS_NAME,
|
||||
};
|
||||
|
||||
static BLOCKING_NOTIFIER_HEAD(memory_chain);
|
||||
@@ -96,21 +78,21 @@ int register_memory(struct memory_block *memory)
|
||||
{
|
||||
int error;
|
||||
|
||||
memory->sysdev.cls = &memory_sysdev_class;
|
||||
memory->sysdev.id = memory->start_section_nr / sections_per_block;
|
||||
memory->dev.bus = &memory_subsys;
|
||||
memory->dev.id = memory->start_section_nr / sections_per_block;
|
||||
|
||||
error = sysdev_register(&memory->sysdev);
|
||||
error = device_register(&memory->dev);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
unregister_memory(struct memory_block *memory)
|
||||
{
|
||||
BUG_ON(memory->sysdev.cls != &memory_sysdev_class);
|
||||
BUG_ON(memory->dev.bus != &memory_subsys);
|
||||
|
||||
/* drop the ref. we got in remove_memory_block() */
|
||||
kobject_put(&memory->sysdev.kobj);
|
||||
sysdev_unregister(&memory->sysdev);
|
||||
kobject_put(&memory->dev.kobj);
|
||||
device_unregister(&memory->dev);
|
||||
}
|
||||
|
||||
unsigned long __weak memory_block_size_bytes(void)
|
||||
@@ -138,22 +120,22 @@ static unsigned long get_memory_block_size(void)
|
||||
* uses.
|
||||
*/
|
||||
|
||||
static ssize_t show_mem_start_phys_index(struct sys_device *dev,
|
||||
struct sysdev_attribute *attr, char *buf)
|
||||
static ssize_t show_mem_start_phys_index(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct memory_block *mem =
|
||||
container_of(dev, struct memory_block, sysdev);
|
||||
container_of(dev, struct memory_block, dev);
|
||||
unsigned long phys_index;
|
||||
|
||||
phys_index = mem->start_section_nr / sections_per_block;
|
||||
return sprintf(buf, "%08lx\n", phys_index);
|
||||
}
|
||||
|
||||
static ssize_t show_mem_end_phys_index(struct sys_device *dev,
|
||||
struct sysdev_attribute *attr, char *buf)
|
||||
static ssize_t show_mem_end_phys_index(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct memory_block *mem =
|
||||
container_of(dev, struct memory_block, sysdev);
|
||||
container_of(dev, struct memory_block, dev);
|
||||
unsigned long phys_index;
|
||||
|
||||
phys_index = mem->end_section_nr / sections_per_block;
|
||||
@@ -163,13 +145,13 @@ static ssize_t show_mem_end_phys_index(struct sys_device *dev,
|
||||
/*
|
||||
* Show whether the section of memory is likely to be hot-removable
|
||||
*/
|
||||
static ssize_t show_mem_removable(struct sys_device *dev,
|
||||
struct sysdev_attribute *attr, char *buf)
|
||||
static ssize_t show_mem_removable(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
unsigned long i, pfn;
|
||||
int ret = 1;
|
||||
struct memory_block *mem =
|
||||
container_of(dev, struct memory_block, sysdev);
|
||||
container_of(dev, struct memory_block, dev);
|
||||
|
||||
for (i = 0; i < sections_per_block; i++) {
|
||||
pfn = section_nr_to_pfn(mem->start_section_nr + i);
|
||||
@@ -182,11 +164,11 @@ static ssize_t show_mem_removable(struct sys_device *dev,
|
||||
/*
|
||||
* online, offline, going offline, etc.
|
||||
*/
|
||||
static ssize_t show_mem_state(struct sys_device *dev,
|
||||
struct sysdev_attribute *attr, char *buf)
|
||||
static ssize_t show_mem_state(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct memory_block *mem =
|
||||
container_of(dev, struct memory_block, sysdev);
|
||||
container_of(dev, struct memory_block, dev);
|
||||
ssize_t len = 0;
|
||||
|
||||
/*
|
||||
@@ -324,13 +306,13 @@ out:
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
store_mem_state(struct sys_device *dev,
|
||||
struct sysdev_attribute *attr, const char *buf, size_t count)
|
||||
store_mem_state(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct memory_block *mem;
|
||||
int ret = -EINVAL;
|
||||
|
||||
mem = container_of(dev, struct memory_block, sysdev);
|
||||
mem = container_of(dev, struct memory_block, dev);
|
||||
|
||||
if (!strncmp(buf, "online", min((int)count, 6)))
|
||||
ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
|
||||
@@ -351,41 +333,41 @@ store_mem_state(struct sys_device *dev,
|
||||
* s.t. if I offline all of these sections I can then
|
||||
* remove the physical device?
|
||||
*/
|
||||
static ssize_t show_phys_device(struct sys_device *dev,
|
||||
struct sysdev_attribute *attr, char *buf)
|
||||
static ssize_t show_phys_device(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct memory_block *mem =
|
||||
container_of(dev, struct memory_block, sysdev);
|
||||
container_of(dev, struct memory_block, dev);
|
||||
return sprintf(buf, "%d\n", mem->phys_device);
|
||||
}
|
||||
|
||||
static SYSDEV_ATTR(phys_index, 0444, show_mem_start_phys_index, NULL);
|
||||
static SYSDEV_ATTR(end_phys_index, 0444, show_mem_end_phys_index, NULL);
|
||||
static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state);
|
||||
static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL);
|
||||
static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);
|
||||
static DEVICE_ATTR(phys_index, 0444, show_mem_start_phys_index, NULL);
|
||||
static DEVICE_ATTR(end_phys_index, 0444, show_mem_end_phys_index, NULL);
|
||||
static DEVICE_ATTR(state, 0644, show_mem_state, store_mem_state);
|
||||
static DEVICE_ATTR(phys_device, 0444, show_phys_device, NULL);
|
||||
static DEVICE_ATTR(removable, 0444, show_mem_removable, NULL);
|
||||
|
||||
#define mem_create_simple_file(mem, attr_name) \
|
||||
sysdev_create_file(&mem->sysdev, &attr_##attr_name)
|
||||
device_create_file(&mem->dev, &dev_attr_##attr_name)
|
||||
#define mem_remove_simple_file(mem, attr_name) \
|
||||
sysdev_remove_file(&mem->sysdev, &attr_##attr_name)
|
||||
device_remove_file(&mem->dev, &dev_attr_##attr_name)
|
||||
|
||||
/*
|
||||
* Block size attribute stuff
|
||||
*/
|
||||
static ssize_t
|
||||
print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr,
|
||||
print_block_size(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%lx\n", get_memory_block_size());
|
||||
}
|
||||
|
||||
static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
|
||||
static DEVICE_ATTR(block_size_bytes, 0444, print_block_size, NULL);
|
||||
|
||||
static int block_size_init(void)
|
||||
{
|
||||
return sysfs_create_file(&memory_sysdev_class.kset.kobj,
|
||||
&attr_block_size_bytes.attr);
|
||||
return device_create_file(memory_subsys.dev_root,
|
||||
&dev_attr_block_size_bytes);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -396,7 +378,7 @@ static int block_size_init(void)
|
||||
*/
|
||||
#ifdef CONFIG_ARCH_MEMORY_PROBE
|
||||
static ssize_t
|
||||
memory_probe_store(struct class *class, struct class_attribute *attr,
|
||||
memory_probe_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
u64 phys_addr;
|
||||
@@ -423,12 +405,11 @@ memory_probe_store(struct class *class, struct class_attribute *attr,
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
static CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store);
|
||||
static DEVICE_ATTR(probe, S_IWUSR, NULL, memory_probe_store);
|
||||
|
||||
static int memory_probe_init(void)
|
||||
{
|
||||
return sysfs_create_file(&memory_sysdev_class.kset.kobj,
|
||||
&class_attr_probe.attr);
|
||||
return device_create_file(memory_subsys.dev_root, &dev_attr_probe);
|
||||
}
|
||||
#else
|
||||
static inline int memory_probe_init(void)
|
||||
@@ -444,8 +425,8 @@ static inline int memory_probe_init(void)
|
||||
|
||||
/* Soft offline a page */
|
||||
static ssize_t
|
||||
store_soft_offline_page(struct class *class,
|
||||
struct class_attribute *attr,
|
||||
store_soft_offline_page(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
@@ -463,8 +444,8 @@ store_soft_offline_page(struct class *class,
|
||||
|
||||
/* Forcibly offline a page, including killing processes. */
|
||||
static ssize_t
|
||||
store_hard_offline_page(struct class *class,
|
||||
struct class_attribute *attr,
|
||||
store_hard_offline_page(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
@@ -478,18 +459,18 @@ store_hard_offline_page(struct class *class,
|
||||
return ret ? ret : count;
|
||||
}
|
||||
|
||||
static CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page);
|
||||
static CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page);
|
||||
static DEVICE_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page);
|
||||
static DEVICE_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page);
|
||||
|
||||
static __init int memory_fail_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = sysfs_create_file(&memory_sysdev_class.kset.kobj,
|
||||
&class_attr_soft_offline_page.attr);
|
||||
err = device_create_file(memory_subsys.dev_root,
|
||||
&dev_attr_soft_offline_page);
|
||||
if (!err)
|
||||
err = sysfs_create_file(&memory_sysdev_class.kset.kobj,
|
||||
&class_attr_hard_offline_page.attr);
|
||||
err = device_create_file(memory_subsys.dev_root,
|
||||
&dev_attr_hard_offline_page);
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
@@ -509,31 +490,23 @@ int __weak arch_get_memory_phys_device(unsigned long start_pfn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* A reference for the returned object is held and the reference for the
|
||||
* hinted object is released.
|
||||
*/
|
||||
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];
|
||||
int block_id = base_memory_block_id(__section_nr(section));
|
||||
struct device *hintdev = hint ? &hint->dev : NULL;
|
||||
struct device *dev;
|
||||
|
||||
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, block_id);
|
||||
|
||||
kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj);
|
||||
if (!kobj)
|
||||
dev = subsys_find_device_by_id(&memory_subsys, block_id, hintdev);
|
||||
if (hint)
|
||||
put_device(&hint->dev);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
sysdev = container_of(kobj, struct sys_device, kobj);
|
||||
mem = container_of(sysdev, struct memory_block, sysdev);
|
||||
|
||||
return mem;
|
||||
return container_of(dev, struct memory_block, dev);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -542,7 +515,7 @@ struct memory_block *find_memory_block_hinted(struct mem_section *section,
|
||||
* 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.
|
||||
* This could be made generic for all device subsystems.
|
||||
*/
|
||||
struct memory_block *find_memory_block(struct mem_section *section)
|
||||
{
|
||||
@@ -598,7 +571,7 @@ static int add_memory_section(int nid, struct mem_section *section,
|
||||
mem = find_memory_block(section);
|
||||
if (mem) {
|
||||
mem->section_count++;
|
||||
kobject_put(&mem->sysdev.kobj);
|
||||
kobject_put(&mem->dev.kobj);
|
||||
} else
|
||||
ret = init_memory_block(&mem, section, state);
|
||||
|
||||
@@ -631,7 +604,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
|
||||
unregister_memory(mem);
|
||||
kfree(mem);
|
||||
} else
|
||||
kobject_put(&mem->sysdev.kobj);
|
||||
kobject_put(&mem->dev.kobj);
|
||||
|
||||
mutex_unlock(&mem_sysfs_mutex);
|
||||
return 0;
|
||||
@@ -664,8 +637,7 @@ int __init memory_dev_init(void)
|
||||
int err;
|
||||
unsigned long block_sz;
|
||||
|
||||
memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops;
|
||||
ret = sysdev_class_register(&memory_sysdev_class);
|
||||
ret = subsys_system_register(&memory_subsys, NULL);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
||||
+80
-74
@@ -1,8 +1,7 @@
|
||||
/*
|
||||
* drivers/base/node.c - basic Node class support
|
||||
* Basic Node interface support
|
||||
*/
|
||||
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
@@ -19,18 +18,16 @@
|
||||
#include <linux/swap.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
static struct sysdev_class_attribute *node_state_attrs[];
|
||||
|
||||
static struct sysdev_class node_class = {
|
||||
static struct bus_type node_subsys = {
|
||||
.name = "node",
|
||||
.attrs = node_state_attrs,
|
||||
.dev_name = "node",
|
||||
};
|
||||
|
||||
|
||||
static ssize_t node_read_cpumap(struct sys_device *dev, int type, char *buf)
|
||||
static ssize_t node_read_cpumap(struct device *dev, int type, char *buf)
|
||||
{
|
||||
struct node *node_dev = to_node(dev);
|
||||
const struct cpumask *mask = cpumask_of_node(node_dev->sysdev.id);
|
||||
const struct cpumask *mask = cpumask_of_node(node_dev->dev.id);
|
||||
int len;
|
||||
|
||||
/* 2008/04/07: buf currently PAGE_SIZE, need 9 chars per 32 bits. */
|
||||
@@ -44,23 +41,23 @@ static ssize_t node_read_cpumap(struct sys_device *dev, int type, char *buf)
|
||||
return len;
|
||||
}
|
||||
|
||||
static inline ssize_t node_read_cpumask(struct sys_device *dev,
|
||||
struct sysdev_attribute *attr, char *buf)
|
||||
static inline ssize_t node_read_cpumask(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return node_read_cpumap(dev, 0, buf);
|
||||
}
|
||||
static inline ssize_t node_read_cpulist(struct sys_device *dev,
|
||||
struct sysdev_attribute *attr, char *buf)
|
||||
static inline ssize_t node_read_cpulist(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return node_read_cpumap(dev, 1, buf);
|
||||
}
|
||||
|
||||
static SYSDEV_ATTR(cpumap, S_IRUGO, node_read_cpumask, NULL);
|
||||
static SYSDEV_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL);
|
||||
static DEVICE_ATTR(cpumap, S_IRUGO, node_read_cpumask, NULL);
|
||||
static DEVICE_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL);
|
||||
|
||||
#define K(x) ((x) << (PAGE_SHIFT - 10))
|
||||
static ssize_t node_read_meminfo(struct sys_device * dev,
|
||||
struct sysdev_attribute *attr, char * buf)
|
||||
static ssize_t node_read_meminfo(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int n;
|
||||
int nid = dev->id;
|
||||
@@ -157,10 +154,10 @@ static ssize_t node_read_meminfo(struct sys_device * dev,
|
||||
}
|
||||
|
||||
#undef K
|
||||
static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL);
|
||||
static DEVICE_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL);
|
||||
|
||||
static ssize_t node_read_numastat(struct sys_device * dev,
|
||||
struct sysdev_attribute *attr, char * buf)
|
||||
static ssize_t node_read_numastat(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf,
|
||||
"numa_hit %lu\n"
|
||||
@@ -176,10 +173,10 @@ static ssize_t node_read_numastat(struct sys_device * dev,
|
||||
node_page_state(dev->id, NUMA_LOCAL),
|
||||
node_page_state(dev->id, NUMA_OTHER));
|
||||
}
|
||||
static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL);
|
||||
static DEVICE_ATTR(numastat, S_IRUGO, node_read_numastat, NULL);
|
||||
|
||||
static ssize_t node_read_vmstat(struct sys_device *dev,
|
||||
struct sysdev_attribute *attr, char *buf)
|
||||
static ssize_t node_read_vmstat(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int nid = dev->id;
|
||||
int i;
|
||||
@@ -191,10 +188,10 @@ static ssize_t node_read_vmstat(struct sys_device *dev,
|
||||
|
||||
return n;
|
||||
}
|
||||
static SYSDEV_ATTR(vmstat, S_IRUGO, node_read_vmstat, NULL);
|
||||
static DEVICE_ATTR(vmstat, S_IRUGO, node_read_vmstat, NULL);
|
||||
|
||||
static ssize_t node_read_distance(struct sys_device * dev,
|
||||
struct sysdev_attribute *attr, char * buf)
|
||||
static ssize_t node_read_distance(struct device *dev,
|
||||
struct device_attribute *attr, char * buf)
|
||||
{
|
||||
int nid = dev->id;
|
||||
int len = 0;
|
||||
@@ -212,7 +209,7 @@ static ssize_t node_read_distance(struct sys_device * dev,
|
||||
len += sprintf(buf + len, "\n");
|
||||
return len;
|
||||
}
|
||||
static SYSDEV_ATTR(distance, S_IRUGO, node_read_distance, NULL);
|
||||
static DEVICE_ATTR(distance, S_IRUGO, node_read_distance, NULL);
|
||||
|
||||
#ifdef CONFIG_HUGETLBFS
|
||||
/*
|
||||
@@ -230,7 +227,7 @@ static node_registration_func_t __hugetlb_unregister_node;
|
||||
static inline bool hugetlb_register_node(struct node *node)
|
||||
{
|
||||
if (__hugetlb_register_node &&
|
||||
node_state(node->sysdev.id, N_HIGH_MEMORY)) {
|
||||
node_state(node->dev.id, N_HIGH_MEMORY)) {
|
||||
__hugetlb_register_node(node);
|
||||
return true;
|
||||
}
|
||||
@@ -266,17 +263,17 @@ int register_node(struct node *node, int num, struct node *parent)
|
||||
{
|
||||
int error;
|
||||
|
||||
node->sysdev.id = num;
|
||||
node->sysdev.cls = &node_class;
|
||||
error = sysdev_register(&node->sysdev);
|
||||
node->dev.id = num;
|
||||
node->dev.bus = &node_subsys;
|
||||
error = device_register(&node->dev);
|
||||
|
||||
if (!error){
|
||||
sysdev_create_file(&node->sysdev, &attr_cpumap);
|
||||
sysdev_create_file(&node->sysdev, &attr_cpulist);
|
||||
sysdev_create_file(&node->sysdev, &attr_meminfo);
|
||||
sysdev_create_file(&node->sysdev, &attr_numastat);
|
||||
sysdev_create_file(&node->sysdev, &attr_distance);
|
||||
sysdev_create_file(&node->sysdev, &attr_vmstat);
|
||||
device_create_file(&node->dev, &dev_attr_cpumap);
|
||||
device_create_file(&node->dev, &dev_attr_cpulist);
|
||||
device_create_file(&node->dev, &dev_attr_meminfo);
|
||||
device_create_file(&node->dev, &dev_attr_numastat);
|
||||
device_create_file(&node->dev, &dev_attr_distance);
|
||||
device_create_file(&node->dev, &dev_attr_vmstat);
|
||||
|
||||
scan_unevictable_register_node(node);
|
||||
|
||||
@@ -296,17 +293,17 @@ int register_node(struct node *node, int num, struct node *parent)
|
||||
*/
|
||||
void unregister_node(struct node *node)
|
||||
{
|
||||
sysdev_remove_file(&node->sysdev, &attr_cpumap);
|
||||
sysdev_remove_file(&node->sysdev, &attr_cpulist);
|
||||
sysdev_remove_file(&node->sysdev, &attr_meminfo);
|
||||
sysdev_remove_file(&node->sysdev, &attr_numastat);
|
||||
sysdev_remove_file(&node->sysdev, &attr_distance);
|
||||
sysdev_remove_file(&node->sysdev, &attr_vmstat);
|
||||
device_remove_file(&node->dev, &dev_attr_cpumap);
|
||||
device_remove_file(&node->dev, &dev_attr_cpulist);
|
||||
device_remove_file(&node->dev, &dev_attr_meminfo);
|
||||
device_remove_file(&node->dev, &dev_attr_numastat);
|
||||
device_remove_file(&node->dev, &dev_attr_distance);
|
||||
device_remove_file(&node->dev, &dev_attr_vmstat);
|
||||
|
||||
scan_unevictable_unregister_node(node);
|
||||
hugetlb_unregister_node(node); /* no-op, if memoryless node */
|
||||
|
||||
sysdev_unregister(&node->sysdev);
|
||||
device_unregister(&node->dev);
|
||||
}
|
||||
|
||||
struct node node_devices[MAX_NUMNODES];
|
||||
@@ -317,41 +314,41 @@ struct node node_devices[MAX_NUMNODES];
|
||||
int register_cpu_under_node(unsigned int cpu, unsigned int nid)
|
||||
{
|
||||
int ret;
|
||||
struct sys_device *obj;
|
||||
struct device *obj;
|
||||
|
||||
if (!node_online(nid))
|
||||
return 0;
|
||||
|
||||
obj = get_cpu_sysdev(cpu);
|
||||
obj = get_cpu_device(cpu);
|
||||
if (!obj)
|
||||
return 0;
|
||||
|
||||
ret = sysfs_create_link(&node_devices[nid].sysdev.kobj,
|
||||
ret = sysfs_create_link(&node_devices[nid].dev.kobj,
|
||||
&obj->kobj,
|
||||
kobject_name(&obj->kobj));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sysfs_create_link(&obj->kobj,
|
||||
&node_devices[nid].sysdev.kobj,
|
||||
kobject_name(&node_devices[nid].sysdev.kobj));
|
||||
&node_devices[nid].dev.kobj,
|
||||
kobject_name(&node_devices[nid].dev.kobj));
|
||||
}
|
||||
|
||||
int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
|
||||
{
|
||||
struct sys_device *obj;
|
||||
struct device *obj;
|
||||
|
||||
if (!node_online(nid))
|
||||
return 0;
|
||||
|
||||
obj = get_cpu_sysdev(cpu);
|
||||
obj = get_cpu_device(cpu);
|
||||
if (!obj)
|
||||
return 0;
|
||||
|
||||
sysfs_remove_link(&node_devices[nid].sysdev.kobj,
|
||||
sysfs_remove_link(&node_devices[nid].dev.kobj,
|
||||
kobject_name(&obj->kobj));
|
||||
sysfs_remove_link(&obj->kobj,
|
||||
kobject_name(&node_devices[nid].sysdev.kobj));
|
||||
kobject_name(&node_devices[nid].dev.kobj));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -393,15 +390,15 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid)
|
||||
continue;
|
||||
if (page_nid != nid)
|
||||
continue;
|
||||
ret = sysfs_create_link_nowarn(&node_devices[nid].sysdev.kobj,
|
||||
&mem_blk->sysdev.kobj,
|
||||
kobject_name(&mem_blk->sysdev.kobj));
|
||||
ret = sysfs_create_link_nowarn(&node_devices[nid].dev.kobj,
|
||||
&mem_blk->dev.kobj,
|
||||
kobject_name(&mem_blk->dev.kobj));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sysfs_create_link_nowarn(&mem_blk->sysdev.kobj,
|
||||
&node_devices[nid].sysdev.kobj,
|
||||
kobject_name(&node_devices[nid].sysdev.kobj));
|
||||
return sysfs_create_link_nowarn(&mem_blk->dev.kobj,
|
||||
&node_devices[nid].dev.kobj,
|
||||
kobject_name(&node_devices[nid].dev.kobj));
|
||||
}
|
||||
/* mem section does not span the specified node */
|
||||
return 0;
|
||||
@@ -434,10 +431,10 @@ int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
|
||||
continue;
|
||||
if (node_test_and_set(nid, *unlinked_nodes))
|
||||
continue;
|
||||
sysfs_remove_link(&node_devices[nid].sysdev.kobj,
|
||||
kobject_name(&mem_blk->sysdev.kobj));
|
||||
sysfs_remove_link(&mem_blk->sysdev.kobj,
|
||||
kobject_name(&node_devices[nid].sysdev.kobj));
|
||||
sysfs_remove_link(&node_devices[nid].dev.kobj,
|
||||
kobject_name(&mem_blk->dev.kobj));
|
||||
sysfs_remove_link(&mem_blk->dev.kobj,
|
||||
kobject_name(&node_devices[nid].dev.kobj));
|
||||
}
|
||||
NODEMASK_FREE(unlinked_nodes);
|
||||
return 0;
|
||||
@@ -468,7 +465,7 @@ static int link_mem_sections(int nid)
|
||||
}
|
||||
|
||||
if (mem_blk)
|
||||
kobject_put(&mem_blk->sysdev.kobj);
|
||||
kobject_put(&mem_blk->dev.kobj);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -596,19 +593,19 @@ static ssize_t print_nodes_state(enum node_states state, char *buf)
|
||||
}
|
||||
|
||||
struct node_attr {
|
||||
struct sysdev_class_attribute attr;
|
||||
struct device_attribute attr;
|
||||
enum node_states state;
|
||||
};
|
||||
|
||||
static ssize_t show_node_state(struct sysdev_class *class,
|
||||
struct sysdev_class_attribute *attr, char *buf)
|
||||
static ssize_t show_node_state(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct node_attr *na = container_of(attr, struct node_attr, attr);
|
||||
return print_nodes_state(na->state, buf);
|
||||
}
|
||||
|
||||
#define _NODE_ATTR(name, state) \
|
||||
{ _SYSDEV_CLASS_ATTR(name, 0444, show_node_state, NULL), state }
|
||||
{ __ATTR(name, 0444, show_node_state, NULL), state }
|
||||
|
||||
static struct node_attr node_state_attr[] = {
|
||||
_NODE_ATTR(possible, N_POSSIBLE),
|
||||
@@ -620,17 +617,26 @@ static struct node_attr node_state_attr[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct sysdev_class_attribute *node_state_attrs[] = {
|
||||
&node_state_attr[0].attr,
|
||||
&node_state_attr[1].attr,
|
||||
&node_state_attr[2].attr,
|
||||
&node_state_attr[3].attr,
|
||||
static struct attribute *node_state_attrs[] = {
|
||||
&node_state_attr[0].attr.attr,
|
||||
&node_state_attr[1].attr.attr,
|
||||
&node_state_attr[2].attr.attr,
|
||||
&node_state_attr[3].attr.attr,
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
&node_state_attr[4].attr,
|
||||
&node_state_attr[4].attr.attr,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group memory_root_attr_group = {
|
||||
.attrs = node_state_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *cpu_root_attr_groups[] = {
|
||||
&memory_root_attr_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
#define NODE_CALLBACK_PRI 2 /* lower than SLAB */
|
||||
static int __init register_node_type(void)
|
||||
{
|
||||
@@ -639,7 +645,7 @@ static int __init register_node_type(void)
|
||||
BUILD_BUG_ON(ARRAY_SIZE(node_state_attr) != NR_NODE_STATES);
|
||||
BUILD_BUG_ON(ARRAY_SIZE(node_state_attrs)-1 != NR_NODE_STATES);
|
||||
|
||||
ret = sysdev_class_register(&node_class);
|
||||
ret = subsys_system_register(&node_subsys, cpu_root_attr_groups);
|
||||
if (!ret) {
|
||||
hotplug_memory_notifier(node_memory_callback,
|
||||
NODE_CALLBACK_PRI);
|
||||
|
||||
@@ -383,7 +383,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister);
|
||||
* Returns &struct platform_device pointer on success, or ERR_PTR() on error.
|
||||
*/
|
||||
struct platform_device *platform_device_register_full(
|
||||
struct platform_device_info *pdevinfo)
|
||||
const struct platform_device_info *pdevinfo)
|
||||
{
|
||||
int ret = -ENOMEM;
|
||||
struct platform_device *pdev;
|
||||
|
||||
+1
-9
@@ -126,7 +126,7 @@ void sysdev_class_remove_file(struct sysdev_class *c,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysdev_class_remove_file);
|
||||
|
||||
static struct kset *system_kset;
|
||||
extern struct kset *system_kset;
|
||||
|
||||
int sysdev_class_register(struct sysdev_class *cls)
|
||||
{
|
||||
@@ -331,14 +331,6 @@ void sysdev_unregister(struct sys_device *sysdev)
|
||||
EXPORT_SYMBOL_GPL(sysdev_register);
|
||||
EXPORT_SYMBOL_GPL(sysdev_unregister);
|
||||
|
||||
int __init system_bus_init(void)
|
||||
{
|
||||
system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj);
|
||||
if (!system_kset)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr)
|
||||
|
||||
ssize_t sysdev_store_ulong(struct sys_device *sysdev,
|
||||
|
||||
+25
-26
@@ -23,7 +23,6 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/cpu.h>
|
||||
@@ -32,14 +31,14 @@
|
||||
#include <linux/topology.h>
|
||||
|
||||
#define define_one_ro_named(_name, _func) \
|
||||
static SYSDEV_ATTR(_name, 0444, _func, NULL)
|
||||
static DEVICE_ATTR(_name, 0444, _func, NULL)
|
||||
|
||||
#define define_one_ro(_name) \
|
||||
static SYSDEV_ATTR(_name, 0444, show_##_name, NULL)
|
||||
static DEVICE_ATTR(_name, 0444, show_##_name, NULL)
|
||||
|
||||
#define define_id_show_func(name) \
|
||||
static ssize_t show_##name(struct sys_device *dev, \
|
||||
struct sysdev_attribute *attr, char *buf) \
|
||||
static ssize_t show_##name(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
unsigned int cpu = dev->id; \
|
||||
return sprintf(buf, "%d\n", topology_##name(cpu)); \
|
||||
@@ -65,16 +64,16 @@ static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf)
|
||||
|
||||
#ifdef arch_provides_topology_pointers
|
||||
#define define_siblings_show_map(name) \
|
||||
static ssize_t show_##name(struct sys_device *dev, \
|
||||
struct sysdev_attribute *attr, char *buf) \
|
||||
static ssize_t show_##name(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
unsigned int cpu = dev->id; \
|
||||
return show_cpumap(0, topology_##name(cpu), buf); \
|
||||
}
|
||||
|
||||
#define define_siblings_show_list(name) \
|
||||
static ssize_t show_##name##_list(struct sys_device *dev, \
|
||||
struct sysdev_attribute *attr, \
|
||||
static ssize_t show_##name##_list(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
unsigned int cpu = dev->id; \
|
||||
@@ -83,15 +82,15 @@ static ssize_t show_##name##_list(struct sys_device *dev, \
|
||||
|
||||
#else
|
||||
#define define_siblings_show_map(name) \
|
||||
static ssize_t show_##name(struct sys_device *dev, \
|
||||
struct sysdev_attribute *attr, char *buf) \
|
||||
static ssize_t show_##name(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
return show_cpumap(0, topology_##name(dev->id), buf); \
|
||||
}
|
||||
|
||||
#define define_siblings_show_list(name) \
|
||||
static ssize_t show_##name##_list(struct sys_device *dev, \
|
||||
struct sysdev_attribute *attr, \
|
||||
static ssize_t show_##name##_list(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
return show_cpumap(1, topology_##name(dev->id), buf); \
|
||||
@@ -124,16 +123,16 @@ define_one_ro_named(book_siblings_list, show_book_cpumask_list);
|
||||
#endif
|
||||
|
||||
static struct attribute *default_attrs[] = {
|
||||
&attr_physical_package_id.attr,
|
||||
&attr_core_id.attr,
|
||||
&attr_thread_siblings.attr,
|
||||
&attr_thread_siblings_list.attr,
|
||||
&attr_core_siblings.attr,
|
||||
&attr_core_siblings_list.attr,
|
||||
&dev_attr_physical_package_id.attr,
|
||||
&dev_attr_core_id.attr,
|
||||
&dev_attr_thread_siblings.attr,
|
||||
&dev_attr_thread_siblings_list.attr,
|
||||
&dev_attr_core_siblings.attr,
|
||||
&dev_attr_core_siblings_list.attr,
|
||||
#ifdef CONFIG_SCHED_BOOK
|
||||
&attr_book_id.attr,
|
||||
&attr_book_siblings.attr,
|
||||
&attr_book_siblings_list.attr,
|
||||
&dev_attr_book_id.attr,
|
||||
&dev_attr_book_siblings.attr,
|
||||
&dev_attr_book_siblings_list.attr,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
@@ -146,16 +145,16 @@ static struct attribute_group topology_attr_group = {
|
||||
/* Add/Remove cpu_topology interface for CPU device */
|
||||
static int __cpuinit topology_add_dev(unsigned int cpu)
|
||||
{
|
||||
struct sys_device *sys_dev = get_cpu_sysdev(cpu);
|
||||
struct device *dev = get_cpu_device(cpu);
|
||||
|
||||
return sysfs_create_group(&sys_dev->kobj, &topology_attr_group);
|
||||
return sysfs_create_group(&dev->kobj, &topology_attr_group);
|
||||
}
|
||||
|
||||
static void __cpuinit topology_remove_dev(unsigned int cpu)
|
||||
{
|
||||
struct sys_device *sys_dev = get_cpu_sysdev(cpu);
|
||||
struct device *dev = get_cpu_device(cpu);
|
||||
|
||||
sysfs_remove_group(&sys_dev->kobj, &topology_attr_group);
|
||||
sysfs_remove_group(&dev->kobj, &topology_attr_group);
|
||||
}
|
||||
|
||||
static int __cpuinit topology_cpu_callback(struct notifier_block *nfb,
|
||||
|
||||
Reference in New Issue
Block a user