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:
Linus Torvalds 2010-10-22 19:36:42 -07:00
commit b9da057105
34 changed files with 1240 additions and 518 deletions

View File

@ -0,0 +1,12 @@
What: /sys/module/pch_phub/drivers/.../pch_mac
Date: August 2010
KernelVersion: 2.6.35
Contact: masa-korg@dsn.okisemi.com
Description: Write/read GbE MAC address.
What: /sys/module/pch_phub/drivers/.../pch_firmware
Date: August 2010
KernelVersion: 2.6.35
Contact: masa-korg@dsn.okisemi.com
Description: Write/read Option ROM data.

View File

@ -24,7 +24,7 @@ Dynamic debug has even more useful features:
read to display the complete list of known debug statements, to help guide you
Controlling dynamic debug Behaviour
===============================
===================================
The behaviour of pr_debug()/dev_debug()s are controlled via writing to a
control file in the 'debugfs' filesystem. Thus, you must first mount the debugfs
@ -212,6 +212,26 @@ Note the regexp ^[-+=][scp]+$ matches a flags specification.
Note also that there is no convenient syntax to remove all
the flags at once, you need to use "-psc".
Debug messages during boot process
==================================
To be able to activate debug messages during the boot process,
even before userspace and debugfs exists, use the boot parameter:
ddebug_query="QUERY"
QUERY follows the syntax described above, but must not exceed 1023
characters. The enablement of debug messages is done as an arch_initcall.
Thus you can enable debug messages in all code processed after this
arch_initcall via this boot parameter.
On an x86 system for example ACPI enablement is a subsys_initcall and
ddebug_query="file ec.c +p"
will show early Embedded Controller transactions during ACPI setup if
your machine (typically a laptop) has an Embedded Controller.
PCI (or other devices) initialization also is a hot candidate for using
this boot parameter for debugging purposes.
Examples
========

View File

@ -43,10 +43,11 @@ parameter is applicable:
AVR32 AVR32 architecture is enabled.
AX25 Appropriate AX.25 support is enabled.
BLACKFIN Blackfin architecture is enabled.
DRM Direct Rendering Management support is enabled.
EDD BIOS Enhanced Disk Drive Services (EDD) is enabled
EFI EFI Partitioning (GPT) is enabled
EIDE EIDE/ATAPI support is enabled.
DRM Direct Rendering Management support is enabled.
DYNAMIC_DEBUG Build in debug messages and enable them at runtime
FB The frame buffer device is enabled.
GCOV GCOV profiling is enabled.
HW Appropriate hardware is enabled.
@ -570,6 +571,10 @@ and is between 256 and 4096 characters. It is defined in the file
Format: <port#>,<type>
See also Documentation/input/joystick-parport.txt
ddebug_query= [KNL,DYNAMIC_DEBUG] Enable debug messages at early boot
time. See Documentation/dynamic-debug-howto.txt for
details.
debug [KNL] Enable kernel debugging (events log level).
debug_locks_verbose=
@ -2370,6 +2375,15 @@ and is between 256 and 4096 characters. It is defined in the file
switches= [HW,M68k]
sysfs.deprecated=0|1 [KNL]
Enable/disable old style sysfs layout for old udev
on older distributions. When this option is enabled
very new udev will not work anymore. When this option
is disabled (or CONFIG_SYSFS_DEPRECATED not compiled)
in older udev will not work anymore.
Default depends on CONFIG_SYSFS_DEPRECATED_V2 set in
the kernel configuration.
sysrq_always_enabled
[KNL]
Ignore sysrq setting - this boot parameter will

View File

@ -2064,14 +2064,16 @@ F: drivers/block/drbd/
F: lib/lru_cache.c
F: Documentation/blockdev/drbd/
DRIVER CORE, KOBJECTS, AND SYSFS
DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
M: Greg Kroah-Hartman <gregkh@suse.de>
T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
S: Supported
F: Documentation/kobject.txt
F: drivers/base/
F: fs/sysfs/
F: fs/debugfs/
F: include/linux/kobj*
F: include/linux/debugfs.h
F: lib/kobj*
DRM DRIVERS

View File

