Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
8bed75c8
Commit
8bed75c8
authored
Dec 04, 2002
by
Patrick Mochel
Browse files
Options
Browse Files
Download
Plain Diff
Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin
into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-core
parents
2becf2fd
6f614c99
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
460 additions
and
122 deletions
+460
-122
drivers/base/base.h
drivers/base/base.h
+2
-10
drivers/base/bus.c
drivers/base/bus.c
+89
-1
drivers/base/class.c
drivers/base/class.c
+8
-4
drivers/base/core.c
drivers/base/core.c
+9
-15
drivers/base/intf.c
drivers/base/intf.c
+222
-53
drivers/base/node.c
drivers/base/node.c
+2
-2
drivers/base/power.c
drivers/base/power.c
+12
-10
drivers/block/genhd.c
drivers/block/genhd.c
+2
-2
drivers/pci/probe.c
drivers/pci/probe.c
+1
-0
fs/partitions/check.c
fs/partitions/check.c
+2
-4
fs/sysfs/inode.c
fs/sysfs/inode.c
+52
-8
include/linux/device.h
include/linux/device.h
+15
-11
include/linux/kobject.h
include/linux/kobject.h
+9
-0
lib/kobject.c
lib/kobject.c
+35
-2
No files found.
drivers/base/base.h
View file @
8bed75c8
#undef DEBUG
#ifdef DEBUG
# define DBG(x...) printk(x)
#else
# define DBG(x...)
#endif
extern
struct
list_head
global_device_list
;
extern
spinlock_t
device_lock
;
extern
struct
semaphore
device_sem
;
extern
int
bus_add_device
(
struct
device
*
dev
);
...
...
@@ -22,8 +14,8 @@ extern void devclass_remove_device(struct device *);
extern
int
devclass_add_driver
(
struct
device_driver
*
);
extern
void
devclass_remove_driver
(
struct
device_driver
*
);
extern
int
interface_add
(
struct
device_class
*
,
struct
device
*
);
extern
void
interface_remove
(
struct
device_class
*
,
struct
device
*
);
extern
int
interface_add
_dev
(
struct
device
*
);
extern
void
interface_remove
_dev
(
struct
device
*
);
#ifdef CONFIG_HOTPLUG
...
...
drivers/base/bus.c
View file @
8bed75c8
...
...
@@ -132,6 +132,91 @@ struct subsystem bus_subsys = {
};
/**
* bus_for_each_dev - device iterator.
* @bus: bus type.
* @start: device to start iterating from.
* @data: data for the callback.
* @fn: function to be called for each device.
*
* Iterate over @bus's list of devices, and call @fn for each,
* passing it @data. If @start is not NULL, we use that device to
* begin iterating from.
*
* We check the return of @fn each time. If it returns anything
* other than 0, we break out and return that value.
*
* NOTE: The device that returns a non-zero value is not retained
* in any way, nor is its refcount incremented. If the caller needs
* to retain this data, it should do, and increment the reference
* count in the supplied callback.
*/
int
bus_for_each_dev
(
struct
bus_type
*
bus
,
struct
device
*
start
,
void
*
data
,
int
(
*
fn
)(
struct
device
*
,
void
*
))
{
struct
list_head
*
head
,
*
entry
;
int
error
=
0
;
if
(
!
(
bus
=
get_bus
(
bus
)))
return
-
EINVAL
;
head
=
start
?
&
start
->
bus_list
:
&
bus
->
devices
;
down_read
(
&
bus
->
subsys
.
rwsem
);
list_for_each
(
entry
,
head
)
{
struct
device
*
dev
=
get_device
(
to_dev
(
entry
));
error
=
fn
(
dev
,
data
);
put_device
(
dev
);
if
(
error
)
break
;
}
up_read
(
&
bus
->
subsys
.
rwsem
);
return
error
;
}
/**
* bus_for_each_drv - driver iterator
* @bus: bus we're dealing with.
* @start: driver to start iterating on.
* @data: data to pass to the callback.
* @fn: function to call for each driver.
*
* This is nearly identical to the device iterator above.
* We iterate over each driver that belongs to @bus, and call
* @fn for each. If @fn returns anything but 0, we break out
* and return it. If @start is not NULL, we use it as the head
* of the list.
*
* NOTE: we don't return the driver that returns a non-zero
* value, nor do we leave the reference count incremented for that
* driver. If the caller needs to know that info, it must set it
* in the callback. It must also be sure to increment the refcount
* so it doesn't disappear before returning to the caller.
*/
int
bus_for_each_drv
(
struct
bus_type
*
bus
,
struct
device_driver
*
start
,
void
*
data
,
int
(
*
fn
)(
struct
device_driver
*
,
void
*
))
{
struct
list_head
*
head
,
*
entry
;
int
error
=
0
;
if
(
!
(
bus
=
get_bus
(
bus
)))
return
-
EINVAL
;
head
=
start
?
&
start
->
bus_list
:
&
bus
->
drivers
;
down_read
(
&
bus
->
subsys
.
rwsem
);
list_for_each
(
entry
,
head
)
{
struct
device_driver
*
drv
=
get_driver
(
to_drv
(
entry
));
error
=
fn
(
drv
,
data
);
put_driver
(
drv
);
if
(
error
)
break
;
}
up_read
(
&
bus
->
subsys
.
rwsem
);
return
error
;
}
/**
* attach - add device to driver.
* @dev: device.
...
...
@@ -190,7 +275,7 @@ static int bus_match(struct device * dev, struct device_driver * drv)
*/
static
int
device_attach
(
struct
device
*
dev
)
{
struct
bus_type
*
bus
=
dev
->
bus
;
struct
bus_type
*
bus
=
dev
->
bus
;
struct
list_head
*
entry
;
int
error
=
0
;
...
...
@@ -455,6 +540,9 @@ static int __init bus_subsys_init(void)
core_initcall
(
bus_subsys_init
);
EXPORT_SYMBOL
(
bus_for_each_dev
);
EXPORT_SYMBOL
(
bus_for_each_drv
);
EXPORT_SYMBOL
(
bus_add_device
);
EXPORT_SYMBOL
(
bus_remove_device
);
EXPORT_SYMBOL
(
bus_register
);
...
...
drivers/base/class.c
View file @
8bed75c8
...
...
@@ -2,7 +2,7 @@
* class.c - basic device class management
*/
#
undef
DEBUG
#
define
DEBUG
#include <linux/device.h>
#include <linux/module.h>
...
...
@@ -98,7 +98,6 @@ void devclass_remove_file(struct device_class * cls, struct devclass_attribute *
}
int
devclass_add_driver
(
struct
device_driver
*
drv
)
{
struct
device_class
*
cls
=
get_devclass
(
drv
->
devclass
);
...
...
@@ -172,9 +171,11 @@ int devclass_add_device(struct device * dev)
error
=
cls
->
add_device
(
dev
);
if
(
!
error
)
{
enum_device
(
cls
,
dev
);
interface_add
(
cls
,
dev
);
interface_add
_dev
(
dev
);
}
list_add_tail
(
&
dev
->
class_list
,
&
cls
->
devices
);
/* notify userspace (call /sbin/hotplug) */
class_hotplug
(
dev
,
"add"
);
...
...
@@ -196,9 +197,11 @@ void devclass_remove_device(struct device * dev)
down_write
(
&
cls
->
subsys
.
rwsem
);
pr_debug
(
"device class %s: removing device %s
\n
"
,
cls
->
name
,
dev
->
name
);
interface_remove
(
cls
,
dev
);
interface_remove
_dev
(
dev
);
unenum_device
(
cls
,
dev
);
list_del
(
&
dev
->
class_list
);
/* notify userspace (call /sbin/hotplug) */
class_hotplug
(
dev
,
"remove"
);
...
...
@@ -224,6 +227,7 @@ void put_devclass(struct device_class * cls)
int
devclass_register
(
struct
device_class
*
cls
)
{
INIT_LIST_HEAD
(
&
cls
->
drivers
);
INIT_LIST_HEAD
(
&
cls
->
devices
);
pr_debug
(
"device class '%s': registering
\n
"
,
cls
->
name
);
strncpy
(
cls
->
subsys
.
kobj
.
name
,
cls
->
name
,
KOBJ_NAME_LEN
);
...
...
drivers/base/core.c
View file @
8bed75c8
...
...
@@ -18,15 +18,11 @@
#include "base.h"
LIST_HEAD
(
global_device_list
);
int
(
*
platform_notify
)(
struct
device
*
dev
)
=
NULL
;
int
(
*
platform_notify_remove
)(
struct
device
*
dev
)
=
NULL
;
DECLARE_MUTEX
(
device_sem
);
spinlock_t
device_lock
=
SPIN_LOCK_UNLOCKED
;
#define to_dev(obj) container_of(obj,struct device,kobj)
...
...
@@ -146,11 +142,10 @@ void device_initialize(struct device *dev)
kobject_init
(
&
dev
->
kobj
);
INIT_LIST_HEAD
(
&
dev
->
node
);
INIT_LIST_HEAD
(
&
dev
->
children
);
INIT_LIST_HEAD
(
&
dev
->
g_list
);
INIT_LIST_HEAD
(
&
dev
->
driver_list
);
INIT_LIST_HEAD
(
&
dev
->
bus_list
);
INIT_LIST_HEAD
(
&
dev
->
class_list
);
INIT_LIST_HEAD
(
&
dev
->
intf_list
);
// spin_lock_init(&dev->lock);
}
/**
...
...
@@ -188,13 +183,11 @@ int device_add(struct device *dev)
goto
register_done
;
/* now take care of our own registration */
down
(
&
device_sem
);
if
(
parent
)
{
list_add_tail
(
&
dev
->
g_list
,
&
dev
->
parent
->
g_list
);
down
(
&
device_sem
);
list_add_tail
(
&
dev
->
node
,
&
parent
->
children
);
}
else
list_add_tail
(
&
dev
->
g_list
,
&
global_device_list
);
up
(
&
device_sem
);
up
(
&
device_sem
);
}
bus_add_device
(
dev
);
...
...
@@ -276,10 +269,11 @@ void device_del(struct device * dev)
{
struct
device
*
parent
=
dev
->
parent
;
down
(
&
device_sem
);
list_del_init
(
&
dev
->
node
);
list_del_init
(
&
dev
->
g_list
);
up
(
&
device_sem
);
if
(
parent
)
{
down
(
&
device_sem
);
list_del_init
(
&
dev
->
node
);
up
(
&
device_sem
);
}
/* Notify the platform of the removal, in case they
* need to do anything...
...
...
drivers/base/intf.c
View file @
8bed75c8
...
...
@@ -2,7 +2,7 @@
* intf.c - class-specific interface management
*/
#
undef
DEBUG
#
define
DEBUG
#include <linux/device.h>
#include <linux/module.h>
...
...
@@ -10,98 +10,267 @@
#include "base.h"
#define to_intf(node) container_of(node,struct device_interface,kobj.entry)
#define to_intf(node) container_of(node,struct device_interface,subsys.kobj.entry)
#define to_data(e) container_of(e,struct intf_data,kobj.entry)
#define intf_from_data(d) container_of(d->kobj.subsys,struct device_interface, subsys);
/**
* intf_dev_link - symlink from interface's directory to device's directory
* intf_dev_link - create sysfs symlink for interface.
* @data: interface data descriptor.
*
* Create a symlink 'phys' in the interface's directory to
*/
static
int
intf_dev_link
(
struct
intf_data
*
data
)
{
char
linkname
[
16
];
snprintf
(
linkname
,
16
,
"%u"
,
data
->
intf_num
);
return
sysfs_create_link
(
&
data
->
intf
->
kobj
,
&
data
->
dev
->
kobj
,
linkname
);
char
name
[
16
];
snprintf
(
name
,
16
,
"%d"
,
data
->
intf_num
);
return
sysfs_create_link
(
&
data
->
intf
->
subsys
.
kobj
,
&
data
->
dev
->
kobj
,
name
);
}
/**
* intf_dev_unlink - remove symlink for interface.
* @intf: interface data descriptor.
*
*/
static
void
intf_dev_unlink
(
struct
intf_data
*
data
)
{
char
linkname
[
16
];
snprintf
(
linkname
,
16
,
"%u"
,
data
->
intf_num
);
sysfs_remove_link
(
&
data
->
intf
->
kobj
,
linkname
);
char
name
[
16
];
snprintf
(
name
,
16
,
"%d"
,
data
->
intf_num
);
sysfs_remove_link
(
&
data
->
intf
->
subsys
.
kobj
,
name
);
}
/**
* interface_add_data - attach data descriptor
* @data: interface data descriptor.
*
* This attaches the per-instance interface object to the
* interface (by registering its kobject) and the device
* itself (by inserting it into the device's list).
*
* Note that there is no explicit protection done in this
* function. This should be called from the interface's
* add_device() method, which is called under the protection
* of the class's rwsem.
*/
int
interface_add_data
(
struct
intf_data
*
data
)
{
struct
device_interface
*
intf
=
intf_from_data
(
data
);
data
->
intf_num
=
data
->
intf
->
devnum
++
;
data
->
kobj
.
subsys
=
&
intf
->
subsys
;
kobject_register
(
&
data
->
kobj
);
list_add_tail
(
&
data
->
dev_entry
,
&
data
->
dev
->
intf_list
);
intf_dev_link
(
data
);
return
0
;
}
/**
* interface_remove_data - detach data descriptor.
* @data: interface data descriptor.
*
* This detaches the per-instance data descriptor by removing
* it from the device's list and unregistering the kobject from
* the subsystem.
*/
void
interface_remove_data
(
struct
intf_data
*
data
)
{
intf_dev_unlink
(
data
);
list_del_init
(
&
data
->
dev_entry
);
kobject_unregister
(
&
data
->
kobj
);
}
/**
* add - attach device to interface
* @intf: interface.
* @dev: device.
*
* This is just a simple helper. Check the interface's interface
* helper and call it. This is called when adding an interface
* the class's devices, or a device to the class's interfaces.
*/
static
int
add
(
struct
device_interface
*
intf
,
struct
device
*
dev
)
{
int
error
=
0
;
if
(
intf
->
add_device
)
error
=
intf
->
add_device
(
dev
);
pr_debug
(
" -> %s (%d)
\n
"
,
dev
->
bus_id
,
error
);
return
error
;
}
/**
* del - detach device from interface.
* @data: interface data descriptor.
*
* Another simple helper. Remove the data descriptor from
* the device and the interface, then call the interface's
* remove_device() method.
*/
static
void
del
(
struct
intf_data
*
data
)
{
struct
device_interface
*
intf
=
intf_from_data
(
data
);
pr_debug
(
" -> %s "
,
data
->
intf
->
name
);
interface_remove_data
(
data
);
if
(
intf
->
remove_device
)
intf
->
remove_device
(
data
);
}
#define to_dev(entry) container_of(entry,struct device,class_list)
/**
* add_intf - add class's devices to interface.
* @intf: interface.
*
* Loop over the devices registered with the class, and call
* the interface's add_device() method for each.
*
* On an error, we won't break, but we will print debugging info.
*/
static
void
add_intf
(
struct
device_interface
*
intf
)
{
struct
device_class
*
cls
=
intf
->
devclass
;
struct
list_head
*
entry
;
down_write
(
&
cls
->
subsys
.
rwsem
);
list_for_each
(
entry
,
&
cls
->
devices
)
add
(
intf
,
to_dev
(
entry
));
up_write
(
&
cls
->
subsys
.
rwsem
);
}
/**
* interface_register - register an interface with a device class.
* @intf: interface.
*
* An interface may be loaded after drivers and devices have been
* added to the class. So, we must add each device already known to
* the class to the interface as its registered.
*/
int
interface_register
(
struct
device_interface
*
intf
)
{
struct
device_class
*
cls
=
get_devclass
(
intf
->
devclass
);
int
error
=
0
;
if
(
cls
)
{
pr_debug
(
"register interface '%s' with class '%s'
\n
"
,
intf
->
name
,
cls
->
name
);
strncpy
(
intf
->
kobj
.
name
,
intf
->
name
,
KOBJ_NAME_LEN
);
intf
->
kobj
.
subsys
=
&
cls
->
subsys
;
kobject_register
(
&
intf
->
kobj
);
}
else
error
=
-
EINVAL
;
return
error
;
strncpy
(
intf
->
subsys
.
kobj
.
name
,
intf
->
name
,
KOBJ_NAME_LEN
);
intf
->
subsys
.
kobj
.
subsys
=
&
cls
->
subsys
;
subsystem_register
(
&
intf
->
subsys
);
add_intf
(
intf
);
}
return
0
;
}
/**
* del_intf - remove devices from interface.
* @intf: interface being unloaded.
*
* This loops over the devices registered with a class and
* calls the interface's remove_device() method for each.
* This is called when an interface is being unregistered.
*/
static
void
del_intf
(
struct
device_interface
*
intf
)
{
struct
list_head
*
entry
;
down_write
(
&
intf
->
devclass
->
subsys
.
rwsem
);
list_for_each
(
entry
,
&
intf
->
subsys
.
list
)
{
struct
intf_data
*
data
=
to_data
(
entry
);
del
(
data
);
}
up_write
(
&
intf
->
devclass
->
subsys
.
rwsem
);
}
/**
* interface_unregister - remove interface from class.
* @intf: interface.
*
* This is called when an interface in unloaded, giving it a
* chance to remove itself from devicse that have been added to
* it.
*/
void
interface_unregister
(
struct
device_interface
*
intf
)
{
pr_debug
(
"unregistering interface '%s' from class '%s'
\n
"
,
intf
->
name
,
intf
->
devclass
->
name
);
kobject_unregister
(
&
intf
->
kobj
);
struct
device_class
*
cls
=
intf
->
devclass
;
if
(
cls
)
{
pr_debug
(
"unregistering interface '%s' from class '%s'
\n
"
,
intf
->
name
,
cls
->
name
);
del_intf
(
intf
);
subsystem_unregister
(
&
intf
->
subsys
);
put_devclass
(
cls
);
}
}
int
interface_add
(
struct
device_class
*
cls
,
struct
device
*
dev
)
/**
* interface_add_dev - add device to interfaces.
* @dev: device.
*
* This is a helper for the class driver core. When a
* device is being added to a class, this is called to add
* the device to all the interfaces in the class.
*
* The operation is simple enough: loop over the interfaces
* and call add() [above] for each. The class rwsem is assumed
* to be held.
*/
int
interface_add_dev
(
struct
device
*
dev
)
{
struct
device_class
*
cls
=
dev
->
driver
->
devclass
;
struct
list_head
*
node
;
int
error
=
0
;
pr_debug
(
"
adding '%s' to %s class interfaces
\n
"
,
dev
->
name
,
cls
->
name
);
pr_debug
(
"
interfaces: adding device %s
\n
"
,
dev
->
name
);
list_for_each
(
node
,
&
cls
->
subsys
.
list
)
{
struct
device_interface
*
intf
=
to_intf
(
node
);
if
(
intf
->
add_device
)
{
error
=
intf
->
add_device
(
dev
);
if
(
error
)
pr_debug
(
"%s:%s: adding '%s' failed: %d
\n
"
,
cls
->
name
,
intf
->
name
,
dev
->
name
,
error
);
}
add
(
intf
,
dev
);
}
return
0
;
}
void
interface_remove
(
struct
device_class
*
cls
,
struct
device
*
dev
)
{
struct
list_head
*
node
;
struct
list_head
*
next
;
pr_debug
(
"remove '%s' from %s class interfaces: "
,
dev
->
name
,
cls
->
name
);
/**
* interface_remove_dev - remove device from interfaces.
* @dev: device.
*
* This is another helper for the class driver core, and called
* when the device is being removed from the class.
*
* We iterate over the list of interface data descriptors attached
* to the device, and call del() [above] for each. Again, the
* class's rwsem is assumed to be held during this.
*/
list_for_each_safe
(
node
,
next
,
&
dev
->
intf_list
)
{
struct
intf_data
*
intf_data
=
container_of
(
node
,
struct
intf_data
,
node
);
list_del_init
(
&
intf_data
->
node
)
;
void
interface_remove_dev
(
struct
device
*
dev
)
{
struct
list_head
*
entry
,
*
next
;
intf_dev_unlink
(
intf_data
);
pr_debug
(
"%s "
,
intf_data
->
intf
->
name
);
if
(
intf_data
->
intf
->
remove_device
)
intf_data
->
intf
->
remove_device
(
intf_data
);
}
pr_debug
(
"
\n
"
);
}
pr_debug
(
"interfaces: removing device %s
\n
"
,
dev
->
name
);
int
interface_add_data
(
struct
intf_data
*
data
)
{
down_write
(
&
data
->
intf
->
devclass
->
subsys
.
rwsem
);
list_add_tail
(
&
data
->
node
,
&
data
->
dev
->
intf_list
);
data
->
intf_num
=
data
->
intf
->
devnum
++
;
intf_dev_link
(
data
);
up_write
(
&
data
->
intf
->
devclass
->
subsys
.
rwsem
);
return
0
;
list_for_each_safe
(
entry
,
next
,
&
dev
->
intf_list
)
{
struct
intf_data
*
intf_data
=
to_data
(
entry
);
del
(
intf_data
);
}
}
EXPORT_SYMBOL
(
interface_register
);
...
...
drivers/base/node.c
View file @
8bed75c8
...
...
@@ -93,7 +93,7 @@ int __init register_node(struct node *node, int num, struct node *parent)
static
int
__init
register_node_type
(
void
)
{
d
river_register
(
&
node_driver
);
return
d
evclass_register
(
&
node_devclass
);
d
evclass_register
(
&
node_devclass
);
return
d
river_register
(
&
node_driver
);
}
postcore_initcall
(
register_node_type
);
drivers/base/power.c
View file @
8bed75c8
...
...
@@ -15,7 +15,9 @@
#include <asm/semaphore.h>
#include "base.h"
#define to_dev(node) container_of(node,struct device,g_list)
#define to_dev(node) container_of(node,struct device,kobj.entry)
extern
struct
subsystem
device_subsys
;
/**
* device_suspend - suspend/remove all devices on the device ree
...
...
@@ -35,8 +37,8 @@ int device_suspend(u32 state, u32 level)
printk
(
KERN_EMERG
"Suspending devices
\n
"
);
down
(
&
device_
sem
);
list_for_each
(
node
,
&
global_device_
list
)
{
down
_write
(
&
device_subsys
.
rw
sem
);
list_for_each
(
node
,
&
device_subsys
.
list
)
{
struct
device
*
dev
=
to_dev
(
node
);
if
(
dev
->
driver
&&
dev
->
driver
->
suspend
)
{
pr_debug
(
"suspending device %s
\n
"
,
dev
->
name
);
...
...
@@ -45,7 +47,7 @@ int device_suspend(u32 state, u32 level)
printk
(
KERN_ERR
"%s: suspend returned %d
\n
"
,
dev
->
name
,
error
);
}
}
up
(
&
device_
sem
);
up
_write
(
&
device_subsys
.
rw
sem
);
return
error
;
}
...
...
@@ -61,15 +63,15 @@ void device_resume(u32 level)
{
struct
list_head
*
node
;
down
(
&
device_
sem
);
list_for_each_prev
(
node
,
&
global_device_
list
)
{
down
_write
(
&
device_subsys
.
rw
sem
);
list_for_each_prev
(
node
,
&
device_subsys
.
list
)
{
struct
device
*
dev
=
to_dev
(
node
);
if
(
dev
->
driver
&&
dev
->
driver
->
resume
)
{
pr_debug
(
"resuming device %s
\n
"
,
dev
->
name
);
dev
->
driver
->
resume
(
dev
,
level
);
}
}
up
(
&
device_
sem
);
up
_write
(
&
device_subsys
.
rw
sem
);
printk
(
KERN_EMERG
"Devices Resumed
\n
"
);
}
...
...
@@ -83,15 +85,15 @@ void device_shutdown(void)
printk
(
KERN_EMERG
"Shutting down devices
\n
"
);
down
(
&
device_
sem
);
list_for_each
(
entry
,
&
global_device_
list
)
{
down
_write
(
&
device_subsys
.
rw
sem
);
list_for_each
(
entry
,
&
device_subsys
.
list
)
{
struct
device
*
dev
=
to_dev
(
entry
);
if
(
dev
->
driver
&&
dev
->
driver
->
shutdown
)
{
pr_debug
(
"shutting down %s
\n
"
,
dev
->
name
);
dev
->
driver
->
shutdown
(
dev
);
}
}
up
(
&
device_
sem
);
up
_write
(
&
device_subsys
.
rw
sem
);
}
EXPORT_SYMBOL
(
device_suspend
);
...
...
drivers/block/genhd.c
View file @
8bed75c8
...
...
@@ -410,11 +410,11 @@ struct gendisk *alloc_disk(int minors)
disk
->
minors
=
minors
;
while
(
minors
>>=
1
)
disk
->
minor_shift
++
;
kobject_init
(
&
disk
->
kobj
);
disk
->
kobj
.
subsys
=
&
block_subsys
;
kobject_init
(
&
disk
->
kobj
);
INIT_LIST_HEAD
(
&
disk
->
full_list
);
rand_initialize_disk
(
disk
);
}
rand_initialize_disk
(
disk
);
return
disk
;
}
...
...
drivers/pci/probe.c
View file @
8bed75c8
...
...
@@ -448,6 +448,7 @@ struct pci_dev * __devinit pci_scan_device(struct pci_dev *temp)
/* now put in global tree */
strcpy
(
dev
->
dev
.
bus_id
,
dev
->
slot_name
);
dev
->
dev
.
dma_mask
=
&
dev
->
dma_mask
;
device_register
(
&
dev
->
dev
);
return
dev
;
...
...
fs/partitions/check.c
View file @
8bed75c8
...
...
@@ -377,7 +377,6 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
p
->
start_sect
=
start
;
p
->
nr_sects
=
len
;
devfs_register_partition
(
disk
,
part
);
kobject_init
(
&
p
->
kobj
);
snprintf
(
p
->
kobj
.
name
,
KOBJ_NAME_LEN
,
"%s%d"
,
disk
->
kobj
.
name
,
part
);
p
->
kobj
.
parent
=
&
disk
->
kobj
;
p
->
kobj
.
subsys
=
&
part_subsys
;
...
...
@@ -406,7 +405,7 @@ void register_disk(struct gendisk *disk)
s
=
strchr
(
disk
->
kobj
.
name
,
'/'
);
if
(
s
)
*
s
=
'!'
;
kobject_
register
(
&
disk
->
kobj
);
kobject_
add
(
&
disk
->
kobj
);
disk_sysfs_symlinks
(
disk
);
if
(
disk
->
flags
&
GENHD_FL_CD
)
...
...
@@ -529,8 +528,7 @@ void del_gendisk(struct gendisk *disk)
sysfs_remove_link
(
&
disk
->
driverfs_dev
->
kobj
,
"block"
);
put_device
(
disk
->
driverfs_dev
);
}
kobject_get
(
&
disk
->
kobj
);
/* kobject model is fucked in head */
kobject_unregister
(
&
disk
->
kobj
);
kobject_del
(
&
disk
->
kobj
);
}
struct
dev_name
{
...
...
fs/sysfs/inode.c
View file @
8bed75c8
...
...
@@ -96,9 +96,10 @@ static int sysfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
if
(
!
dentry
->
d_inode
)
{
inode
=
sysfs_get_inode
(
dir
->
i_sb
,
mode
,
dev
);
if
(
inode
)
if
(
inode
)
{
d_instantiate
(
dentry
,
inode
);
else
dget
(
dentry
);
}
else
error
=
-
ENOSPC
;
}
else
error
=
-
EEXIST
;
...
...
@@ -135,14 +136,52 @@ static int sysfs_symlink(struct inode * dir, struct dentry *dentry, const char *
if
(
inode
)
{
int
l
=
strlen
(
symname
)
+
1
;
error
=
page_symlink
(
inode
,
symname
,
l
);
if
(
!
error
)
if
(
!
error
)
{
d_instantiate
(
dentry
,
inode
);
else
dget
(
dentry
);
}
else
iput
(
inode
);
}
return
error
;
}
#define to_subsys(k) container_of(k,struct subsystem,kobj)
#define to_sattr(a) container_of(a,struct subsys_attribute,attr)
/**
* Subsystem file operations.
* These operations allow subsystems to have files that can be
* read/written.
*/
ssize_t
subsys_attr_show
(
struct
kobject
*
kobj
,
struct
attribute
*
attr
,
char
*
page
,
size_t
count
,
loff_t
off
)
{
struct
subsystem
*
s
=
to_subsys
(
kobj
);
struct
subsys_attribute
*
sattr
=
to_sattr
(
attr
);
ssize_t
ret
=
0
;
if
(
sattr
->
show
)
ret
=
sattr
->
show
(
s
,
page
,
count
,
off
);
return
ret
;
}
ssize_t
subsys_attr_store
(
struct
kobject
*
kobj
,
struct
attribute
*
attr
,
const
char
*
page
,
size_t
count
,
loff_t
off
)
{
struct
subsystem
*
s
=
to_subsys
(
kobj
);
struct
subsys_attribute
*
sattr
=
to_sattr
(
attr
);
ssize_t
ret
=
0
;
if
(
sattr
->
store
)
ret
=
sattr
->
store
(
s
,
page
,
count
,
off
);
return
ret
;
}
static
struct
sysfs_ops
subsys_sysfs_ops
=
{
.
show
=
subsys_attr_show
,
.
store
=
subsys_attr_store
,
};
/**
* sysfs_read_file - read an attribute.
* @file: file pointer.
...
...
@@ -263,9 +302,14 @@ static int check_perm(struct inode * inode, struct file * file)
if
(
!
kobj
||
!
attr
)
goto
Einval
;
/* if the kobject has no subsystem, then it is a subsystem itself,
* so give it the subsys_sysfs_ops.
*/
if
(
kobj
->
subsys
)
ops
=
kobj
->
subsys
->
sysfs_ops
;
else
ops
=
&
subsys_sysfs_ops
;
/* No sysfs operations, either from having no subsystem,
* or the subsystem have no operations.
...
...
@@ -571,8 +615,8 @@ static void hash_and_remove(struct dentry * dir, const char * name)
/* make sure dentry is really there */
if
(
victim
->
d_inode
&&
(
victim
->
d_parent
->
d_inode
==
dir
->
d_inode
))
{
d_invalidate
(
victim
);
simple_unlink
(
dir
->
d_inode
,
victim
);
d_delete
(
victim
);
}
}
up
(
&
dir
->
d_inode
->
i_sem
);
...
...
@@ -631,15 +675,15 @@ void sysfs_remove_dir(struct kobject * kobj)
struct
dentry
*
d
=
list_entry
(
node
,
struct
dentry
,
d_child
);
/* make sure dentry is still there */
if
(
d
->
d_inode
)
{
d_invalidate
(
d
);
simple_unlink
(
dentry
->
d_inode
,
d
);
d_delete
(
dentry
);
}
}
up
(
&
dentry
->
d_inode
->
i_sem
);
d_invalidate
(
dentry
);
simple_rmdir
(
parent
->
d_inode
,
dentry
);
d_delete
(
dentry
);
up
(
&
parent
->
d_inode
->
i_sem
);
dput
(
parent
);
}
...
...
include/linux/device.h
View file @
8bed75c8
...
...
@@ -85,6 +85,15 @@ extern struct bus_type * get_bus(struct bus_type * bus);
extern
void
put_bus
(
struct
bus_type
*
bus
);
/* iterator helpers for buses */
int
bus_for_each_dev
(
struct
bus_type
*
bus
,
struct
device
*
start
,
void
*
data
,
int
(
*
fn
)(
struct
device
*
,
void
*
));
int
bus_for_each_drv
(
struct
bus_type
*
bus
,
struct
device_driver
*
start
,
void
*
data
,
int
(
*
fn
)(
struct
device_driver
*
,
void
*
));
/* driverfs interface for exporting bus attributes */
struct
bus_attribute
{
...
...
@@ -159,6 +168,7 @@ struct device_class {
struct
subsystem
devsubsys
;
struct
subsystem
drvsubsys
;
struct
list_head
drivers
;
struct
list_head
devices
;
int
(
*
add_device
)(
struct
device
*
);
void
(
*
remove_device
)(
struct
device
*
);
...
...
@@ -207,9 +217,7 @@ struct device_interface {
char
*
name
;
struct
device_class
*
devclass
;
struct
kobject
kobj
;
struct
list_head
devices
;
struct
subsystem
subsys
;
u32
devnum
;
int
(
*
add_device
)
(
struct
device
*
);
...
...
@@ -230,10 +238,11 @@ extern void interface_unregister(struct device_interface *);
* and create a driverfs symlink for it.
*/
struct
intf_data
{
struct
list_head
node
;
struct
device_interface
*
intf
;
struct
device
*
dev
;
u32
intf_num
;
struct
list_head
dev_entry
;
struct
kobject
kobj
;
};
extern
int
interface_add_data
(
struct
intf_data
*
);
...
...
@@ -241,9 +250,9 @@ extern int interface_add_data(struct intf_data *);
struct
device
{
struct
list_head
g_list
;
/* node in depth-first order list */
struct
list_head
node
;
/* node in sibling list */
struct
list_head
bus_list
;
/* node in bus's list */
struct
list_head
class_list
;
struct
list_head
driver_list
;
struct
list_head
children
;
struct
list_head
intf_list
;
...
...
@@ -270,6 +279,7 @@ struct device {
being off. */
unsigned
char
*
saved_state
;
/* saved device state */
u64
*
dma_mask
;
/* dma mask (if dma'able device) */
void
(
*
release
)(
struct
device
*
dev
);
};
...
...
@@ -280,12 +290,6 @@ list_to_dev(struct list_head *node)
return
list_entry
(
node
,
struct
device
,
node
);
}
static
inline
struct
device
*
g_list_to_dev
(
struct
list_head
*
g_list
)
{
return
list_entry
(
g_list
,
struct
device
,
g_list
);
}
static
inline
void
*
dev_get_drvdata
(
struct
device
*
dev
)
{
...
...
include/linux/kobject.h
View file @
8bed75c8
...
...
@@ -60,4 +60,13 @@ static inline void subsys_put(struct subsystem * s)
kobject_put
(
&
s
->
kobj
);
}
struct
subsys_attribute
{
struct
attribute
attr
;
ssize_t
(
*
show
)(
struct
subsystem
*
,
char
*
,
size_t
,
loff_t
);
ssize_t
(
*
store
)(
struct
subsystem
*
,
const
char
*
,
size_t
,
loff_t
);
};
extern
int
subsys_create_file
(
struct
subsystem
*
,
struct
subsys_attribute
*
);
extern
void
subsys_remove_file
(
struct
subsystem
*
,
struct
subsys_attribute
*
);
#endif
/* _KOBJECT_H_ */
lib/kobject.c
View file @
8bed75c8
...
...
@@ -110,8 +110,7 @@ int kobject_register(struct kobject * kobj)
if
(
kobj
)
{
kobject_init
(
kobj
);
error
=
kobject_add
(
kobj
);
if
(
error
)
kobject_cleanup
(
kobj
);
WARN_ON
(
error
);
}
else
error
=
-
EINVAL
;
return
error
;
...
...
@@ -229,6 +228,38 @@ void subsystem_unregister(struct subsystem * s)
}
/**
* subsystem_create_file - export sysfs attribute file.
* @s: subsystem.
* @a: subsystem attribute descriptor.
*/
int
subsys_create_file
(
struct
subsystem
*
s
,
struct
subsys_attribute
*
a
)
{
int
error
=
0
;
if
(
subsys_get
(
s
))
{
error
=
sysfs_create_file
(
&
s
->
kobj
,
&
a
->
attr
);
subsys_put
(
s
);
}
return
error
;
}
/**
* subsystem_remove_file - remove sysfs attribute file.
* @s: subsystem.
* @a: attribute desciptor.
*/
void
subsys_remove_file
(
struct
subsystem
*
s
,
struct
subsys_attribute
*
a
)
{
if
(
subsys_get
(
s
))
{
sysfs_remove_file
(
&
s
->
kobj
,
&
a
->
attr
);
subsys_put
(
s
);
}
}
EXPORT_SYMBOL
(
kobject_init
);
EXPORT_SYMBOL
(
kobject_register
);
EXPORT_SYMBOL
(
kobject_unregister
);
...
...
@@ -238,3 +269,5 @@ EXPORT_SYMBOL(kobject_put);
EXPORT_SYMBOL
(
subsystem_init
);
EXPORT_SYMBOL
(
subsystem_register
);
EXPORT_SYMBOL
(
subsystem_unregister
);
EXPORT_SYMBOL
(
subsys_create_file
);
EXPORT_SYMBOL
(
subsys_remove_file
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment