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
487680ca
Commit
487680ca
authored
Oct 17, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://ldm.bkbits.net/linux-2.5-core
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
d103bdbf
879a1092
Changes
22
Show whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
466 additions
and
392 deletions
+466
-392
arch/arm/kernel/ecard.c
arch/arm/kernel/ecard.c
+1
-1
drivers/base/base.h
drivers/base/base.h
+4
-3
drivers/base/bus.c
drivers/base/bus.c
+193
-48
drivers/base/class.c
drivers/base/class.c
+96
-36
drivers/base/core.c
drivers/base/core.c
+35
-180
drivers/base/driver.c
drivers/base/driver.c
+57
-50
drivers/base/interface.c
drivers/base/interface.c
+1
-1
drivers/base/power.c
drivers/base/power.c
+31
-37
drivers/base/sys.c
drivers/base/sys.c
+4
-2
drivers/input/serio/sa1111ps2.c
drivers/input/serio/sa1111ps2.c
+1
-1
drivers/pci/pci-driver.c
drivers/pci/pci-driver.c
+1
-1
drivers/pcmcia/sa1111_generic.c
drivers/pcmcia/sa1111_generic.c
+1
-1
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_debug.c
+1
-2
drivers/scsi/sd.c
drivers/scsi/sd.c
+1
-1
drivers/scsi/sg.c
drivers/scsi/sg.c
+1
-1
drivers/scsi/sr.c
drivers/scsi/sr.c
+1
-1
drivers/scsi/st.c
drivers/scsi/st.c
+1
-1
drivers/usb/core/usb.c
drivers/usb/core/usb.c
+2
-2
drivers/usb/host/ohci-sa1111.c
drivers/usb/host/ohci-sa1111.c
+1
-1
fs/driverfs/inode.c
fs/driverfs/inode.c
+3
-1
include/linux/device.h
include/linux/device.h
+30
-19
include/linux/driverfs_fs.h
include/linux/driverfs_fs.h
+0
-2
No files found.
arch/arm/kernel/ecard.c
View file @
487680ca
...
@@ -1114,7 +1114,7 @@ int ecard_register_driver(struct ecard_driver *drv)
...
@@ -1114,7 +1114,7 @@ int ecard_register_driver(struct ecard_driver *drv)
void
ecard_remove_driver
(
struct
ecard_driver
*
drv
)
void
ecard_remove_driver
(
struct
ecard_driver
*
drv
)
{
{
remove_driv
er
(
&
drv
->
drv
);
driver_unregist
er
(
&
drv
->
drv
);
}
}
static
int
ecard_match
(
struct
device
*
_dev
,
struct
device_driver
*
_drv
)
static
int
ecard_match
(
struct
device
*
_dev
,
struct
device_driver
*
_drv
)
...
...
drivers/base/base.h
View file @
487680ca
...
@@ -8,6 +8,7 @@
...
@@ -8,6 +8,7 @@
extern
struct
list_head
global_device_list
;
extern
struct
list_head
global_device_list
;
extern
spinlock_t
device_lock
;
extern
spinlock_t
device_lock
;
extern
struct
semaphore
device_sem
;
extern
struct
device
*
get_device_locked
(
struct
device
*
);
extern
struct
device
*
get_device_locked
(
struct
device
*
);
...
@@ -20,6 +21,9 @@ extern void device_remove_dir(struct device * dev);
...
@@ -20,6 +21,9 @@ extern void device_remove_dir(struct device * dev);
extern
int
bus_make_dir
(
struct
bus_type
*
bus
);
extern
int
bus_make_dir
(
struct
bus_type
*
bus
);
extern
void
bus_remove_dir
(
struct
bus_type
*
bus
);
extern
void
bus_remove_dir
(
struct
bus_type
*
bus
);
extern
int
bus_add_driver
(
struct
device_driver
*
);
extern
void
bus_remove_driver
(
struct
device_driver
*
);
extern
int
driver_make_dir
(
struct
device_driver
*
drv
);
extern
int
driver_make_dir
(
struct
device_driver
*
drv
);
extern
void
driver_remove_dir
(
struct
device_driver
*
drv
);
extern
void
driver_remove_dir
(
struct
device_driver
*
drv
);
...
@@ -48,9 +52,6 @@ extern int interface_add(struct device_class *, struct device *);
...
@@ -48,9 +52,6 @@ extern int interface_add(struct device_class *, struct device *);
extern
void
interface_remove
(
struct
device_class
*
,
struct
device
*
);
extern
void
interface_remove
(
struct
device_class
*
,
struct
device
*
);
extern
int
driver_attach
(
struct
device_driver
*
drv
);
extern
void
driver_detach
(
struct
device_driver
*
drv
);
#ifdef CONFIG_HOTPLUG
#ifdef CONFIG_HOTPLUG
extern
int
dev_hotplug
(
struct
device
*
dev
,
const
char
*
action
);
extern
int
dev_hotplug
(
struct
device
*
dev
,
const
char
*
action
);
#else
#else
...
...
drivers/base/bus.c
View file @
487680ca
...
@@ -43,28 +43,23 @@ int bus_for_each_dev(struct bus_type * bus, void * data,
...
@@ -43,28 +43,23 @@ int bus_for_each_dev(struct bus_type * bus, void * data,
int
(
*
callback
)(
struct
device
*
dev
,
void
*
data
))
int
(
*
callback
)(
struct
device
*
dev
,
void
*
data
))
{
{
struct
list_head
*
node
;
struct
list_head
*
node
;
struct
device
*
prev
=
NULL
;
int
error
=
0
;
int
error
=
0
;
get_bus
(
bus
);
bus
=
get_bus
(
bus
);
spin_lock
(
&
device_lock
);
if
(
bus
)
{
down_read
(
&
bus
->
rwsem
);
list_for_each
(
node
,
&
bus
->
devices
)
{
list_for_each
(
node
,
&
bus
->
devices
)
{
struct
device
*
dev
=
get_device_locked
(
to_dev
(
node
));
struct
device
*
dev
=
get_device
(
to_dev
(
node
));
if
(
dev
)
{
if
(
dev
)
{
spin_unlock
(
&
device_lock
);
error
=
callback
(
dev
,
data
);
error
=
callback
(
dev
,
data
);
if
(
prev
)
put_device
(
dev
);
put_device
(
prev
);
prev
=
dev
;
spin_lock
(
&
device_lock
);
if
(
error
)
if
(
error
)
break
;
break
;
}
}
}
}
spin_unlock
(
&
device_lock
);
up_read
(
&
bus
->
rwsem
);
if
(
prev
)
put_device
(
prev
);
put_bus
(
bus
);
put_bus
(
bus
);
}
return
error
;
return
error
;
}
}
...
@@ -72,33 +67,126 @@ int bus_for_each_drv(struct bus_type * bus, void * data,
...
@@ -72,33 +67,126 @@ int bus_for_each_drv(struct bus_type * bus, void * data,
int
(
*
callback
)(
struct
device_driver
*
drv
,
void
*
data
))
int
(
*
callback
)(
struct
device_driver
*
drv
,
void
*
data
))
{
{
struct
list_head
*
node
;
struct
list_head
*
node
;
struct
device_driver
*
prev
=
NULL
;
int
error
=
0
;
int
error
=
0
;
/* pin bus in memory */
bus
=
get_bus
(
bus
);
get_bus
(
bus
);
if
(
bus
)
{
down_read
(
&
bus
->
rwsem
);
spin_lock
(
&
device_lock
);
list_for_each
(
node
,
&
bus
->
drivers
)
{
list_for_each
(
node
,
&
bus
->
drivers
)
{
struct
device_driver
*
drv
=
get_driver
(
to_drv
(
node
));
struct
device_driver
*
drv
=
get_driver
(
to_drv
(
node
));
if
(
drv
)
{
if
(
drv
)
{
spin_unlock
(
&
device_lock
);
error
=
callback
(
drv
,
data
);
error
=
callback
(
drv
,
data
);
if
(
prev
)
put_driver
(
drv
);
put_driver
(
prev
);
prev
=
drv
;
spin_lock
(
&
device_lock
);
if
(
error
)
if
(
error
)
break
;
break
;
}
}
}
}
spin_unlock
(
&
device_lock
);
up_read
(
&
bus
->
rwsem
);
if
(
prev
)
put_driver
(
prev
);
put_bus
(
bus
);
put_bus
(
bus
);
}
return
error
;
}
static
void
attach
(
struct
device
*
dev
)
{
pr_debug
(
"bound device '%s' to driver '%s'
\n
"
,
dev
->
bus_id
,
dev
->
driver
->
name
);
list_add_tail
(
&
dev
->
driver_list
,
&
dev
->
driver
->
devices
);
}
static
int
bus_match
(
struct
device
*
dev
,
struct
device_driver
*
drv
)
{
int
error
=
0
;
if
(
dev
->
bus
->
match
(
dev
,
drv
))
{
dev
->
driver
=
drv
;
if
(
drv
->
probe
)
{
if
(
!
(
error
=
drv
->
probe
(
dev
)))
attach
(
dev
);
else
dev
->
driver
=
NULL
;
}
}
return
error
;
return
error
;
}
}
static
int
device_attach
(
struct
device
*
dev
)
{
struct
bus_type
*
bus
=
dev
->
bus
;
struct
list_head
*
entry
;
int
error
=
0
;
if
(
dev
->
driver
)
{
attach
(
dev
);
return
0
;
}
if
(
!
bus
->
match
)
return
0
;
list_for_each
(
entry
,
&
bus
->
drivers
)
{
struct
device_driver
*
drv
=
get_driver
(
container_of
(
entry
,
struct
device_driver
,
bus_list
));
if
(
!
drv
)
continue
;
error
=
bus_match
(
dev
,
drv
);
put_driver
(
drv
);
if
(
!
error
)
break
;
}
return
error
;
}
static
int
driver_attach
(
struct
device_driver
*
drv
)
{
struct
bus_type
*
bus
=
drv
->
bus
;
struct
list_head
*
entry
;
int
error
=
0
;
if
(
!
bus
->
match
)
return
0
;
list_for_each
(
entry
,
&
bus
->
devices
)
{
struct
device
*
dev
=
container_of
(
entry
,
struct
device
,
bus_list
);
if
(
get_device
(
dev
))
{
if
(
!
dev
->
driver
)
{
if
(
!
bus_match
(
dev
,
drv
)
&&
dev
->
driver
)
devclass_add_device
(
dev
);
}
put_device
(
dev
);
}
}
return
error
;
}
static
void
detach
(
struct
device
*
dev
,
struct
device_driver
*
drv
)
{
if
(
drv
)
{
list_del_init
(
&
dev
->
driver_list
);
devclass_remove_device
(
dev
);
if
(
drv
->
remove
)
drv
->
remove
(
dev
);
dev
->
driver
=
NULL
;
}
}
static
void
device_detach
(
struct
device
*
dev
)
{
detach
(
dev
,
dev
->
driver
);
}
static
void
driver_detach
(
struct
device_driver
*
drv
)
{
struct
list_head
*
entry
,
*
next
;
list_for_each_safe
(
entry
,
next
,
&
drv
->
devices
)
{
struct
device
*
dev
=
container_of
(
entry
,
struct
device
,
driver_list
);
if
(
get_device
(
dev
))
{
detach
(
dev
,
drv
);
put_device
(
dev
);
}
}
}
/**
/**
* bus_add_device - add device to bus
* bus_add_device - add device to bus
* @dev: device being added
* @dev: device being added
...
@@ -110,12 +198,13 @@ int bus_for_each_drv(struct bus_type * bus, void * data,
...
@@ -110,12 +198,13 @@ int bus_for_each_drv(struct bus_type * bus, void * data,
*/
*/
int
bus_add_device
(
struct
device
*
dev
)
int
bus_add_device
(
struct
device
*
dev
)
{
{
if
(
dev
->
bus
)
{
struct
bus_type
*
bus
=
get_bus
(
dev
->
bus
);
pr_debug
(
"registering %s with bus '%s'
\n
"
,
dev
->
bus_id
,
dev
->
bus
->
name
);
if
(
bus
)
{
get_bus
(
dev
->
bus
);
down_write
(
&
dev
->
bus
->
rwsem
);
spin_lock
(
&
device_lock
);
pr_debug
(
"bus %s: add device %s
\n
"
,
bus
->
name
,
dev
->
bus_id
);
list_add_tail
(
&
dev
->
bus_list
,
&
dev
->
bus
->
devices
);
list_add_tail
(
&
dev
->
bus_list
,
&
dev
->
bus
->
devices
);
spin_unlock
(
&
device_lock
);
device_attach
(
dev
);
up_write
(
&
dev
->
bus
->
rwsem
);
device_bus_link
(
dev
);
device_bus_link
(
dev
);
}
}
return
0
;
return
0
;
...
@@ -131,17 +220,70 @@ int bus_add_device(struct device * dev)
...
@@ -131,17 +220,70 @@ int bus_add_device(struct device * dev)
void
bus_remove_device
(
struct
device
*
dev
)
void
bus_remove_device
(
struct
device
*
dev
)
{
{
if
(
dev
->
bus
)
{
if
(
dev
->
bus
)
{
down_write
(
&
dev
->
bus
->
rwsem
);
pr_debug
(
"bus %s: remove device %s
\n
"
,
dev
->
bus
->
name
,
dev
->
bus_id
);
device_remove_symlink
(
&
dev
->
bus
->
device_dir
,
dev
->
bus_id
);
device_remove_symlink
(
&
dev
->
bus
->
device_dir
,
dev
->
bus_id
);
device_detach
(
dev
);
list_del_init
(
&
dev
->
bus_list
);
up_write
(
&
dev
->
bus
->
rwsem
);
put_bus
(
dev
->
bus
);
put_bus
(
dev
->
bus
);
}
}
}
}
int
bus_add_driver
(
struct
device_driver
*
drv
)
{
struct
bus_type
*
bus
=
get_bus
(
drv
->
bus
);
if
(
bus
)
{
down_write
(
&
bus
->
rwsem
);
pr_debug
(
"bus %s: add driver %s
\n
"
,
bus
->
name
,
drv
->
name
);
list_add_tail
(
&
drv
->
bus_list
,
&
bus
->
drivers
);
driver_attach
(
drv
);
up_write
(
&
bus
->
rwsem
);
driver_make_dir
(
drv
);
}
return
0
;
}
void
bus_remove_driver
(
struct
device_driver
*
drv
)
{
if
(
drv
->
bus
)
{
down_write
(
&
drv
->
bus
->
rwsem
);
pr_debug
(
"bus %s: remove driver %s
\n
"
,
drv
->
bus
->
name
,
drv
->
name
);
driver_detach
(
drv
);
list_del_init
(
&
drv
->
bus_list
);
up_write
(
&
drv
->
bus
->
rwsem
);
}
}
struct
bus_type
*
get_bus
(
struct
bus_type
*
bus
)
{
struct
bus_type
*
ret
=
bus
;
spin_lock
(
&
device_lock
);
if
(
bus
&&
bus
->
present
&&
atomic_read
(
&
bus
->
refcount
))
atomic_inc
(
&
bus
->
refcount
);
else
ret
=
NULL
;
spin_unlock
(
&
device_lock
);
return
ret
;
}
void
put_bus
(
struct
bus_type
*
bus
)
{
if
(
!
atomic_dec_and_lock
(
&
bus
->
refcount
,
&
device_lock
))
return
;
list_del_init
(
&
bus
->
node
);
spin_unlock
(
&
device_lock
);
BUG_ON
(
bus
->
present
);
bus_remove_dir
(
bus
);
}
int
bus_register
(
struct
bus_type
*
bus
)
int
bus_register
(
struct
bus_type
*
bus
)
{
{
rwlock_init
(
&
bus
->
lock
);
init_rwsem
(
&
bus
->
rwsem
);
INIT_LIST_HEAD
(
&
bus
->
devices
);
INIT_LIST_HEAD
(
&
bus
->
devices
);
INIT_LIST_HEAD
(
&
bus
->
drivers
);
INIT_LIST_HEAD
(
&
bus
->
drivers
);
atomic_set
(
&
bus
->
refcount
,
2
);
atomic_set
(
&
bus
->
refcount
,
2
);
bus
->
present
=
1
;
spin_lock
(
&
device_lock
);
spin_lock
(
&
device_lock
);
list_add_tail
(
&
bus
->
node
,
&
bus_driver_list
);
list_add_tail
(
&
bus
->
node
,
&
bus_driver_list
);
...
@@ -156,13 +298,14 @@ int bus_register(struct bus_type * bus)
...
@@ -156,13 +298,14 @@ int bus_register(struct bus_type * bus)
return
0
;
return
0
;
}
}
void
put_bus
(
struct
bus_type
*
bus
)
void
bus_unregister
(
struct
bus_type
*
bus
)
{
{
if
(
!
atomic_dec_and_lock
(
&
bus
->
refcount
,
&
device_lock
))
spin_lock
(
&
device_lock
);
return
;
bus
->
present
=
0
;
list_del_init
(
&
bus
->
node
);
spin_unlock
(
&
device_lock
);
spin_unlock
(
&
device_lock
);
bus_remove_dir
(
bus
);
pr_debug
(
"bus %s: unregistering
\n
"
,
bus
->
name
);
put_bus
(
bus
);
}
}
EXPORT_SYMBOL
(
bus_for_each_dev
);
EXPORT_SYMBOL
(
bus_for_each_dev
);
...
@@ -170,4 +313,6 @@ EXPORT_SYMBOL(bus_for_each_drv);
...
@@ -170,4 +313,6 @@ EXPORT_SYMBOL(bus_for_each_drv);
EXPORT_SYMBOL
(
bus_add_device
);
EXPORT_SYMBOL
(
bus_add_device
);
EXPORT_SYMBOL
(
bus_remove_device
);
EXPORT_SYMBOL
(
bus_remove_device
);
EXPORT_SYMBOL
(
bus_register
);
EXPORT_SYMBOL
(
bus_register
);
EXPORT_SYMBOL
(
bus_unregister
);
EXPORT_SYMBOL
(
get_bus
);
EXPORT_SYMBOL
(
put_bus
);
EXPORT_SYMBOL
(
put_bus
);
drivers/base/class.c
View file @
487680ca
...
@@ -10,27 +10,29 @@ static LIST_HEAD(class_list);
...
@@ -10,27 +10,29 @@ static LIST_HEAD(class_list);
int
devclass_add_driver
(
struct
device_driver
*
drv
)
int
devclass_add_driver
(
struct
device_driver
*
drv
)
{
{
if
(
drv
->
devclass
)
{
struct
device_class
*
cls
=
get_devclass
(
drv
->
devclass
);
pr_debug
(
"Registering driver %s:%s with class %s
\n
"
,
if
(
cls
)
{
drv
->
bus
->
name
,
drv
->
name
,
drv
->
devclass
->
name
);
down_write
(
&
cls
->
rwsem
);
pr_debug
(
"device class %s: adding driver %s:%s
\n
"
,
spin_lock
(
&
device_lock
);
cls
->
name
,
drv
->
bus
->
name
,
drv
->
name
);
list_add_tail
(
&
drv
->
class_list
,
&
drv
->
devclass
->
drivers
);
list_add_tail
(
&
drv
->
class_list
,
&
cls
->
drivers
);
spin_unlock
(
&
device_lock
);
devclass_drv_link
(
drv
);
devclass_drv_link
(
drv
);
up_write
(
&
cls
->
rwsem
);
}
}
return
0
;
return
0
;
}
}
void
devclass_remove_driver
(
struct
device_driver
*
drv
)
void
devclass_remove_driver
(
struct
device_driver
*
drv
)
{
{
if
(
drv
->
devclass
)
{
struct
device_class
*
cls
=
drv
->
devclass
;
pr_debug
(
"Removing driver %s:%s:%s
\n
"
,
if
(
cls
)
{
drv
->
devclass
->
name
,
drv
->
bus
->
name
,
drv
->
name
);
down_write
(
&
cls
->
rwsem
);
spin_lock
(
&
device_lock
);
pr_debug
(
"device class %s: removing driver %s:%s
\n
"
,
cls
->
name
,
drv
->
bus
->
name
,
drv
->
name
);
list_del_init
(
&
drv
->
class_list
);
list_del_init
(
&
drv
->
class_list
);
spin_unlock
(
&
device_lock
);
devclass_drv_unlink
(
drv
);
devclass_drv_unlink
(
drv
);
up_write
(
&
cls
->
rwsem
);
put_devclass
(
cls
);
}
}
}
}
...
@@ -38,9 +40,7 @@ void devclass_remove_driver(struct device_driver * drv)
...
@@ -38,9 +40,7 @@ void devclass_remove_driver(struct device_driver * drv)
static
void
enum_device
(
struct
device_class
*
cls
,
struct
device
*
dev
)
static
void
enum_device
(
struct
device_class
*
cls
,
struct
device
*
dev
)
{
{
u32
val
;
u32
val
;
spin_lock
(
&
device_lock
);
val
=
cls
->
devnum
++
;
val
=
cls
->
devnum
++
;
spin_unlock
(
&
device_lock
);
dev
->
class_num
=
val
;
dev
->
class_num
=
val
;
devclass_dev_link
(
cls
,
dev
);
devclass_dev_link
(
cls
,
dev
);
}
}
...
@@ -51,59 +51,119 @@ static void unenum_device(struct device_class * cls, struct device * dev)
...
@@ -51,59 +51,119 @@ static void unenum_device(struct device_class * cls, struct device * dev)
dev
->
class_num
=
0
;
dev
->
class_num
=
0
;
}
}
/**
* devclass_add_device - register device with device class
* @dev: device to be registered
*
* This is called when a device is either registered with the
* core, or after the a driver module is loaded and bound to
* the device.
* The class is determined by looking at @dev's driver, so one
* way or another, it must be bound to something. Once the
* class is determined, it's set to prevent against concurrent
* calls for the same device stomping on each other.
*
* /sbin/hotplug should be called once the device is added to
* class and all the interfaces.
*/
int
devclass_add_device
(
struct
device
*
dev
)
int
devclass_add_device
(
struct
device
*
dev
)
{
{
struct
device_class
*
cls
=
dev
->
driver
->
devclass
;
struct
device_class
*
cls
;
int
error
=
0
;
int
error
=
0
;
if
(
dev
->
driver
)
{
cls
=
get_devclass
(
dev
->
driver
->
devclass
);
if
(
cls
)
{
if
(
cls
)
{
pr_debug
(
"adding device '%s' to class '%s'
\n
"
,
down_write
(
&
cls
->
rwsem
);
dev
->
name
,
cls
->
name
);
pr_debug
(
"device class %s: adding device %s
\n
"
,
cls
->
name
,
dev
->
name
);
if
(
cls
->
add_device
)
if
(
cls
->
add_device
)
error
=
cls
->
add_device
(
dev
);
error
=
cls
->
add_device
(
dev
);
if
(
!
error
)
{
if
(
!
error
)
{
enum_device
(
cls
,
dev
);
enum_device
(
cls
,
dev
);
interface_add
(
cls
,
dev
);
interface_add
(
cls
,
dev
);
}
}
/* notify userspace (call /sbin/hotplug) here */
up_write
(
&
cls
->
rwsem
);
if
(
error
)
put_devclass
(
cls
);
}
}
}
return
error
;
return
error
;
}
}
void
devclass_remove_device
(
struct
device
*
dev
)
void
devclass_remove_device
(
struct
device
*
dev
)
{
{
struct
device_class
*
cls
=
dev
->
driver
->
devclass
;
struct
device_class
*
cls
;
if
(
dev
->
driver
)
{
cls
=
dev
->
driver
->
devclass
;
if
(
cls
)
{
if
(
cls
)
{
pr_debug
(
"removing device '%s' from class '%s'
\n
"
,
down_write
(
&
cls
->
rwsem
);
dev
->
name
,
cls
->
name
);
pr_debug
(
"device class %s: removing device %s
\n
"
,
cls
->
name
,
dev
->
name
);
interface_remove
(
cls
,
dev
);
interface_remove
(
cls
,
dev
);
unenum_device
(
cls
,
dev
);
unenum_device
(
cls
,
dev
);
if
(
cls
->
remove_device
)
if
(
cls
->
remove_device
)
cls
->
remove_device
(
dev
);
cls
->
remove_device
(
dev
);
up_write
(
&
cls
->
rwsem
);
put_devclass
(
cls
);
}
}
}
}
struct
device_class
*
get_devclass
(
struct
device_class
*
cls
)
{
struct
device_class
*
ret
=
cls
;
spin_lock
(
&
device_lock
);
if
(
cls
&&
cls
->
present
&&
atomic_read
(
&
cls
->
refcount
)
>
0
)
atomic_inc
(
&
cls
->
refcount
);
else
ret
=
NULL
;
spin_unlock
(
&
device_lock
);
return
ret
;
}
}
void
put_devclass
(
struct
device_class
*
cls
)
{
if
(
atomic_dec_and_lock
(
&
cls
->
refcount
,
&
device_lock
))
{
list_del_init
(
&
cls
->
node
);
spin_unlock
(
&
device_lock
);
devclass_remove_dir
(
cls
);
}
}
int
devclass_register
(
struct
device_class
*
cls
)
int
devclass_register
(
struct
device_class
*
cls
)
{
{
INIT_LIST_HEAD
(
&
cls
->
drivers
);
INIT_LIST_HEAD
(
&
cls
->
drivers
);
INIT_LIST_HEAD
(
&
cls
->
intf_list
);
INIT_LIST_HEAD
(
&
cls
->
intf_list
);
init_rwsem
(
&
cls
->
rwsem
);
pr_debug
(
"registering device class '%s'
\n
"
,
cls
->
name
);
atomic_set
(
&
cls
->
refcount
,
2
);
cls
->
present
=
1
;
pr_debug
(
"device class '%s': registering
\n
"
,
cls
->
name
);
spin_lock
(
&
device_lock
);
spin_lock
(
&
device_lock
);
list_add_tail
(
&
cls
->
node
,
&
class_list
);
list_add_tail
(
&
cls
->
node
,
&
class_list
);
spin_unlock
(
&
device_lock
);
spin_unlock
(
&
device_lock
);
devclass_make_dir
(
cls
);
devclass_make_dir
(
cls
);
put_devclass
(
cls
);
return
0
;
return
0
;
}
}
void
devclass_unregister
(
struct
device_class
*
cls
)
void
devclass_unregister
(
struct
device_class
*
cls
)
{
{
pr_debug
(
"unregistering device class '%s'
\n
"
,
cls
->
name
);
devclass_remove_dir
(
cls
);
spin_lock
(
&
device_lock
);
spin_lock
(
&
device_lock
);
list_del_init
(
&
class_list
)
;
cls
->
present
=
0
;
spin_unlock
(
&
device_lock
);
spin_unlock
(
&
device_lock
);
pr_debug
(
"device class '%s': unregistering
\n
"
,
cls
->
name
);
put_devclass
(
cls
);
}
}
EXPORT_SYMBOL
(
devclass_register
);
EXPORT_SYMBOL
(
devclass_register
);
EXPORT_SYMBOL
(
devclass_unregister
);
EXPORT_SYMBOL
(
devclass_unregister
);
EXPORT_SYMBOL
(
get_devclass
);
EXPORT_SYMBOL
(
put_devclass
);
drivers/base/core.c
View file @
487680ca
...
@@ -19,136 +19,12 @@ LIST_HEAD(global_device_list);
...
@@ -19,136 +19,12 @@ LIST_HEAD(global_device_list);
int
(
*
platform_notify
)(
struct
device
*
dev
)
=
NULL
;
int
(
*
platform_notify
)(
struct
device
*
dev
)
=
NULL
;
int
(
*
platform_notify_remove
)(
struct
device
*
dev
)
=
NULL
;
int
(
*
platform_notify_remove
)(
struct
device
*
dev
)
=
NULL
;
DECLARE_MUTEX
(
device_sem
);
spinlock_t
device_lock
=
SPIN_LOCK_UNLOCKED
;
spinlock_t
device_lock
=
SPIN_LOCK_UNLOCKED
;
#define to_dev(node) container_of(node,struct device,driver_list)
#define to_dev(node) container_of(node,struct device,driver_list)
static
int
probe
(
struct
device
*
dev
,
struct
device_driver
*
drv
)
{
dev
->
driver
=
drv
;
return
drv
->
probe
?
drv
->
probe
(
dev
)
:
0
;
}
static
void
attach
(
struct
device
*
dev
)
{
spin_lock
(
&
device_lock
);
list_add_tail
(
&
dev
->
driver_list
,
&
dev
->
driver
->
devices
);
spin_unlock
(
&
device_lock
);
devclass_add_device
(
dev
);
}
/**
* found_match - do actual binding of device to driver
* @dev: device
* @drv: driver
*
* We're here because the bus's match callback returned success for this
* pair. We call the driver's probe callback to verify they're really a
* match made in heaven.
*
* In the future, we may want to notify userspace of the binding. (But,
* we might not want to do it here).
*
* We may also want to create a symlink in the driver's directory to the
* device's physical directory.
*/
static
int
found_match
(
struct
device
*
dev
,
struct
device_driver
*
drv
)
{
int
error
=
0
;
if
(
!
(
error
=
probe
(
dev
,
get_driver
(
drv
))))
{
pr_debug
(
"bound device '%s' to driver '%s'
\n
"
,
dev
->
bus_id
,
drv
->
name
);
attach
(
dev
);
}
else
{
put_driver
(
drv
);
dev
->
driver
=
NULL
;
}
return
error
;
}
/**
* device_attach - try to associated device with a driver
* @drv: current driver to try
* @data: device in disguise
*
* This function is used as a callback to bus_for_each_drv.
* It calls the bus's match callback to check if the driver supports
* the device. If so, it calls the found_match() function above to
* take care of all the details.
*/
static
int
do_device_attach
(
struct
device_driver
*
drv
,
void
*
data
)
{
struct
device
*
dev
=
(
struct
device
*
)
data
;
int
error
=
0
;
if
(
drv
->
bus
->
match
&&
drv
->
bus
->
match
(
dev
,
drv
))
error
=
found_match
(
dev
,
drv
);
return
error
;
}
static
int
device_attach
(
struct
device
*
dev
)
{
int
error
=
0
;
if
(
!
dev
->
driver
)
{
if
(
dev
->
bus
)
error
=
bus_for_each_drv
(
dev
->
bus
,
dev
,
do_device_attach
);
}
else
attach
(
dev
);
return
error
;
}
static
void
device_detach
(
struct
device
*
dev
)
{
struct
device_driver
*
drv
=
dev
->
driver
;
if
(
drv
)
{
devclass_remove_device
(
dev
);
if
(
drv
&&
drv
->
remove
)
drv
->
remove
(
dev
);
dev
->
driver
=
NULL
;
}
}
static
int
do_driver_attach
(
struct
device
*
dev
,
void
*
data
)
{
struct
device_driver
*
drv
=
(
struct
device_driver
*
)
data
;
int
error
=
0
;
if
(
!
dev
->
driver
)
{
if
(
dev
->
bus
->
match
&&
dev
->
bus
->
match
(
dev
,
drv
))
error
=
found_match
(
dev
,
drv
);
}
return
error
;
}
int
driver_attach
(
struct
device_driver
*
drv
)
{
return
bus_for_each_dev
(
drv
->
bus
,
drv
,
do_driver_attach
);
}
void
driver_detach
(
struct
device_driver
*
drv
)
{
struct
list_head
*
node
;
struct
device
*
prev
=
NULL
;
spin_lock
(
&
device_lock
);
list_for_each
(
node
,
&
drv
->
devices
)
{
struct
device
*
dev
=
get_device_locked
(
to_dev
(
node
));
if
(
dev
)
{
if
(
prev
)
list_del_init
(
&
prev
->
driver_list
);
spin_unlock
(
&
device_lock
);
device_detach
(
dev
);
if
(
prev
)
put_device
(
prev
);
prev
=
dev
;
spin_lock
(
&
device_lock
);
}
}
spin_unlock
(
&
device_lock
);
}
int
device_add
(
struct
device
*
dev
)
int
device_add
(
struct
device
*
dev
)
{
{
int
error
;
int
error
;
...
@@ -156,14 +32,14 @@ int device_add(struct device *dev)
...
@@ -156,14 +32,14 @@ int device_add(struct device *dev)
if
(
!
dev
||
!
strlen
(
dev
->
bus_id
))
if
(
!
dev
||
!
strlen
(
dev
->
bus_id
))
return
-
EINVAL
;
return
-
EINVAL
;
spin_lock
(
&
device_lock
);
down
(
&
device_sem
);
dev
->
present
=
1
;
dev
->
state
=
DEVICE_REGISTERED
;
if
(
dev
->
parent
)
{
if
(
dev
->
parent
)
{
list_add_tail
(
&
dev
->
g_list
,
&
dev
->
parent
->
g_list
);
list_add_tail
(
&
dev
->
g_list
,
&
dev
->
parent
->
g_list
);
list_add_tail
(
&
dev
->
node
,
&
dev
->
parent
->
children
);
list_add_tail
(
&
dev
->
node
,
&
dev
->
parent
->
children
);
}
else
}
else
list_add_tail
(
&
dev
->
g_list
,
&
global_device_list
);
list_add_tail
(
&
dev
->
g_list
,
&
global_device_list
);
spin_unlock
(
&
device_lock
);
up
(
&
device_sem
);
pr_debug
(
"DEV: registering device: ID = '%s', name = %s
\n
"
,
pr_debug
(
"DEV: registering device: ID = '%s', name = %s
\n
"
,
dev
->
bus_id
,
dev
->
name
);
dev
->
bus_id
,
dev
->
name
);
...
@@ -173,9 +49,6 @@ int device_add(struct device *dev)
...
@@ -173,9 +49,6 @@ int device_add(struct device *dev)
bus_add_device
(
dev
);
bus_add_device
(
dev
);
/* bind to driver */
device_attach
(
dev
);
/* notify platform of device entry */
/* notify platform of device entry */
if
(
platform_notify
)
if
(
platform_notify
)
platform_notify
(
dev
);
platform_notify
(
dev
);
...
@@ -183,12 +56,13 @@ int device_add(struct device *dev)
...
@@ -183,12 +56,13 @@ int device_add(struct device *dev)
/* notify userspace of device entry */
/* notify userspace of device entry */
dev_hotplug
(
dev
,
"add"
);
dev_hotplug
(
dev
,
"add"
);
devclass_add_device
(
dev
);
register_done:
register_done:
if
(
error
)
{
if
(
error
)
{
spin_lock
(
&
device_lock
);
up
(
&
device_sem
);
list_del_init
(
&
dev
->
g_list
);
list_del_init
(
&
dev
->
g_list
);
list_del_init
(
&
dev
->
node
);
list_del_init
(
&
dev
->
node
);
spin_unlock
(
&
device_lock
);
up
(
&
device_sem
);
}
}
return
error
;
return
error
;
}
}
...
@@ -203,6 +77,7 @@ void device_initialize(struct device *dev)
...
@@ -203,6 +77,7 @@ void device_initialize(struct device *dev)
INIT_LIST_HEAD
(
&
dev
->
intf_list
);
INIT_LIST_HEAD
(
&
dev
->
intf_list
);
spin_lock_init
(
&
dev
->
lock
);
spin_lock_init
(
&
dev
->
lock
);
atomic_set
(
&
dev
->
refcount
,
1
);
atomic_set
(
&
dev
->
refcount
,
1
);
dev
->
state
=
DEVICE_INITIALIZED
;
if
(
dev
->
parent
)
if
(
dev
->
parent
)
get_device
(
dev
->
parent
);
get_device
(
dev
->
parent
);
}
}
...
@@ -234,22 +109,15 @@ int device_register(struct device *dev)
...
@@ -234,22 +109,15 @@ int device_register(struct device *dev)
return
error
;
return
error
;
}
}
struct
device
*
get_device
_locked
(
struct
device
*
dev
)
struct
device
*
get_device
(
struct
device
*
dev
)
{
{
struct
device
*
ret
=
dev
;
struct
device
*
ret
=
dev
;
if
(
dev
&&
dev
->
present
&&
atomic_read
(
&
dev
->
refcount
)
>
0
)
down
(
&
device_sem
);
if
(
device_present
(
dev
)
&&
atomic_read
(
&
dev
->
refcount
)
>
0
)
atomic_inc
(
&
dev
->
refcount
);
atomic_inc
(
&
dev
->
refcount
);
else
else
ret
=
NULL
;
ret
=
NULL
;
return
ret
;
up
(
&
device_sem
);
}
struct
device
*
get_device
(
struct
device
*
dev
)
{
struct
device
*
ret
;
spin_lock
(
&
device_lock
);
ret
=
get_device_locked
(
dev
);
spin_unlock
(
&
device_lock
);
return
ret
;
return
ret
;
}
}
...
@@ -259,34 +127,23 @@ struct device * get_device(struct device * dev)
...
@@ -259,34 +127,23 @@ struct device * get_device(struct device * dev)
*/
*/
void
put_device
(
struct
device
*
dev
)
void
put_device
(
struct
device
*
dev
)
{
{
struct
device
*
parent
;
down
(
&
device_sem
);
if
(
!
atomic_dec_and_lock
(
&
dev
->
refcount
,
&
device_lock
))
if
(
!
atomic_dec_and_test
(
&
dev
->
refcount
))
{
up
(
&
device_sem
);
return
;
return
;
parent
=
dev
->
parent
;
}
dev
->
parent
=
NULL
;
list_del_init
(
&
dev
->
node
);
spin_unlock
(
&
device_lock
);
list_del_init
(
&
dev
->
g_list
);
up
(
&
device_sem
);
BUG_ON
(
dev
->
present
);
if
(
dev
->
release
)
BUG_ON
((
dev
->
state
!=
DEVICE_GONE
));
dev
->
release
(
dev
);
if
(
parent
)
device_del
(
dev
);
put_device
(
parent
);
}
}
void
device_del
(
struct
device
*
dev
)
void
device_del
(
struct
device
*
dev
)
{
{
spin_lock
(
&
device_lock
);
struct
device
*
parent
=
dev
->
parent
;
dev
->
present
=
0
;
list_del_init
(
&
dev
->
node
);
list_del_init
(
&
dev
->
g_list
);
list_del_init
(
&
dev
->
bus_list
);
list_del_init
(
&
dev
->
driver_list
);
spin_unlock
(
&
device_lock
);
pr_debug
(
"DEV: Unregistering device. ID = '%s', name = '%s'
\n
"
,
dev
->
bus_id
,
dev
->
name
);
/* Notify the platform of the removal, in case they
/* Notify the platform of the removal, in case they
* need to do anything...
* need to do anything...
...
@@ -297,11 +154,16 @@ void device_del(struct device * dev)
...
@@ -297,11 +154,16 @@ void device_del(struct device * dev)
/* notify userspace that this device is about to disappear */
/* notify userspace that this device is about to disappear */
dev_hotplug
(
dev
,
"remove"
);
dev_hotplug
(
dev
,
"remove"
);
device_detach
(
dev
);
bus_remove_device
(
dev
);
bus_remove_device
(
dev
);
/* remove the driverfs directory */
/* remove the driverfs directory */
device_remove_dir
(
dev
);
device_remove_dir
(
dev
);
if
(
dev
->
release
)
dev
->
release
(
dev
);
if
(
parent
)
put_device
(
parent
);
}
}
/**
/**
...
@@ -315,22 +177,15 @@ void device_del(struct device * dev)
...
@@ -315,22 +177,15 @@ void device_del(struct device * dev)
*/
*/
void
device_unregister
(
struct
device
*
dev
)
void
device_unregister
(
struct
device
*
dev
)
{
{
d
evice_del
(
dev
);
d
own
(
&
device_sem
);
put_device
(
dev
)
;
dev
->
state
=
DEVICE_GONE
;
}
up
(
&
device_sem
);
static
int
__init
device_init
(
void
)
pr_debug
(
"DEV: Unregistering device. ID = '%s', name = '%s'
\n
"
,
{
dev
->
bus_id
,
dev
->
name
);
int
error
;
put_device
(
dev
);
error
=
init_driverfs_fs
();
if
(
error
)
panic
(
"DEV: could not initialize driverfs"
);
return
0
;
}
}
core_initcall
(
device_init
);
EXPORT_SYMBOL
(
device_register
);
EXPORT_SYMBOL
(
device_register
);
EXPORT_SYMBOL
(
device_unregister
);
EXPORT_SYMBOL
(
device_unregister
);
EXPORT_SYMBOL
(
get_device
);
EXPORT_SYMBOL
(
get_device
);
...
...
drivers/base/driver.c
View file @
487680ca
...
@@ -16,29 +16,61 @@ int driver_for_each_dev(struct device_driver * drv, void * data,
...
@@ -16,29 +16,61 @@ int driver_for_each_dev(struct device_driver * drv, void * data,
int
(
*
callback
)(
struct
device
*
,
void
*
))
int
(
*
callback
)(
struct
device
*
,
void
*
))
{
{
struct
list_head
*
node
;
struct
list_head
*
node
;
struct
device
*
prev
=
NULL
;
int
error
=
0
;
int
error
=
0
;
get_driver
(
drv
);
drv
=
get_driver
(
drv
);
spin_lock
(
&
device_lock
);
if
(
drv
)
{
down_read
(
&
drv
->
bus
->
rwsem
);
list_for_each
(
node
,
&
drv
->
devices
)
{
list_for_each
(
node
,
&
drv
->
devices
)
{
struct
device
*
dev
=
get_device_locked
(
to_dev
(
node
));
struct
device
*
dev
=
get_device
(
to_dev
(
node
));
if
(
dev
)
{
if
(
dev
)
{
spin_unlock
(
&
device_lock
);
error
=
callback
(
dev
,
data
);
error
=
callback
(
dev
,
data
);
if
(
prev
)
put_device
(
dev
);
put_device
(
prev
);
prev
=
dev
;
spin_lock
(
&
device_lock
);
if
(
error
)
if
(
error
)
break
;
break
;
}
}
}
}
spin_unlock
(
&
device_lock
);
up_read
(
&
drv
->
bus
->
rwsem
);
put_driver
(
drv
);
put_driver
(
drv
);
}
return
error
;
return
error
;
}
}
struct
device_driver
*
get_driver
(
struct
device_driver
*
drv
)
{
struct
device_driver
*
ret
=
drv
;
spin_lock
(
&
device_lock
);
if
(
drv
&&
drv
->
present
&&
atomic_read
(
&
drv
->
refcount
)
>
0
)
atomic_inc
(
&
drv
->
refcount
);
else
ret
=
NULL
;
spin_unlock
(
&
device_lock
);
return
ret
;
}
void
remove_driver
(
struct
device_driver
*
drv
)
{
BUG
();
}
/**
* put_driver - decrement driver's refcount and clean up if necessary
* @drv: driver in question
*/
void
put_driver
(
struct
device_driver
*
drv
)
{
struct
bus_type
*
bus
=
drv
->
bus
;
if
(
!
atomic_dec_and_lock
(
&
drv
->
refcount
,
&
device_lock
))
return
;
spin_unlock
(
&
device_lock
);
BUG_ON
(
drv
->
present
);
bus_remove_driver
(
drv
);
if
(
drv
->
release
)
drv
->
release
(
drv
);
put_bus
(
bus
);
}
/**
/**
* driver_register - register driver with bus
* driver_register - register driver with bus
* @drv: driver to register
* @drv: driver to register
...
@@ -50,54 +82,29 @@ int driver_register(struct device_driver * drv)
...
@@ -50,54 +82,29 @@ int driver_register(struct device_driver * drv)
if
(
!
drv
->
bus
)
if
(
!
drv
->
bus
)
return
-
EINVAL
;
return
-
EINVAL
;
pr_debug
(
"
Registering driver '%s' with bus '%s'
\n
"
,
drv
->
name
,
drv
->
bus
->
name
);
pr_debug
(
"
driver %s:%s: registering
\n
"
,
drv
->
bus
->
name
,
drv
->
name
);
get_bus
(
drv
->
bus
);
get_bus
(
drv
->
bus
);
atomic_set
(
&
drv
->
refcount
,
2
);
atomic_set
(
&
drv
->
refcount
,
2
);
rwlock_init
(
&
drv
->
lock
);
rwlock_init
(
&
drv
->
lock
);
INIT_LIST_HEAD
(
&
drv
->
devices
);
INIT_LIST_HEAD
(
&
drv
->
devices
);
spin_lock
(
&
device_lock
);
drv
->
present
=
1
;
list_add
(
&
drv
->
bus_list
,
&
drv
->
bus
->
drivers
);
bus_add_driver
(
drv
);
spin_unlock
(
&
device_lock
);
driver_make_dir
(
drv
);
driver_attach
(
drv
);
put_driver
(
drv
);
put_driver
(
drv
);
return
0
;
return
0
;
}
}
static
void
__remove_driver
(
struct
device_driver
*
drv
)
void
driver_unregister
(
struct
device_driver
*
drv
)
{
pr_debug
(
"Unregistering driver '%s' from bus '%s'
\n
"
,
drv
->
name
,
drv
->
bus
->
name
);
driver_detach
(
drv
);
driver_remove_dir
(
drv
);
if
(
drv
->
release
)
drv
->
release
(
drv
);
put_bus
(
drv
->
bus
);
}
void
remove_driver
(
struct
device_driver
*
drv
)
{
{
spin_lock
(
&
device_lock
);
spin_lock
(
&
device_lock
);
atomic_set
(
&
drv
->
refcount
,
0
);
drv
->
present
=
0
;
list_del_init
(
&
drv
->
bus_list
);
spin_unlock
(
&
device_lock
);
spin_unlock
(
&
device_lock
);
__remove_driver
(
drv
);
pr_debug
(
"driver %s:%s: unregistering
\n
"
,
drv
->
bus
->
name
,
drv
->
name
);
}
put_driver
(
drv
);
/**
* put_driver - decrement driver's refcount and clean up if necessary
* @drv: driver in question
*/
void
put_driver
(
struct
device_driver
*
drv
)
{
if
(
!
atomic_dec_and_lock
(
&
drv
->
refcount
,
&
device_lock
))
return
;
list_del_init
(
&
drv
->
bus_list
);
spin_unlock
(
&
device_lock
);
__remove_driver
(
drv
);
}
}
EXPORT_SYMBOL
(
driver_for_each_dev
);
EXPORT_SYMBOL
(
driver_for_each_dev
);
EXPORT_SYMBOL
(
driver_register
);
EXPORT_SYMBOL
(
driver_register
);
EXPORT_SYMBOL
(
driver_unregister
);
EXPORT_SYMBOL
(
get_driver
);
EXPORT_SYMBOL
(
put_driver
);
EXPORT_SYMBOL
(
put_driver
);
EXPORT_SYMBOL
(
remove_driver
);
drivers/base/interface.c
View file @
487680ca
...
@@ -19,7 +19,7 @@ static DEVICE_ATTR(name,S_IRUGO,device_read_name,NULL);
...
@@ -19,7 +19,7 @@ static DEVICE_ATTR(name,S_IRUGO,device_read_name,NULL);
static
ssize_t
static
ssize_t
device_read_power
(
struct
device
*
dev
,
char
*
page
,
size_t
count
,
loff_t
off
)
device_read_power
(
struct
device
*
dev
,
char
*
page
,
size_t
count
,
loff_t
off
)
{
{
return
off
?
0
:
sprintf
(
page
,
"%d
\n
"
,
dev
->
current
_state
);
return
off
?
0
:
sprintf
(
page
,
"%d
\n
"
,
dev
->
power
_state
);
}
}
static
ssize_t
static
ssize_t
...
...
drivers/base/power.c
View file @
487680ca
...
@@ -8,6 +8,8 @@
...
@@ -8,6 +8,8 @@
*
*
*/
*/
#define DEBUG 0
#include <linux/device.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/module.h>
#include "base.h"
#include "base.h"
...
@@ -28,34 +30,21 @@
...
@@ -28,34 +30,21 @@
int
device_suspend
(
u32
state
,
u32
level
)
int
device_suspend
(
u32
state
,
u32
level
)
{
{
struct
list_head
*
node
;
struct
list_head
*
node
;
struct
device
*
prev
=
NULL
;
int
error
=
0
;
int
error
=
0
;
if
(
level
==
SUSPEND_POWER_DOWN
)
printk
(
KERN_EMERG
"Shutting down devices
\n
"
);
else
printk
(
KERN_EMERG
"Suspending devices
\n
"
);
printk
(
KERN_EMERG
"Suspending devices
\n
"
);
spin_lock
(
&
device_lock
);
down
(
&
device_sem
);
list_for_each
(
node
,
&
global_device_list
)
{
list_for_each
(
node
,
&
global_device_list
)
{
struct
device
*
dev
=
get_device_locked
(
to_dev
(
node
));
struct
device
*
dev
=
to_dev
(
node
);
if
(
dev
)
{
if
(
device_present
(
dev
)
&&
dev
->
driver
&&
dev
->
driver
->
suspend
)
{
spin_unlock
(
&
device_lock
);
pr_debug
(
"suspending device %s
\n
"
,
dev
->
name
);
if
(
dev
->
driver
)
{
if
(
level
==
SUSPEND_POWER_DOWN
)
{
if
(
dev
->
driver
->
remove
)
dev
->
driver
->
remove
(
dev
);
}
else
if
(
dev
->
driver
->
suspend
)
error
=
dev
->
driver
->
suspend
(
dev
,
state
,
level
);
error
=
dev
->
driver
->
suspend
(
dev
,
state
,
level
);
}
if
(
error
)
if
(
prev
)
printk
(
KERN_ERR
"%s: suspend returned %d
\n
"
,
dev
->
name
,
error
);
put_device
(
prev
);
prev
=
dev
;
spin_lock
(
&
device_lock
);
}
}
}
}
spin_unlock
(
&
device_lock
);
up
(
&
device_sem
);
return
error
;
return
error
;
}
}
...
@@ -70,33 +59,38 @@ int device_suspend(u32 state, u32 level)
...
@@ -70,33 +59,38 @@ int device_suspend(u32 state, u32 level)
void
device_resume
(
u32
level
)
void
device_resume
(
u32
level
)
{
{
struct
list_head
*
node
;
struct
list_head
*
node
;
struct
device
*
prev
=
NULL
;
spin_lock
(
&
device_lock
);
down
(
&
device_sem
);
list_for_each_prev
(
node
,
&
global_device_list
)
{
list_for_each_prev
(
node
,
&
global_device_list
)
{
struct
device
*
dev
=
get_device_locked
(
to_dev
(
node
));
struct
device
*
dev
=
to_dev
(
node
);
if
(
dev
)
{
if
(
device_present
(
dev
)
&&
dev
->
driver
&&
dev
->
driver
->
resume
)
{
spin_unlock
(
&
device_lock
);
pr_debug
(
"resuming device %s
\n
"
,
dev
->
name
);
if
(
dev
->
driver
&&
dev
->
driver
->
resume
)
dev
->
driver
->
resume
(
dev
,
level
);
dev
->
driver
->
resume
(
dev
,
level
);
if
(
prev
)
put_device
(
prev
);
prev
=
dev
;
spin_lock
(
&
device_lock
);
}
}
}
}
spin_unlock
(
&
device_lock
);
up
(
&
device_sem
);
printk
(
KERN_EMERG
"Devices Resumed
\n
"
);
printk
(
KERN_EMERG
"Devices Resumed
\n
"
);
}
}
/**
/**
* device_shutdown - call device_suspend with status set to shutdown, to
* device_shutdown - call ->remove() on each device to shutdown.
* cause all devices to remove themselves cleanly
*/
*/
void
device_shutdown
(
void
)
void
device_shutdown
(
void
)
{
{
device_suspend
(
4
,
SUSPEND_POWER_DOWN
);
struct
list_head
*
entry
;
printk
(
KERN_EMERG
"Shutting down devices
\n
"
);
down
(
&
device_sem
);
list_for_each
(
entry
,
&
global_device_list
)
{
struct
device
*
dev
=
to_dev
(
entry
);
if
(
device_present
(
dev
)
&&
dev
->
driver
&&
dev
->
driver
->
shutdown
)
{
pr_debug
(
"shutting down %s
\n
"
,
dev
->
name
);
dev
->
driver
->
shutdown
(
dev
);
}
}
up
(
&
device_sem
);
}
}
EXPORT_SYMBOL
(
device_suspend
);
EXPORT_SYMBOL
(
device_suspend
);
...
...
drivers/base/sys.c
View file @
487680ca
...
@@ -10,6 +10,8 @@
...
@@ -10,6 +10,8 @@
* add themselves as children of the system bus.
* add themselves as children of the system bus.
*/
*/
#define DEBUG 1
#include <linux/device.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
...
@@ -76,8 +78,8 @@ int sys_register_root(struct sys_root * root)
...
@@ -76,8 +78,8 @@ int sys_register_root(struct sys_root * root)
*/
*/
void
sys_unegister_root
(
struct
sys_root
*
root
)
void
sys_unegister_root
(
struct
sys_root
*
root
)
{
{
put_device
(
&
root
->
sysdev
);
device_unregister
(
&
root
->
sysdev
);
put_device
(
&
root
->
dev
);
device_unregister
(
&
root
->
dev
);
}
}
/**
/**
...
...
drivers/input/serio/sa1111ps2.c
View file @
487680ca
...
@@ -354,7 +354,7 @@ static int __init ps2_init(void)
...
@@ -354,7 +354,7 @@ static int __init ps2_init(void)
static
void
__exit
ps2_exit
(
void
)
static
void
__exit
ps2_exit
(
void
)
{
{
remove_driv
er
(
&
ps2_driver
.
drv
);
driver_unregist
er
(
&
ps2_driver
.
drv
);
}
}
module_init
(
ps2_init
);
module_init
(
ps2_init
);
...
...
drivers/pci/pci-driver.c
View file @
487680ca
...
@@ -141,7 +141,7 @@ pci_register_driver(struct pci_driver *drv)
...
@@ -141,7 +141,7 @@ pci_register_driver(struct pci_driver *drv)
void
void
pci_unregister_driver
(
struct
pci_driver
*
drv
)
pci_unregister_driver
(
struct
pci_driver
*
drv
)
{
{
remove_driv
er
(
&
drv
->
driver
);
driver_unregist
er
(
&
drv
->
driver
);
}
}
static
struct
pci_driver
pci_compat_driver
=
{
static
struct
pci_driver
pci_compat_driver
=
{
...
...
drivers/pcmcia/sa1111_generic.c
View file @
487680ca
...
@@ -297,7 +297,7 @@ static int __init sa1111_drv_pcmcia_init(void)
...
@@ -297,7 +297,7 @@ static int __init sa1111_drv_pcmcia_init(void)
static
void
__exit
sa1111_drv_pcmcia_exit
(
void
)
static
void
__exit
sa1111_drv_pcmcia_exit
(
void
)
{
{
remove_driv
er
(
&
pcmcia_driver
.
drv
);
driver_unregist
er
(
&
pcmcia_driver
.
drv
);
}
}
module_init
(
sa1111_drv_pcmcia_init
);
module_init
(
sa1111_drv_pcmcia_init
);
...
...
drivers/scsi/scsi_debug.c
View file @
487680ca
...
@@ -861,8 +861,7 @@ static int scsi_debug_release(struct Scsi_Host * hpnt)
...
@@ -861,8 +861,7 @@ static int scsi_debug_release(struct Scsi_Host * hpnt)
if
(
++
num_releases
==
num_present
)
{
if
(
++
num_releases
==
num_present
)
{
#ifdef DRIVERFS_SUPPORT
#ifdef DRIVERFS_SUPPORT
do_remove_driverfs_files
();
do_remove_driverfs_files
();
remove_driver
(
&
sdebug_driverfs_driver
);
driver_unregister
(
&
sdebug_driverfs_driver
);
// driver_unregister(&sdebug_driverfs_driver);
#endif
#endif
vfree
(
fake_storep
);
vfree
(
fake_storep
);
vfree
(
devInfop
);
vfree
(
devInfop
);
...
...
drivers/scsi/sd.c
View file @
487680ca
...
@@ -1525,7 +1525,7 @@ static void __exit exit_sd(void)
...
@@ -1525,7 +1525,7 @@ static void __exit exit_sd(void)
vfree
(
sd_dsk_arr
);
vfree
(
sd_dsk_arr
);
}
}
sd_template
.
dev_max
=
0
;
sd_template
.
dev_max
=
0
;
remove_driv
er
(
&
sd_template
.
scsi_driverfs_driver
);
driver_unregist
er
(
&
sd_template
.
scsi_driverfs_driver
);
unregister_reboot_notifier
(
&
sd_notifier_block
);
unregister_reboot_notifier
(
&
sd_notifier_block
);
}
}
...
...
drivers/scsi/sg.c
View file @
487680ca
...
@@ -1655,7 +1655,7 @@ exit_sg(void)
...
@@ -1655,7 +1655,7 @@ exit_sg(void)
sg_dev_arr
=
NULL
;
sg_dev_arr
=
NULL
;
}
}
sg_template
.
dev_max
=
0
;
sg_template
.
dev_max
=
0
;
remove_driv
er
(
&
sg_template
.
scsi_driverfs_driver
);
driver_unregist
er
(
&
sg_template
.
scsi_driverfs_driver
);
}
}
static
int
static
int
...
...
drivers/scsi/sr.c
View file @
487680ca
...
@@ -856,7 +856,7 @@ static void __exit exit_sr(void)
...
@@ -856,7 +856,7 @@ static void __exit exit_sr(void)
kfree
(
scsi_CDs
);
kfree
(
scsi_CDs
);
sr_template
.
dev_max
=
0
;
sr_template
.
dev_max
=
0
;
remove_driv
er
(
&
sr_template
.
scsi_driverfs_driver
);
driver_unregist
er
(
&
sr_template
.
scsi_driverfs_driver
);
}
}
module_init
(
init_sr
);
module_init
(
init_sr
);
...
...
drivers/scsi/st.c
View file @
487680ca
...
@@ -3992,7 +3992,7 @@ static void __exit exit_st(void)
...
@@ -3992,7 +3992,7 @@ static void __exit exit_st(void)
kfree
(
scsi_tapes
);
kfree
(
scsi_tapes
);
}
}
st_template
.
dev_max
=
0
;
st_template
.
dev_max
=
0
;
remove_driv
er
(
&
st_template
.
scsi_driverfs_driver
);
driver_unregist
er
(
&
st_template
.
scsi_driverfs_driver
);
printk
(
KERN_INFO
"st: Unloaded.
\n
"
);
printk
(
KERN_INFO
"st: Unloaded.
\n
"
);
}
}
...
...
drivers/usb/core/usb.c
View file @
487680ca
...
@@ -208,7 +208,7 @@ void usb_deregister(struct usb_driver *driver)
...
@@ -208,7 +208,7 @@ void usb_deregister(struct usb_driver *driver)
{
{
info
(
"deregistering driver %s"
,
driver
->
name
);
info
(
"deregistering driver %s"
,
driver
->
name
);
remove_driv
er
(
&
driver
->
driver
);
driver_unregist
er
(
&
driver
->
driver
);
usbfs_update_special
();
usbfs_update_special
();
}
}
...
@@ -1394,7 +1394,7 @@ static void __exit usb_exit(void)
...
@@ -1394,7 +1394,7 @@ static void __exit usb_exit(void)
if
(
nousb
)
if
(
nousb
)
return
;
return
;
remove_driv
er
(
&
usb_generic_driver
);
driver_unregist
er
(
&
usb_generic_driver
);
usb_major_cleanup
();
usb_major_cleanup
();
usbfs_cleanup
();
usbfs_cleanup
();
usb_hub_cleanup
();
usb_hub_cleanup
();
...
...
drivers/usb/host/ohci-sa1111.c
View file @
487680ca
...
@@ -413,7 +413,7 @@ static int __init ohci_hcd_sa1111_init (void)
...
@@ -413,7 +413,7 @@ static int __init ohci_hcd_sa1111_init (void)
static
void
__exit
ohci_hcd_sa1111_cleanup
(
void
)
static
void
__exit
ohci_hcd_sa1111_cleanup
(
void
)
{
{
remove_driv
er
(
&
ohci_hcd_sa1111_driver
.
drv
);
driver_unregist
er
(
&
ohci_hcd_sa1111_driver
.
drv
);
}
}
module_init
(
ohci_hcd_sa1111_init
);
module_init
(
ohci_hcd_sa1111_init
);
...
...
fs/driverfs/inode.c
View file @
487680ca
...
@@ -509,11 +509,13 @@ static void put_mount(void)
...
@@ -509,11 +509,13 @@ static void put_mount(void)
DBG
(
"driverfs: mount_count = %d
\n
"
,
mount_count
);
DBG
(
"driverfs: mount_count = %d
\n
"
,
mount_count
);
}
}
int
__init
init_driverfs_fs
(
void
)
static
int
__init
driverfs_init
(
void
)
{
{
return
register_filesystem
(
&
driverfs_fs_type
);
return
register_filesystem
(
&
driverfs_fs_type
);
}
}
core_initcall
(
driverfs_init
);
static
struct
dentry
*
get_dentry
(
struct
dentry
*
parent
,
const
char
*
name
)
static
struct
dentry
*
get_dentry
(
struct
dentry
*
parent
,
const
char
*
name
)
{
{
struct
qstr
qstr
;
struct
qstr
qstr
;
...
...
include/linux/device.h
View file @
487680ca
...
@@ -48,14 +48,22 @@ enum {
...
@@ -48,14 +48,22 @@ enum {
RESUME_ENABLE
,
RESUME_ENABLE
,
};
};
enum
device_state
{
DEVICE_UNINITIALIZED
=
0
,
DEVICE_INITIALIZED
=
1
,
DEVICE_REGISTERED
=
2
,
DEVICE_GONE
=
3
,
};
struct
device
;
struct
device
;
struct
device_driver
;
struct
device_driver
;
struct
device_class
;
struct
device_class
;
struct
bus_type
{
struct
bus_type
{
char
*
name
;
char
*
name
;
rwlock_t
lock
;
struct
rw_semaphore
rwsem
;
atomic_t
refcount
;
atomic_t
refcount
;
u32
present
;
struct
list_head
node
;
struct
list_head
node
;
struct
list_head
devices
;
struct
list_head
devices
;
...
@@ -73,14 +81,9 @@ struct bus_type {
...
@@ -73,14 +81,9 @@ struct bus_type {
extern
int
bus_register
(
struct
bus_type
*
bus
);
extern
int
bus_register
(
struct
bus_type
*
bus
);
extern
void
bus_unregister
(
struct
bus_type
*
bus
);
static
inline
struct
bus_type
*
get_bus
(
struct
bus_type
*
bus
)
extern
struct
bus_type
*
get_bus
(
struct
bus_type
*
bus
);
{
BUG_ON
(
!
atomic_read
(
&
bus
->
refcount
));
atomic_inc
(
&
bus
->
refcount
);
return
bus
;
}
extern
void
put_bus
(
struct
bus_type
*
bus
);
extern
void
put_bus
(
struct
bus_type
*
bus
);
extern
int
bus_for_each_dev
(
struct
bus_type
*
bus
,
void
*
data
,
extern
int
bus_for_each_dev
(
struct
bus_type
*
bus
,
void
*
data
,
...
@@ -114,6 +117,7 @@ struct device_driver {
...
@@ -114,6 +117,7 @@ struct device_driver {
rwlock_t
lock
;
rwlock_t
lock
;
atomic_t
refcount
;
atomic_t
refcount
;
u32
present
;
struct
list_head
bus_list
;
struct
list_head
bus_list
;
struct
list_head
class_list
;
struct
list_head
class_list
;
...
@@ -123,7 +127,7 @@ struct device_driver {
...
@@ -123,7 +127,7 @@ struct device_driver {
int
(
*
probe
)
(
struct
device
*
dev
);
int
(
*
probe
)
(
struct
device
*
dev
);
int
(
*
remove
)
(
struct
device
*
dev
);
int
(
*
remove
)
(
struct
device
*
dev
);
void
(
*
shutdown
)
(
struct
device
*
dev
);
int
(
*
suspend
)
(
struct
device
*
dev
,
u32
state
,
u32
level
);
int
(
*
suspend
)
(
struct
device
*
dev
,
u32
state
,
u32
level
);
int
(
*
resume
)
(
struct
device
*
dev
,
u32
level
);
int
(
*
resume
)
(
struct
device
*
dev
,
u32
level
);
...
@@ -131,16 +135,10 @@ struct device_driver {
...
@@ -131,16 +135,10 @@ struct device_driver {
};
};
extern
int
driver_register
(
struct
device_driver
*
drv
);
extern
int
driver_register
(
struct
device_driver
*
drv
);
extern
void
driver_unregister
(
struct
device_driver
*
drv
);
static
inline
struct
device_driver
*
get_driver
(
struct
device_driver
*
drv
)
extern
struct
device_driver
*
get_driver
(
struct
device_driver
*
drv
);
{
BUG_ON
(
!
atomic_read
(
&
drv
->
refcount
));
atomic_inc
(
&
drv
->
refcount
);
return
drv
;
}
extern
void
put_driver
(
struct
device_driver
*
drv
);
extern
void
put_driver
(
struct
device_driver
*
drv
);
extern
void
remove_driver
(
struct
device_driver
*
drv
);
extern
void
remove_driver
(
struct
device_driver
*
drv
);
...
@@ -172,6 +170,11 @@ extern void driver_remove_file(struct device_driver *, struct driver_attribute *
...
@@ -172,6 +170,11 @@ extern void driver_remove_file(struct device_driver *, struct driver_attribute *
*/
*/
struct
device_class
{
struct
device_class
{
char
*
name
;
char
*
name
;
struct
rw_semaphore
rwsem
;
atomic_t
refcount
;
u32
present
;
u32
devnum
;
u32
devnum
;
struct
list_head
node
;
struct
list_head
node
;
...
@@ -189,6 +192,9 @@ struct device_class {
...
@@ -189,6 +192,9 @@ struct device_class {
extern
int
devclass_register
(
struct
device_class
*
);
extern
int
devclass_register
(
struct
device_class
*
);
extern
void
devclass_unregister
(
struct
device_class
*
);
extern
void
devclass_unregister
(
struct
device_class
*
);
extern
struct
device_class
*
get_devclass
(
struct
device_class
*
);
extern
void
put_devclass
(
struct
device_class
*
);
struct
devclass_attribute
{
struct
devclass_attribute
{
struct
attribute
attr
;
struct
attribute
attr
;
...
@@ -289,8 +295,8 @@ struct device {
...
@@ -289,8 +295,8 @@ struct device {
void
*
platform_data
;
/* Platform specific data (e.g. ACPI,
void
*
platform_data
;
/* Platform specific data (e.g. ACPI,
BIOS data relevant to device) */
BIOS data relevant to device) */
u32
present
;
enum
device_state
state
;
u32
current
_state
;
/* Current operating state. In
u32
power
_state
;
/* Current operating state. In
ACPI-speak, this is D0-D3, D0
ACPI-speak, this is D0-D3, D0
being fully functional, and D3
being fully functional, and D3
being off. */
being off. */
...
@@ -362,6 +368,11 @@ extern int (*platform_notify)(struct device * dev);
...
@@ -362,6 +368,11 @@ extern int (*platform_notify)(struct device * dev);
extern
int
(
*
platform_notify_remove
)(
struct
device
*
dev
);
extern
int
(
*
platform_notify_remove
)(
struct
device
*
dev
);
static
inline
int
device_present
(
struct
device
*
dev
)
{
return
(
dev
&&
(
dev
->
state
==
DEVICE_INITIALIZED
||
dev
->
state
==
DEVICE_REGISTERED
));
}
/* device and bus locking helpers.
/* device and bus locking helpers.
*
*
* FIXME: Is there anything else we need to do?
* FIXME: Is there anything else we need to do?
...
...
include/linux/driverfs_fs.h
View file @
487680ca
...
@@ -65,6 +65,4 @@ driverfs_create_symlink(struct driver_dir_entry * parent,
...
@@ -65,6 +65,4 @@ driverfs_create_symlink(struct driver_dir_entry * parent,
extern
void
extern
void
driverfs_remove_file
(
struct
driver_dir_entry
*
,
const
char
*
name
);
driverfs_remove_file
(
struct
driver_dir_entry
*
,
const
char
*
name
);
extern
int
init_driverfs_fs
(
void
);
#endif
/* _DDFS_H_ */
#endif
/* _DDFS_H_ */
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