@ -22,9 +22,7 @@
#include "blk.h"
static DEFINE_MUTEX(block_class_lock);
#ifndef CONFIG_SYSFS_DEPRECATED
struct kobject *block_depr;
#endif
/* for extended dynamic devt allocation, currently only one major is used */
#define MAX_EXT_DEVT (1 << MINORBITS)
@ -810,10 +808,9 @@ static int __init genhd_device_init(void)
register_blkdev(BLOCK_EXT_MAJOR, "blkext");
#ifndef CONFIG_SYSFS_DEPRECATED
/* create top-level block dir */
if (!sysfs_deprecated)
block_depr = kobject_create_and_add("block", NULL);
#endif
return 0;
}

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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
}
/**

View File

@ -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);
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;
}

View File

@ -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;
}

View File

@ -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;
}
if (data) {
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;
}
if (data) {
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;

View File

@ -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;

View File

@ -248,15 +248,15 @@ config CS5535_CLOCK_EVENT_SRC
generic PIT, and are suitable for use as high-res timers.
config HP_ILO
tristate "Channel interface driver for HP iLO/iLO2 processor"
tristate "Channel interface driver for the HP iLO processor"
depends on PCI
default n
help
The channel interface driver allows applications to communicate
with iLO/iLO2 management processors present on HP ProLiant
servers. Upon loading, the driver creates /dev/hpilo/dXccbN files,
which can be used to gather data from the management processor,
via read and write system calls.
with iLO management processors present on HP ProLiant servers.
Upon loading, the driver creates /dev/hpilo/dXccbN files, which
can be used to gather data from the management processor, via
read and write system calls.
To compile this driver as a module, choose M here: the
module will be called hpilo.
@ -390,6 +390,18 @@ config BMP085
To compile this driver as a module, choose M here: the
module will be called bmp085.
config PCH_PHUB
tristate "PCH Packet Hub of Intel Topcliff"
depends on PCI
help
This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of
Intel Topcliff which is an IOH(Input/Output Hub) for x86 embedded
processor. The Topcliff has MAC address and Option ROM data in SROM.
This driver can access MAC address and Option ROM data in SROM.
To compile this driver as a module, choose M here: the module will
be called pch_phub.
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"

View File

@ -35,3 +35,4 @@ obj-y += eeprom/
obj-y += cb710/
obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o
obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o
obj-$(CONFIG_PCH_PHUB) += pch_phub.o

View File

@ -1,5 +1,5 @@
/*
* Driver for HP iLO/iLO2 management processor.
* Driver for the HP iLO management processor.
*
* Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
* David Altobelli <david.altobelli@hp.com>

717
drivers/misc/pch_phub.c Normal file
View File

@ -0,0 +1,717 @@
/*
* Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/if_ether.h>
#include <linux/ctype.h>
#define PHUB_STATUS 0x00 /* Status Register offset */
#define PHUB_CONTROL 0x04 /* Control Register offset */
#define PHUB_TIMEOUT 0x05 /* Time out value for Status Register */
#define PCH_PHUB_ROM_WRITE_ENABLE 0x01 /* Enabling for writing ROM */
#define PCH_PHUB_ROM_WRITE_DISABLE 0x00 /* Disabling for writing ROM */
#define PCH_PHUB_ROM_START_ADDR 0x14 /* ROM data area start address offset */
/* MAX number of INT_REDUCE_CONTROL registers */
#define MAX_NUM_INT_REDUCE_CONTROL_REG 128
#define PCI_DEVICE_ID_PCH1_PHUB 0x8801
#define PCH_MINOR_NOS 1
#define CLKCFG_CAN_50MHZ 0x12000000
#define CLKCFG_CANCLK_MASK 0xFF000000
/* SROM ACCESS Macro */
#define PCH_WORD_ADDR_MASK (~((1 << 2) - 1))
/* Registers address offset */
#define PCH_PHUB_ID_REG 0x0000
#define PCH_PHUB_QUEUE_PRI_VAL_REG 0x0004
#define PCH_PHUB_RC_QUEUE_MAXSIZE_REG 0x0008
#define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG 0x000C
#define PCH_PHUB_COMP_RESP_TIMEOUT_REG 0x0010
#define PCH_PHUB_BUS_SLAVE_CONTROL_REG 0x0014
#define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG 0x0018
#define PCH_PHUB_INTPIN_REG_WPERMIT_REG0 0x0020
#define PCH_PHUB_INTPIN_REG_WPERMIT_REG1 0x0024
#define PCH_PHUB_INTPIN_REG_WPERMIT_REG2 0x0028
#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3 0x002C
#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE 0x0040
#define CLKCFG_REG_OFFSET 0x500
#define PCH_PHUB_OROM_SIZE 15360
/**
* struct pch_phub_reg - PHUB register structure
* @phub_id_reg: PHUB_ID register val
* @q_pri_val_reg: QUEUE_PRI_VAL register val
* @rc_q_maxsize_reg: RC_QUEUE_MAXSIZE register val
* @bri_q_maxsize_reg: BRI_QUEUE_MAXSIZE register val
* @comp_resp_timeout_reg: COMP_RESP_TIMEOUT register val
* @bus_slave_control_reg: BUS_SLAVE_CONTROL_REG register val
* @deadlock_avoid_type_reg: DEADLOCK_AVOID_TYPE register val
* @intpin_reg_wpermit_reg0: INTPIN_REG_WPERMIT register 0 val
* @intpin_reg_wpermit_reg1: INTPIN_REG_WPERMIT register 1 val
* @intpin_reg_wpermit_reg2: INTPIN_REG_WPERMIT register 2 val
* @intpin_reg_wpermit_reg3: INTPIN_REG_WPERMIT register 3 val
* @int_reduce_control_reg: INT_REDUCE_CONTROL registers val
* @clkcfg_reg: CLK CFG register val
* @pch_phub_base_address: Register base address
* @pch_phub_extrom_base_address: external rom base address
*/
struct pch_phub_reg {
u32 phub_id_reg;
u32 q_pri_val_reg;
u32 rc_q_maxsize_reg;
u32 bri_q_maxsize_reg;
u32 comp_resp_timeout_reg;
u32 bus_slave_control_reg;
u32 deadlock_avoid_type_reg;
u32 intpin_reg_wpermit_reg0;
u32 intpin_reg_wpermit_reg1;
u32 intpin_reg_wpermit_reg2;
u32 intpin_reg_wpermit_reg3;
u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
u32 clkcfg_reg;
void __iomem *pch_phub_base_address;
void __iomem *pch_phub_extrom_base_address;
};
/* SROM SPEC for MAC address assignment offset */
static const int pch_phub_mac_offset[ETH_ALEN] = {0x3, 0x2, 0x1, 0x0, 0xb, 0xa};
static DEFINE_MUTEX(pch_phub_mutex);
/**
* pch_phub_read_modify_write_reg() - Reading modifying and writing register
* @reg_addr_offset: Register offset address value.
* @data: Writing value.
* @mask: Mask value.
*/
static void pch_phub_read_modify_write_reg(struct pch_phub_reg *chip,
unsigned int reg_addr_offset,
unsigned int data, unsigned int mask)
{
void __iomem *reg_addr = chip->pch_phub_base_address + reg_addr_offset;
iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
}
/* pch_phub_save_reg_conf - saves register configuration */
static void pch_phub_save_reg_conf(struct pci_dev *pdev)
{
unsigned int i;
struct pch_phub_reg *chip = pci_get_drvdata(pdev);
void __iomem *p = chip->pch_phub_base_address;
chip->phub_id_reg = ioread32(p + PCH_PHUB_ID_REG);
chip->q_pri_val_reg = ioread32(p + PCH_PHUB_QUEUE_PRI_VAL_REG);
chip->rc_q_maxsize_reg = ioread32(p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
chip->bri_q_maxsize_reg = ioread32(p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
chip->comp_resp_timeout_reg =
ioread32(p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
chip->bus_slave_control_reg =
ioread32(p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
chip->deadlock_avoid_type_reg =
ioread32(p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
chip->intpin_reg_wpermit_reg0 =
ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
chip->intpin_reg_wpermit_reg1 =
ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
chip->intpin_reg_wpermit_reg2 =
ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
chip->intpin_reg_wpermit_reg3 =
ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
dev_dbg(&pdev->dev, "%s : "
"chip->phub_id_reg=%x, "
"chip->q_pri_val_reg=%x, "
"chip->rc_q_maxsize_reg=%x, "
"chip->bri_q_maxsize_reg=%x, "
"chip->comp_resp_timeout_reg=%x, "
"chip->bus_slave_control_reg=%x, "
"chip->deadlock_avoid_type_reg=%x, "
"chip->intpin_reg_wpermit_reg0=%x, "
"chip->intpin_reg_wpermit_reg1=%x, "
"chip->intpin_reg_wpermit_reg2=%x, "
"chip->intpin_reg_wpermit_reg3=%x\n", __func__,
chip->phub_id_reg,
chip->q_pri_val_reg,
chip->rc_q_maxsize_reg,
chip->bri_q_maxsize_reg,
chip->comp_resp_timeout_reg,
chip->bus_slave_control_reg,
chip->deadlock_avoid_type_reg,
chip->intpin_reg_wpermit_reg0,
chip->intpin_reg_wpermit_reg1,
chip->intpin_reg_wpermit_reg2,
chip->intpin_reg_wpermit_reg3);
for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
chip->int_reduce_control_reg[i] =
ioread32(p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
dev_dbg(&pdev->dev, "%s : "
"chip->int_reduce_control_reg[%d]=%x\n",
__func__, i, chip->int_reduce_control_reg[i]);
}
chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET);
}
/* pch_phub_restore_reg_conf - restore register configuration */
static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
{
unsigned int i;
struct pch_phub_reg *chip = pci_get_drvdata(pdev);
void __iomem *p;
p = chip->pch_phub_base_address;
iowrite32(chip->phub_id_reg, p + PCH_PHUB_ID_REG);
iowrite32(chip->q_pri_val_reg, p + PCH_PHUB_QUEUE_PRI_VAL_REG);
iowrite32(chip->rc_q_maxsize_reg, p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
iowrite32(chip->bri_q_maxsize_reg, p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
iowrite32(chip->comp_resp_timeout_reg,
p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
iowrite32(chip->bus_slave_control_reg,
p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
iowrite32(chip->deadlock_avoid_type_reg,
p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
iowrite32(chip->intpin_reg_wpermit_reg0,
p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
iowrite32(chip->intpin_reg_wpermit_reg1,
p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
iowrite32(chip->intpin_reg_wpermit_reg2,
p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
iowrite32(chip->intpin_reg_wpermit_reg3,
p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
dev_dbg(&pdev->dev, "%s : "
"chip->phub_id_reg=%x, "
"chip->q_pri_val_reg=%x, "
"chip->rc_q_maxsize_reg=%x, "
"chip->bri_q_maxsize_reg=%x, "
"chip->comp_resp_timeout_reg=%x, "
"chip->bus_slave_control_reg=%x, "
"chip->deadlock_avoid_type_reg=%x, "
"chip->intpin_reg_wpermit_reg0=%x, "
"chip->intpin_reg_wpermit_reg1=%x, "
"chip->intpin_reg_wpermit_reg2=%x, "
"chip->intpin_reg_wpermit_reg3=%x\n", __func__,
chip->phub_id_reg,
chip->q_pri_val_reg,
chip->rc_q_maxsize_reg,
chip->bri_q_maxsize_reg,
chip->comp_resp_timeout_reg,
chip->bus_slave_control_reg,
chip->deadlock_avoid_type_reg,
chip->intpin_reg_wpermit_reg0,
chip->intpin_reg_wpermit_reg1,
chip->intpin_reg_wpermit_reg2,
chip->intpin_reg_wpermit_reg3);
for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
iowrite32(chip->int_reduce_control_reg[i],
p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
dev_dbg(&pdev->dev, "%s : "
"chip->int_reduce_control_reg[%d]=%x\n",
__func__, i, chip->int_reduce_control_reg[i]);
}
iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET);
}
/**
* pch_phub_read_serial_rom() - Reading Serial ROM
* @offset_address: Serial ROM offset address to read.
* @data: Read buffer for specified Serial ROM value.
*/
static void pch_phub_read_serial_rom(struct pch_phub_reg *chip,
unsigned int offset_address, u8 *data)
{
void __iomem *mem_addr = chip->pch_phub_extrom_base_address +
offset_address;
*data = ioread8(mem_addr);
}
/**
* pch_phub_write_serial_rom() - Writing Serial ROM
* @offset_address: Serial ROM offset address.
* @data: Serial ROM value to write.
*/
static int pch_phub_write_serial_rom(struct pch_phub_reg *chip,
unsigned int offset_address, u8 data)
{
void __iomem *mem_addr = chip->pch_phub_extrom_base_address +
(offset_address & PCH_WORD_ADDR_MASK);
int i;
unsigned int word_data;
unsigned int pos;
unsigned int mask;
pos = (offset_address % 4) * 8;
mask = ~(0xFF << pos);
iowrite32(PCH_PHUB_ROM_WRITE_ENABLE,
chip->pch_phub_extrom_base_address + PHUB_CONTROL);
word_data = ioread32(mem_addr);
iowrite32((word_data & mask) | (u32)data << pos, mem_addr);
i = 0;
while (ioread8(chip->pch_phub_extrom_base_address +
PHUB_STATUS) != 0x00) {
msleep(1);
if (i == PHUB_TIMEOUT)
return -ETIMEDOUT;
i++;
}
iowrite32(PCH_PHUB_ROM_WRITE_DISABLE,
chip->pch_phub_extrom_base_address + PHUB_CONTROL);
return 0;
}
/**
* pch_phub_read_serial_rom_val() - Read Serial ROM value
* @offset_address: Serial ROM address offset value.
* @data: Serial ROM value to read.
*/
static void pch_phub_read_serial_rom_val(struct pch_phub_reg *chip,
unsigned int offset_address, u8 *data)
{
unsigned int mem_addr;
mem_addr = PCH_PHUB_ROM_START_ADDR +
pch_phub_mac_offset[offset_address];
pch_phub_read_serial_rom(chip, mem_addr, data);
}
/**
* pch_phub_write_serial_rom_val() - writing Serial ROM value
* @offset_address: Serial ROM address offset value.
* @data: Serial ROM value.
*/
static int pch_phub_write_serial_rom_val(struct pch_phub_reg *chip,
unsigned int offset_address, u8 data)
{
int retval;
unsigned int mem_addr;
mem_addr = PCH_PHUB_ROM_START_ADDR +
pch_phub_mac_offset[offset_address];
retval = pch_phub_write_serial_rom(chip, mem_addr, data);
return retval;
}
/* pch_phub_gbe_serial_rom_conf - makes Serial ROM header format configuration
* for Gigabit Ethernet MAC address
*/
static int pch_phub_gbe_serial_rom_conf(struct pch_phub_reg *chip)
{
int retval;
retval = pch_phub_write_serial_rom(chip, 0x0b, 0xbc);
retval |= pch_phub_write_serial_rom(chip, 0x0a, 0x10);
retval |= pch_phub_write_serial_rom(chip, 0x09, 0x01);
retval |= pch_phub_write_serial_rom(chip, 0x08, 0x02);
retval |= pch_phub_write_serial_rom(chip, 0x0f, 0x00);
retval |= pch_phub_write_serial_rom(chip, 0x0e, 0x00);
retval |= pch_phub_write_serial_rom(chip, 0x0d, 0x00);
retval |= pch_phub_write_serial_rom(chip, 0x0c, 0x80);
retval |= pch_phub_write_serial_rom(chip, 0x13, 0xbc);
retval |= pch_phub_write_serial_rom(chip, 0x12, 0x10);
retval |= pch_phub_write_serial_rom(chip, 0x11, 0x01);
retval |= pch_phub_write_serial_rom(chip, 0x10, 0x18);
retval |= pch_phub_write_serial_rom(chip, 0x1b, 0xbc);
retval |= pch_phub_write_serial_rom(chip, 0x1a, 0x10);
retval |= pch_phub_write_serial_rom(chip, 0x19, 0x01);
retval |= pch_phub_write_serial_rom(chip, 0x18, 0x19);
retval |= pch_phub_write_serial_rom(chip, 0x23, 0xbc);
retval |= pch_phub_write_serial_rom(chip, 0x22, 0x10);
retval |= pch_phub_write_serial_rom(chip, 0x21, 0x01);
retval |= pch_phub_write_serial_rom(chip, 0x20, 0x3a);
retval |= pch_phub_write_serial_rom(chip, 0x27, 0x01);
retval |= pch_phub_write_serial_rom(chip, 0x26, 0x00);
retval |= pch_phub_write_serial_rom(chip, 0x25, 0x00);
retval |= pch_phub_write_serial_rom(chip, 0x24, 0x00);
return retval;
}
/**
* pch_phub_read_gbe_mac_addr() - Read Gigabit Ethernet MAC address
* @offset_address: Gigabit Ethernet MAC address offset value.
* @data: Buffer of the Gigabit Ethernet MAC address value.
*/
static void pch_phub_read_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data)
{
int i;
for (i = 0; i < ETH_ALEN; i++)
pch_phub_read_serial_rom_val(chip, i, &data[i]);
}
/**
* pch_phub_write_gbe_mac_addr() - Write MAC address
* @offset_address: Gigabit Ethernet MAC address offset value.
* @data: Gigabit Ethernet MAC address value.
*/
static int pch_phub_write_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data)
{
int retval;
int i;
retval = pch_phub_gbe_serial_rom_conf(chip);
if (retval)
return retval;
for (i = 0; i < ETH_ALEN; i++) {
retval = pch_phub_write_serial_rom_val(chip, i, data[i]);
if (retval)
return retval;
}
return retval;
}
static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
unsigned int rom_signature;
unsigned char rom_length;
unsigned int tmp;
unsigned int addr_offset;
unsigned int orom_size;
int ret;
int err;
struct pch_phub_reg *chip =
dev_get_drvdata(container_of(kobj, struct device, kobj));
ret = mutex_lock_interruptible(&pch_phub_mutex);
if (ret) {
err = -ERESTARTSYS;
goto return_err_nomutex;
}
/* Get Rom signature */
pch_phub_read_serial_rom(chip, 0x80, (unsigned char *)&rom_signature);
rom_signature &= 0xff;
pch_phub_read_serial_rom(chip, 0x81, (unsigned char *)&tmp);
rom_signature |= (tmp & 0xff) << 8;
if (rom_signature == 0xAA55) {
pch_phub_read_serial_rom(chip, 0x82, &rom_length);
orom_size = rom_length * 512;
if (orom_size < off) {
addr_offset = 0;
goto return_ok;
}
if (orom_size < count) {
addr_offset = 0;
goto return_ok;
}
for (addr_offset = 0; addr_offset < count; addr_offset++) {
pch_phub_read_serial_rom(chip, 0x80 + addr_offset + off,
&buf[addr_offset]);
}
} else {
err = -ENODATA;
goto return_err;
}
return_ok:
mutex_unlock(&pch_phub_mutex);
return addr_offset;
return_err:
mutex_unlock(&pch_phub_mutex);
return_err_nomutex:
return err;
}
static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
int err;
unsigned int addr_offset;
int ret;
struct pch_phub_reg *chip =
dev_get_drvdata(container_of(kobj, struct device, kobj));
ret = mutex_lock_interruptible(&pch_phub_mutex);
if (ret)
return -ERESTARTSYS;
if (off > PCH_PHUB_OROM_SIZE) {
addr_offset = 0;
goto return_ok;
}
if (count > PCH_PHUB_OROM_SIZE) {
addr_offset = 0;
goto return_ok;
}
for (addr_offset = 0; addr_offset < count; addr_offset++) {
if (PCH_PHUB_OROM_SIZE < off + addr_offset)
goto return_ok;
ret = pch_phub_write_serial_rom(chip, 0x80 + addr_offset + off,
buf[addr_offset]);
if (ret) {
err = ret;
goto return_err;
}
}
return_ok:
mutex_unlock(&pch_phub_mutex);
return addr_offset;
return_err:
mutex_unlock(&pch_phub_mutex);
return err;
}
static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr,
char *buf)
{
u8 mac[8];
struct pch_phub_reg *chip = dev_get_drvdata(dev);
pch_phub_read_gbe_mac_addr(chip, mac);
return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
u8 mac[6];
struct pch_phub_reg *chip = dev_get_drvdata(dev);
if (count != 18)
return -EINVAL;
sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
(u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3],
(u32 *)&mac[4], (u32 *)&mac[5]);
pch_phub_write_gbe_mac_addr(chip, mac);
return count;
}
static DEVICE_ATTR(pch_mac, S_IRUGO | S_IWUSR, show_pch_mac, store_pch_mac);
static struct bin_attribute pch_bin_attr = {
.attr = {
.name = "pch_firmware",
.mode = S_IRUGO | S_IWUSR,
},
.size = PCH_PHUB_OROM_SIZE + 1,
.read = pch_phub_bin_read,
.write = pch_phub_bin_write,
};
static int __devinit pch_phub_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int retval;
int ret;
ssize_t rom_size;
struct pch_phub_reg *chip;
chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
ret = pci_enable_device(pdev);
if (ret) {
dev_err(&pdev->dev,
"%s : pci_enable_device FAILED(ret=%d)", __func__, ret);
goto err_pci_enable_dev;
}
dev_dbg(&pdev->dev, "%s : pci_enable_device returns %d\n", __func__,
ret);
ret = pci_request_regions(pdev, KBUILD_MODNAME);
if (ret) {
dev_err(&pdev->dev,
"%s : pci_request_regions FAILED(ret=%d)", __func__, ret);
goto err_req_regions;
}
dev_dbg(&pdev->dev, "%s : "
"pci_request_regions returns %d\n", __func__, ret);
chip->pch_phub_base_address = pci_iomap(pdev, 1, 0);
if (chip->pch_phub_base_address == 0) {
dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
ret = -ENOMEM;
goto err_pci_iomap;
}
dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value "
"in pch_phub_base_address variable is %p\n", __func__,
chip->pch_phub_base_address);
chip->pch_phub_extrom_base_address = pci_map_rom(pdev, &rom_size);
if (chip->pch_phub_extrom_base_address == 0) {
dev_err(&pdev->dev, "%s : pci_map_rom FAILED", __func__);
ret = -ENOMEM;
goto err_pci_map;
}
dev_dbg(&pdev->dev, "%s : "
"pci_map_rom SUCCESS and value in "
"pch_phub_extrom_base_address variable is %p\n", __func__,
chip->pch_phub_extrom_base_address);
pci_set_drvdata(pdev, chip);
retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
if (retval)
goto err_sysfs_create;
retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
if (retval)
goto exit_bin_attr;
pch_phub_read_modify_write_reg(chip, (unsigned int)CLKCFG_REG_OFFSET,
CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);
/* set the prefech value */
iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14);
/* set the interrupt delay value */
iowrite32(0x25, chip->pch_phub_base_address + 0x44);
return 0;
exit_bin_attr:
sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
err_sysfs_create:
pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
err_pci_map:
pci_iounmap(pdev, chip->pch_phub_base_address);
err_pci_iomap:
pci_release_regions(pdev);
err_req_regions:
pci_disable_device(pdev);
err_pci_enable_dev:
kfree(chip);
dev_err(&pdev->dev, "%s returns %d\n", __func__, ret);
return ret;
}
static void __devexit pch_phub_remove(struct pci_dev *pdev)
{
struct pch_phub_reg *chip = pci_get_drvdata(pdev);
sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
sysfs_remove_bin_file(&pdev->dev.kobj, &pch_bin_attr);
pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
pci_iounmap(pdev, chip->pch_phub_base_address);
pci_release_regions(pdev);
pci_disable_device(pdev);
kfree(chip);
}
#ifdef CONFIG_PM
static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state)
{
int ret;
pch_phub_save_reg_conf(pdev);
ret = pci_save_state(pdev);
if (ret) {
dev_err(&pdev->dev,
" %s -pci_save_state returns %d\n", __func__, ret);
return ret;
}
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_disable_device(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
return 0;
}
static int pch_phub_resume(struct pci_dev *pdev)
{
int ret;
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
ret = pci_enable_device(pdev);
if (ret) {
dev_err(&pdev->dev,
"%s-pci_enable_device failed(ret=%d) ", __func__, ret);
return ret;
}
pci_enable_wake(pdev, PCI_D3hot, 0);
pch_phub_restore_reg_conf(pdev);
return 0;
}
#else
#define pch_phub_suspend NULL
#define pch_phub_resume NULL
#endif /* CONFIG_PM */
static struct pci_device_id pch_phub_pcidev_id[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
{0,}
};
static struct pci_driver pch_phub_driver = {
.name = "pch_phub",
.id_table = pch_phub_pcidev_id,
.probe = pch_phub_probe,
.remove = __devexit_p(pch_phub_remove),
.suspend = pch_phub_suspend,
.resume = pch_phub_resume
};
static int __init pch_phub_pci_init(void)
{
return pci_register_driver(&pch_phub_driver);
}
static void __exit pch_phub_pci_exit(void)
{
pci_unregister_driver(&pch_phub_driver);
}
module_init(pch_phub_pci_init);
module_exit(pch_phub_pci_exit);
MODULE_DESCRIPTION("PCH Packet Hub PCI Driver");
MODULE_LICENSE("GPL");

View File

@ -412,9 +412,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
device_initialize(&shost->shost_gendev);
dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
#ifndef CONFIG_SYSFS_DEPRECATED
shost->shost_gendev.bus = &scsi_bus_type;
#endif
shost->shost_gendev.type = &scsi_host_type;
device_initialize(&shost->shost_dev);

View File

@ -417,9 +417,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
starget->reap_ref = 1;
dev->parent = get_device(parent);
dev_set_name(dev, "target%d:%d:%d", shost->host_no, channel, id);
#ifndef CONFIG_SYSFS_DEPRECATED
dev->bus = &scsi_bus_type;
#endif
dev->type = &scsi_target_type;
starget->id = id;
starget->channel = channel;

View File

@ -23,9 +23,10 @@
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/kobject.h>
#include <linux/cdev.h>
#include <linux/uio_driver.h>
#define UIO_MAX_DEVICES 255
#define UIO_MAX_DEVICES (1U << MINORBITS)
struct uio_device {
struct module *owner;
@ -41,15 +42,10 @@ struct uio_device {
};
static int uio_major;
static struct cdev *uio_cdev;
static DEFINE_IDR(uio_idr);
static const struct file_operations uio_fops;
/* UIO class infrastructure */
static struct uio_class {
struct kref kref;
struct class *class;
} *uio_class;
/* Protect idr accesses */
static DEFINE_MUTEX(minor_lock);
@ -232,45 +228,34 @@ static ssize_t show_name(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct uio_device *idev = dev_get_drvdata(dev);
if (idev)
return sprintf(buf, "%s\n", idev->info->name);
else
return -ENODEV;
}
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
static ssize_t show_version(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct uio_device *idev = dev_get_drvdata(dev);
if (idev)
return sprintf(buf, "%s\n", idev->info->version);
else
return -ENODEV;
}
static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
static ssize_t show_event(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct uio_device *idev = dev_get_drvdata(dev);
if (idev)
return sprintf(buf, "%u\n",
(unsigned int)atomic_read(&idev->event));
else
return -ENODEV;
return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event));
}
static DEVICE_ATTR(event, S_IRUGO, show_event, NULL);
static struct attribute *uio_attrs[] = {
&dev_attr_name.attr,
&dev_attr_version.attr,
&dev_attr_event.attr,
NULL,
static struct device_attribute uio_class_attributes[] = {
__ATTR(name, S_IRUGO, show_name, NULL),
__ATTR(version, S_IRUGO, show_version, NULL),
__ATTR(event, S_IRUGO, show_event, NULL),
{}
};
static struct attribute_group uio_attr_grp = {
.attrs = uio_attrs,
/* UIO class infrastructure */
static struct class uio_class = {
.name = "uio",
.dev_attrs = uio_class_attributes,
};
/*
@ -287,10 +272,6 @@ static int uio_dev_add_attributes(struct uio_device *idev)
struct uio_port *port;
struct uio_portio *portio;
ret = sysfs_create_group(&idev->dev->kobj, &uio_attr_grp);
if (ret)
goto err_group;
for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
mem = &idev->info->mem[mi];
if (mem->size == 0)
@ -358,8 +339,6 @@ static int uio_dev_add_attributes(struct uio_device *idev)
kobject_put(&map->kobj);
}
kobject_put(idev->map_dir);
sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
err_group:
dev_err(idev->dev, "error creating sysfs files (%d)\n", ret);
return ret;
}
@ -385,8 +364,6 @@ static void uio_dev_del_attributes(struct uio_device *idev)
kobject_put(&port->portio->kobj);
}
kobject_put(idev->portio_dir);
sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
}
static int uio_get_minor(struct uio_device *idev)
@ -525,7 +502,7 @@ static unsigned int uio_poll(struct file *filep, poll_table *wait)
struct uio_listener *listener = filep->private_data;
struct uio_device *idev = listener->dev;
if (idev->info->irq == UIO_IRQ_NONE)
if (!idev->info->irq)
return -EIO;
poll_wait(filep, &idev->wait, wait);
@ -543,7 +520,7 @@ static ssize_t uio_read(struct file *filep, char __user *buf,
ssize_t retval;
s32 event_count;
if (idev->info->irq == UIO_IRQ_NONE)
if (!idev->info->irq)
return -EIO;
if (count != sizeof(s32))
@ -591,7 +568,7 @@ static ssize_t uio_write(struct file *filep, const char __user *buf,
ssize_t retval;
s32 irq_on;
if (idev->info->irq == UIO_IRQ_NONE)
if (!idev->info->irq)
return -EIO;
if (count != sizeof(s32))
@ -745,68 +722,72 @@ static const struct file_operations uio_fops = {
static int uio_major_init(void)
{
uio_major = register_chrdev(0, "uio", &uio_fops);
if (uio_major < 0)
return uio_major;
return 0;
static const char name[] = "uio";
struct cdev *cdev = NULL;
dev_t uio_dev = 0;
int result;
result = alloc_chrdev_region(&uio_dev, 0, UIO_MAX_DEVICES, name);
if (result)
goto out;
result = -ENOMEM;
cdev = cdev_alloc();
if (!cdev)
goto out_unregister;
cdev->owner = THIS_MODULE;
cdev->ops = &uio_fops;
kobject_set_name(&cdev->kobj, "%s", name);
result = cdev_add(cdev, uio_dev, UIO_MAX_DEVICES);
if (result)
goto out_put;
uio_major = MAJOR(uio_dev);
uio_cdev = cdev;
result = 0;
out:
return result;
out_put:
kobject_put(&cdev->kobj);
out_unregister:
unregister_chrdev_region(uio_dev, UIO_MAX_DEVICES);
goto out;
}
static void uio_major_cleanup(void)
{
unregister_chrdev(uio_major, "uio");
unregister_chrdev_region(MKDEV(uio_major, 0), UIO_MAX_DEVICES);
cdev_del(uio_cdev);
}
static int init_uio_class(void)
{
int ret = 0;
if (uio_class != NULL) {
kref_get(&uio_class->kref);
goto exit;
}
int ret;
/* This is the first time in here, set everything up properly */
ret = uio_major_init();
if (ret)
goto exit;
uio_class = kzalloc(sizeof(*uio_class), GFP_KERNEL);
if (!uio_class) {
ret = -ENOMEM;
goto err_kzalloc;
}
kref_init(&uio_class->kref);
uio_class->class = class_create(THIS_MODULE, "uio");
if (IS_ERR(uio_class->class)) {
ret = IS_ERR(uio_class->class);
printk(KERN_ERR "class_create failed for uio\n");
goto err_class_create;
ret = class_register(&uio_class);
if (ret) {
printk(KERN_ERR "class_register failed for uio\n");
goto err_class_register;
}
return 0;
err_class_create:
kfree(uio_class);
uio_class = NULL;
err_kzalloc:
err_class_register:
uio_major_cleanup();
exit:
return ret;
}
static void release_uio_class(struct kref *kref)
static void release_uio_class(void)
{
/* Ok, we cheat as we know we only have one uio_class */
class_destroy(uio_class->class);
kfree(uio_class);
class_unregister(&uio_class);
uio_major_cleanup();
uio_class = NULL;
}
static void uio_class_destroy(void)
{
if (uio_class)
kref_put(&uio_class->kref, release_uio_class);
}
/**
@ -829,10 +810,6 @@ int __uio_register_device(struct module *owner,
info->uio_dev = NULL;
ret = init_uio_class();
if (ret)
return ret;
idev = kzalloc(sizeof(*idev), GFP_KERNEL);
if (!idev) {
ret = -ENOMEM;
@ -848,7 +825,7 @@ int __uio_register_device(struct module *owner,
if (ret)
goto err_get_minor;
idev->dev = device_create(uio_class->class, parent,
idev->dev = device_create(&uio_class, parent,
MKDEV(uio_major, idev->minor), idev,
"uio%d", idev->minor);
if (IS_ERR(idev->dev)) {
@ -863,9 +840,9 @@ int __uio_register_device(struct module *owner,
info->uio_dev = idev;
if (idev->info->irq >= 0) {
ret = request_irq(idev->info->irq, uio_interrupt,
idev->info->irq_flags, idev->info->name, idev);
if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) {
ret = request_irq(info->irq, uio_interrupt,
info->irq_flags, info->name, idev);
if (ret)
goto err_request_irq;
}
@ -875,13 +852,12 @@ int __uio_register_device(struct module *owner,
err_request_irq:
uio_dev_del_attributes(idev);
err_uio_dev_add_attributes:
device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
err_device_create:
uio_free_minor(idev);
err_get_minor:
kfree(idev);
err_kzalloc:
uio_class_destroy();
return ret;
}
EXPORT_SYMBOL_GPL(__uio_register_device);
@ -902,15 +878,13 @@ void uio_unregister_device(struct uio_info *info)
uio_free_minor(idev);
if (info->irq >= 0)
if (info->irq && (info->irq != UIO_IRQ_CUSTOM))
free_irq(info->irq, idev);
uio_dev_del_attributes(idev);
dev_set_drvdata(idev->dev, NULL);
device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
kfree(idev);
uio_class_destroy();
return;
}
@ -918,11 +892,12 @@ EXPORT_SYMBOL_GPL(uio_unregister_device);
static int __init uio_init(void)
{
return 0;
return init_uio_class();
}
static void __exit uio_exit(void)
{
release_uio_class();
}
module_init(uio_init)

View File

@ -128,12 +128,6 @@ static int __devinit probe(struct pci_dev *pdev,
struct uio_pci_generic_dev *gdev;
int err;
if (!pdev->irq) {
dev_warn(&pdev->dev, "No IRQ assigned to device: "
"no support for interrupts?\n");
return -ENODEV;
}
err = pci_enable_device(pdev);
if (err) {
dev_err(&pdev->dev, "%s: pci_enable_device failed: %d\n",
@ -141,6 +135,13 @@ static int __devinit probe(struct pci_dev *pdev,
return err;
}
if (!pdev->irq) {
dev_warn(&pdev->dev, "No IRQ assigned to device: "
"no support for interrupts?\n");
pci_disable_device(pdev);
return -ENODEV;
}
err = verify_pci_2_3(pdev);
if (err)
goto err_verify;

View File

@ -537,14 +537,14 @@ void register_disk(struct gendisk *disk)
if (device_add(ddev))
return;
#ifndef CONFIG_SYSFS_DEPRECATED
if (!sysfs_deprecated) {
err = sysfs_create_link(block_depr, &ddev->kobj,
kobject_name(&ddev->kobj));
if (err) {
device_del(ddev);
return;
}
#endif
}
disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj);
disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);
@ -766,8 +766,7 @@ void del_gendisk(struct gendisk *disk)
kobject_put(disk->part0.holder_dir);
kobject_put(disk->slave_dir);
disk->driverfs_dev = NULL;
#ifndef CONFIG_SYSFS_DEPRECATED
if (!sysfs_deprecated)
sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
#endif
device_del(disk_to_dev(disk));
}

View File

@ -179,34 +179,18 @@ static void bin_vma_open(struct vm_area_struct *vma)
struct bin_buffer *bb = file->private_data;
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
if (!bb->vm_ops || !bb->vm_ops->open)
if (!bb->vm_ops)
return;
if (!sysfs_get_active(attr_sd))
return;
if (bb->vm_ops->open)
bb->vm_ops->open(vma);
sysfs_put_active(attr_sd);
}
static void bin_vma_close(struct vm_area_struct *vma)
{
struct file *file = vma->vm_file;
struct bin_buffer *bb = file->private_data;
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
if (!bb->vm_ops || !bb->vm_ops->close)
return;
if (!sysfs_get_active(attr_sd))
return;
bb->vm_ops->close(vma);
sysfs_put_active(attr_sd);
}
static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct file *file = vma->vm_file;
@ -214,12 +198,14 @@ static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
int ret;
if (!bb->vm_ops || !bb->vm_ops->fault)
if (!bb->vm_ops)
return VM_FAULT_SIGBUS;
if (!sysfs_get_active(attr_sd))
return VM_FAULT_SIGBUS;
ret = VM_FAULT_SIGBUS;
if (bb->vm_ops->fault)
ret = bb->vm_ops->fault(vma, vmf);
sysfs_put_active(attr_sd);
@ -236,12 +222,11 @@ static int bin_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
if (!bb->vm_ops)
return VM_FAULT_SIGBUS;
if (!bb->vm_ops->page_mkwrite)
return 0;
if (!sysfs_get_active(attr_sd))
return VM_FAULT_SIGBUS;
ret = 0;
if (bb->vm_ops->page_mkwrite)
ret = bb->vm_ops->page_mkwrite(vma, vmf);
sysfs_put_active(attr_sd);
@ -256,12 +241,14 @@ static int bin_access(struct vm_area_struct *vma, unsigned long addr,
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
int ret;
if (!bb->vm_ops || !bb->vm_ops->access)
if (!bb->vm_ops)
return -EINVAL;
if (!sysfs_get_active(attr_sd))
return -EINVAL;
ret = -EINVAL;
if (bb->vm_ops->access)
ret = bb->vm_ops->access(vma, addr, buf, len, write);
sysfs_put_active(attr_sd);
@ -276,12 +263,14 @@ static int bin_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
int ret;
if (!bb->vm_ops || !bb->vm_ops->set_policy)
if (!bb->vm_ops)
return 0;
if (!sysfs_get_active(attr_sd))
return -EINVAL;
ret = 0;
if (bb->vm_ops->set_policy)
ret = bb->vm_ops->set_policy(vma, new);
sysfs_put_active(attr_sd);
@ -296,12 +285,14 @@ static struct mempolicy *bin_get_policy(struct vm_area_struct *vma,
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
struct mempolicy *pol;
if (!bb->vm_ops || !bb->vm_ops->get_policy)
if (!bb->vm_ops)
return vma->vm_policy;
if (!sysfs_get_active(attr_sd))
return vma->vm_policy;
pol = vma->vm_policy;
if (bb->vm_ops->get_policy)
pol = bb->vm_ops->get_policy(vma, addr);
sysfs_put_active(attr_sd);
@ -316,12 +307,14 @@ static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from,
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
int ret;
if (!bb->vm_ops || !bb->vm_ops->migrate)
if (!bb->vm_ops)
return 0;
if (!sysfs_get_active(attr_sd))
return 0;
ret = 0;
if (bb->vm_ops->migrate)
ret = bb->vm_ops->migrate(vma, from, to, flags);
sysfs_put_active(attr_sd);
@ -331,7 +324,6 @@ static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from,
static const struct vm_operations_struct bin_vm_ops = {
.open = bin_vma_open,
.close = bin_vma_close,
.fault = bin_fault,
.page_mkwrite = bin_page_mkwrite,
.access = bin_access,
@ -377,6 +369,14 @@ static int mmap(struct file *file, struct vm_area_struct *vma)
if (bb->mmapped && bb->vm_ops != vma->vm_ops)
goto out_put;
/*
* It is not possible to successfully wrap close.
* So error if someone is trying to use close.
*/
rc = -EINVAL;
if (vma->vm_ops && vma->vm_ops->close)
goto out_put;
rc = 0;
bb->mmapped = 1;
bb->vm_ops = vma->vm_ops;

View File

@ -751,4 +751,11 @@ do { \
MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor))
#define MODULE_ALIAS_CHARDEV_MAJOR(major) \
MODULE_ALIAS("char-major-" __stringify(major) "-*")
#ifdef CONFIG_SYSFS_DEPRECATED
extern long sysfs_deprecated;
#else
#define sysfs_deprecated 0
#endif
#endif /* _DEVICE_H_ */

View File

@ -191,6 +191,8 @@ static inline struct kobj_type *get_ktype(struct kobject *kobj)
}
extern struct kobject *kset_find_obj(struct kset *, const char *);
extern struct kobject *kset_find_obj_hinted(struct kset *, const char *,
struct kobject *);
/* The global /sys/kernel/ kobject for people to chain off of */
extern struct kobject *kernel_kobj;

View File

@ -23,6 +23,8 @@
struct memory_block {
unsigned long phys_index;
unsigned long state;
int section_count;
/*
* This serializes all state change requests. It isn't
* held during creation because the control files are
@ -113,6 +115,8 @@ extern int memory_dev_init(void);
extern int remove_memory_block(unsigned long, struct mem_section *, int);
extern int memory_notify(unsigned long val, void *v);
extern int memory_isolate_notify(unsigned long val, void *v);
extern struct memory_block *find_memory_block_hinted(struct mem_section *,
struct memory_block *);
extern struct memory_block *find_memory_block(struct mem_section *);
#define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT)
enum mem_add_context { BOOT, HOTPLUG };

View File

@ -138,6 +138,9 @@ extern struct platform_device *platform_create_bundle(struct platform_driver *dr
struct resource *res, unsigned int n_res,
const void *data, size_t size);
extern const struct dev_pm_ops * platform_bus_get_pm_ops(void);
extern void platform_bus_set_pm_ops(const struct dev_pm_ops *pm);
/* early platform driver interface */
struct early_platform_driver {
const char *class_str;

View File

@ -108,7 +108,7 @@ extern void uio_event_notify(struct uio_info *info);
/* defines for uio_info->irq */
#define UIO_IRQ_CUSTOM -1
#define UIO_IRQ_NONE -2
#define UIO_IRQ_NONE 0
/* defines for uio_mem->memtype */
#define UIO_MEM_NONE 0

View File

@ -133,9 +133,7 @@ struct snd_card {
int free_on_last_close; /* free in context of file_release */
wait_queue_head_t shutdown_sleep;
struct device *dev; /* device assigned to this card */
#ifndef CONFIG_SYSFS_DEPRECATED
struct device *card_dev; /* cardX object for sysfs */
#endif
#ifdef CONFIG_PM
unsigned int power_state; /* power state */
@ -196,11 +194,7 @@ struct snd_minor {
/* return a device pointer linked to each sound device as a parent */
static inline struct device *snd_card_get_device_link(struct snd_card *card)
{
#ifdef CONFIG_SYSFS_DEPRECATED
return card ? card->dev : NULL;
#else
return card ? card->card_dev : NULL;
#endif
}
/* sound.c */

View File

@ -686,40 +686,42 @@ config MM_OWNER
bool
config SYSFS_DEPRECATED
bool
config SYSFS_DEPRECATED_V2
bool "enable deprecated sysfs features to support old userspace tools"
depends on SYSFS
default n
select SYSFS_DEPRECATED
help
This option switches the layout of sysfs to the deprecated
version. Do not use it on recent distributions.
This option adds code that switches the layout of the "block" class
devices, to not show up in /sys/class/block/, but only in
/sys/block/.
The current sysfs layout features a unified device tree at
/sys/devices/, which is able to express a hierarchy between
class devices. If the deprecated option is set to Y, the
unified device tree is split into a bus device tree at
/sys/devices/ and several individual class device trees at
/sys/class/. The class and bus devices will be connected by
"<subsystem>:<name>" and the "device" links. The "block"
class devices, will not show up in /sys/class/block/. Some
subsystems will suppress the creation of some devices which
depend on the unified device tree.
This switch is only active when the sysfs.deprecated=1 boot option is
passed or the SYSFS_DEPRECATED_V2 option is set.
This option is not a pure compatibility option that can
be safely enabled on newer distributions. It will change the
layout of sysfs to the non-extensible deprecated version,
and disable some features, which can not be exported without
confusing older userspace tools. Since 2007/2008 all major
distributions do not enable this option, and ship no tools which
depend on the deprecated layout or this option.
This option allows new kernels to run on old distributions and tools,
which might get confused by /sys/class/block/. Since 2007/2008 all
major distributions and tools handle this just fine.
If you are using a new kernel on an older distribution, or use
older userspace tools, you might need to say Y here. Do not say Y,
if the original kernel, that came with your distribution, has
this option set to N.
Recent distributions and userspace tools after 2009/2010 depend on
the existence of /sys/class/block/, and will not work with this
option enabled.
Only if you are using a new kernel on an old distribution, you might
need to say Y here.
config SYSFS_DEPRECATED_V2
bool "enabled deprecated sysfs features by default"
default n
depends on SYSFS
depends on SYSFS_DEPRECATED
help
Enable deprecated sysfs by default.
See the CONFIG_SYSFS_DEPRECATED option for more details about this
option.
Only if you are using a new kernel on an old distribution, you might
need to say Y here. Even then, odds are you would not need it
enabled, you can always pass the boot option if absolutely necessary.
config RELAY
bool "Kernel->user space relay support (formerly relayfs)"

View File

@ -393,6 +393,40 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
return 0;
}
static int ddebug_exec_query(char *query_string)
{
unsigned int flags = 0, mask = 0;
struct ddebug_query query;
#define MAXWORDS 9
int nwords;
char *words[MAXWORDS];
nwords = ddebug_tokenize(query_string, words, MAXWORDS);
if (nwords <= 0)
return -EINVAL;
if (ddebug_parse_query(words, nwords-1, &query))
return -EINVAL;
if (ddebug_parse_flags(words[nwords-1], &flags, &mask))
return -EINVAL;
/* actually go and implement the change */
ddebug_change(&query, flags, mask);
return 0;
}
static __initdata char ddebug_setup_string[1024];
static __init int ddebug_setup_query(char *str)
{
if (strlen(str) >= 1024) {
pr_warning("ddebug boot param string too large\n");
return 0;
}
strcpy(ddebug_setup_string, str);
return 1;
}
__setup("ddebug_query=", ddebug_setup_query);
/*
* File_ops->write method for <debugfs>/dynamic_debug/conrol. Gathers the
* command text from userspace, parses and executes it.
@ -400,12 +434,8 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
size_t len, loff_t *offp)
{
unsigned int flags = 0, mask = 0;
struct ddebug_query query;
#define MAXWORDS 9
int nwords;
char *words[MAXWORDS];
char tmpbuf[256];
int ret;
if (len == 0)
return 0;
@ -419,16 +449,9 @@ static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
printk(KERN_INFO "%s: read %d bytes from userspace\n",
__func__, (int)len);
nwords = ddebug_tokenize(tmpbuf, words, MAXWORDS);
if (nwords <= 0)
return -EINVAL;
if (ddebug_parse_query(words, nwords-1, &query))
return -EINVAL;
if (ddebug_parse_flags(words[nwords-1], &flags, &mask))
return -EINVAL;
/* actually go and implement the change */
ddebug_change(&query, flags, mask);
ret = ddebug_exec_query(tmpbuf);
if (ret)
return ret;
*offp += len;
return len;
@ -689,13 +712,14 @@ static void ddebug_remove_all_tables(void)
mutex_unlock(&ddebug_lock);
}
static int __init dynamic_debug_init(void)
static __initdata int ddebug_init_success;
static int __init dynamic_debug_init_debugfs(void)
{
struct dentry *dir, *file;
struct _ddebug *iter, *iter_start;
const char *modname = NULL;
int ret = 0;
int n = 0;
if (!ddebug_init_success)
return -ENODEV;
dir = debugfs_create_dir("dynamic_debug", NULL);
if (!dir)
@ -706,6 +730,16 @@ static int __init dynamic_debug_init(void)
debugfs_remove(dir);
return -ENOMEM;
}
return 0;
}
static int __init dynamic_debug_init(void)
{
struct _ddebug *iter, *iter_start;
const char *modname = NULL;
int ret = 0;
int n = 0;
if (__start___verbose != __stop___verbose) {
iter = __start___verbose;
modname = iter->modname;
@ -723,12 +757,26 @@ static int __init dynamic_debug_init(void)
}
ret = ddebug_add_module(iter_start, n, modname);
}
out_free:
if (ret) {
ddebug_remove_all_tables();
debugfs_remove(dir);
debugfs_remove(file);
/* ddebug_query boot param got passed -> set it up */
if (ddebug_setup_string[0] != '\0') {
ret = ddebug_exec_query(ddebug_setup_string);
if (ret)
pr_warning("Invalid ddebug boot param %s",
ddebug_setup_string);
else
pr_info("ddebug initialized with string %s",
ddebug_setup_string);
}
out_free:
if (ret)
ddebug_remove_all_tables();
else
ddebug_init_success = 1;
return 0;
}
module_init(dynamic_debug_init);
/* Allow early initialization for boot messages via boot param */
arch_initcall(dynamic_debug_init);
/* Debugfs setup must be done later */
module_init(dynamic_debug_init_debugfs);

View File

@ -745,18 +745,57 @@ void kset_unregister(struct kset *k)
* take a reference and return the object.
*/
struct kobject *kset_find_obj(struct kset *kset, const char *name)
{
return kset_find_obj_hinted(kset, name, NULL);
}
/**
* kset_find_obj_hinted - search for object in kset given a predecessor hint.
* @kset: kset we're looking in.
* @name: object's name.
* @hint: hint to possible object's predecessor.
*
* Check the hint's next object and if it is a match return it directly,
* otherwise, fall back to the behavior of kset_find_obj(). Either way
* a reference for the returned object is held and the reference on the
* hinted object is released.
*/
struct kobject *kset_find_obj_hinted(struct kset *kset, const char *name,
struct kobject *hint)
{
struct kobject *k;
struct kobject *ret = NULL;
spin_lock(&kset->list_lock);
if (!hint)
goto slow_search;
/* end of list detection */
if (hint->entry.next == kset->list.next)
goto slow_search;
k = container_of(hint->entry.next, struct kobject, entry);
if (!kobject_name(k) || strcmp(kobject_name(k), name))
goto slow_search;
ret = kobject_get(k);
goto unlock_exit;
slow_search:
list_for_each_entry(k, &kset->list, entry) {
if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
ret = kobject_get(k);
break;
}
}
unlock_exit:
spin_unlock(&kset->list_lock);
if (hint)
kobject_put(hint);
return ret;
}

View File

@ -395,12 +395,10 @@ int snd_card_disconnect(struct snd_card *card)
snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number);
snd_info_card_disconnect(card);
#ifndef CONFIG_SYSFS_DEPRECATED
if (card->card_dev) {
device_unregister(card->card_dev);
card->card_dev = NULL;
}
#endif
#ifdef CONFIG_PM
wake_up(&card->power_sleep);
#endif
@ -573,7 +571,6 @@ void snd_card_set_id(struct snd_card *card, const char *nid)
}
EXPORT_SYMBOL(snd_card_set_id);
#ifndef CONFIG_SYSFS_DEPRECATED
static ssize_t
card_id_show_attr(struct device *dev,
struct device_attribute *attr, char *buf)
@ -630,7 +627,6 @@ card_number_show_attr(struct device *dev,
static struct device_attribute card_number_attrs =
__ATTR(number, S_IRUGO, card_number_show_attr, NULL);
#endif /* CONFIG_SYSFS_DEPRECATED */
/**
* snd_card_register - register the soundcard
@ -649,7 +645,7 @@ int snd_card_register(struct snd_card *card)
if (snd_BUG_ON(!card))
return -EINVAL;
#ifndef CONFIG_SYSFS_DEPRECATED
if (!card->card_dev) {
card->card_dev = device_create(sound_class, card->dev,
MKDEV(0, 0), card,
@ -657,7 +653,7 @@ int snd_card_register(struct snd_card *card)
if (IS_ERR(card->card_dev))
card->card_dev = NULL;
}
#endif
if ((err = snd_device_register_all(card)) < 0)
return err;
mutex_lock(&snd_card_mutex);
@ -674,7 +670,6 @@ int snd_card_register(struct snd_card *card)
if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);
#endif
#ifndef CONFIG_SYSFS_DEPRECATED
if (card->card_dev) {
err = device_create_file(card->card_dev, &card_id_attrs);
if (err < 0)
@ -683,7 +678,7 @@ int snd_card_register(struct snd_card *card)
if (err < 0)
return err;
}
#endif
return 0;
}