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