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
bd53d127
Commit
bd53d127
authored
Jun 30, 2005
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
parents
12829dcb
bf164c79
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
143 additions
and
21 deletions
+143
-21
drivers/base/base.h
drivers/base/base.h
+1
-0
drivers/base/bus.c
drivers/base/bus.c
+99
-18
drivers/base/core.c
drivers/base/core.c
+1
-1
drivers/base/dd.c
drivers/base/dd.c
+1
-1
drivers/base/driver.c
drivers/base/driver.c
+35
-0
include/linux/device.h
include/linux/device.h
+6
-1
No files found.
drivers/base/base.h
View file @
bd53d127
...
@@ -5,6 +5,7 @@ extern int bus_add_driver(struct device_driver *);
...
@@ -5,6 +5,7 @@ extern int bus_add_driver(struct device_driver *);
extern
void
bus_remove_driver
(
struct
device_driver
*
);
extern
void
bus_remove_driver
(
struct
device_driver
*
);
extern
void
driver_detach
(
struct
device_driver
*
drv
);
extern
void
driver_detach
(
struct
device_driver
*
drv
);
extern
int
driver_probe_device
(
struct
device_driver
*
,
struct
device
*
);
static
inline
struct
class_device
*
to_class_dev
(
struct
kobject
*
obj
)
static
inline
struct
class_device
*
to_class_dev
(
struct
kobject
*
obj
)
{
{
...
...
drivers/base/bus.c
View file @
bd53d127
...
@@ -133,6 +133,58 @@ static struct kobj_type ktype_bus = {
...
@@ -133,6 +133,58 @@ static struct kobj_type ktype_bus = {
decl_subsys
(
bus
,
&
ktype_bus
,
NULL
);
decl_subsys
(
bus
,
&
ktype_bus
,
NULL
);
/* Manually detach a device from it's associated driver. */
static
int
driver_helper
(
struct
device
*
dev
,
void
*
data
)
{
const
char
*
name
=
data
;
if
(
strcmp
(
name
,
dev
->
bus_id
)
==
0
)
return
1
;
return
0
;
}
static
ssize_t
driver_unbind
(
struct
device_driver
*
drv
,
const
char
*
buf
,
size_t
count
)
{
struct
bus_type
*
bus
=
get_bus
(
drv
->
bus
);
struct
device
*
dev
;
int
err
=
-
ENODEV
;
dev
=
bus_find_device
(
bus
,
NULL
,
(
void
*
)
buf
,
driver_helper
);
if
((
dev
)
&&
(
dev
->
driver
==
drv
))
{
device_release_driver
(
dev
);
err
=
count
;
}
return
err
;
}
static
DRIVER_ATTR
(
unbind
,
S_IWUSR
,
NULL
,
driver_unbind
);
/*
* Manually attach a device to a driver.
* Note: the driver must want to bind to the device,
* it is not possible to override the driver's id table.
*/
static
ssize_t
driver_bind
(
struct
device_driver
*
drv
,
const
char
*
buf
,
size_t
count
)
{
struct
bus_type
*
bus
=
get_bus
(
drv
->
bus
);
struct
device
*
dev
;
int
err
=
-
ENODEV
;
dev
=
bus_find_device
(
bus
,
NULL
,
(
void
*
)
buf
,
driver_helper
);
if
((
dev
)
&&
(
dev
->
driver
==
NULL
))
{
down
(
&
dev
->
sem
);
err
=
driver_probe_device
(
drv
,
dev
);
up
(
&
dev
->
sem
);
put_device
(
dev
);
}
return
err
;
}
static
DRIVER_ATTR
(
bind
,
S_IWUSR
,
NULL
,
driver_bind
);
static
struct
device
*
next_device
(
struct
klist_iter
*
i
)
static
struct
device
*
next_device
(
struct
klist_iter
*
i
)
{
{
struct
klist_node
*
n
=
klist_next
(
i
);
struct
klist_node
*
n
=
klist_next
(
i
);
...
@@ -177,6 +229,39 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start,
...
@@ -177,6 +229,39 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start,
return
error
;
return
error
;
}
}
/**
* bus_find_device - device iterator for locating a particular device.
* @bus: bus type
* @start: Device to begin with
* @data: Data to pass to match function
* @match: Callback function to check device
*
* This is similar to the bus_for_each_dev() function above, but it
* returns a reference to a device that is 'found' for later use, as
* determined by the @match callback.
*
* The callback should return 0 if the device doesn't match and non-zero
* if it does. If the callback returns non-zero, this function will
* return to the caller and not iterate over any more devices.
*/
struct
device
*
bus_find_device
(
struct
bus_type
*
bus
,
struct
device
*
start
,
void
*
data
,
int
(
*
match
)(
struct
device
*
,
void
*
))
{
struct
klist_iter
i
;
struct
device
*
dev
;
if
(
!
bus
)
return
NULL
;
klist_iter_init_node
(
&
bus
->
klist_devices
,
&
i
,
(
start
?
&
start
->
knode_bus
:
NULL
));
while
((
dev
=
next_device
(
&
i
)))
if
(
match
(
dev
,
data
)
&&
get_device
(
dev
))
break
;
klist_iter_exit
(
&
i
);
return
dev
;
}
static
struct
device_driver
*
next_driver
(
struct
klist_iter
*
i
)
static
struct
device_driver
*
next_driver
(
struct
klist_iter
*
i
)
...
@@ -363,6 +448,8 @@ int bus_add_driver(struct device_driver * drv)
...
@@ -363,6 +448,8 @@ int bus_add_driver(struct device_driver * drv)
module_add_driver
(
drv
->
owner
,
drv
);
module_add_driver
(
drv
->
owner
,
drv
);
driver_add_attrs
(
bus
,
drv
);
driver_add_attrs
(
bus
,
drv
);
driver_create_file
(
drv
,
&
driver_attr_unbind
);
driver_create_file
(
drv
,
&
driver_attr_bind
);
}
}
return
error
;
return
error
;
}
}
...
@@ -380,6 +467,8 @@ int bus_add_driver(struct device_driver * drv)
...
@@ -380,6 +467,8 @@ int bus_add_driver(struct device_driver * drv)
void
bus_remove_driver
(
struct
device_driver
*
drv
)
void
bus_remove_driver
(
struct
device_driver
*
drv
)
{
{
if
(
drv
->
bus
)
{
if
(
drv
->
bus
)
{
driver_remove_file
(
drv
,
&
driver_attr_bind
);
driver_remove_file
(
drv
,
&
driver_attr_unbind
);
driver_remove_attrs
(
drv
->
bus
,
drv
);
driver_remove_attrs
(
drv
->
bus
,
drv
);
klist_remove
(
&
drv
->
knode_bus
);
klist_remove
(
&
drv
->
knode_bus
);
pr_debug
(
"bus %s: remove driver %s
\n
"
,
drv
->
bus
->
name
,
drv
->
name
);
pr_debug
(
"bus %s: remove driver %s
\n
"
,
drv
->
bus
->
name
,
drv
->
name
);
...
@@ -394,31 +483,22 @@ void bus_remove_driver(struct device_driver * drv)
...
@@ -394,31 +483,22 @@ void bus_remove_driver(struct device_driver * drv)
/* Helper for bus_rescan_devices's iter */
/* Helper for bus_rescan_devices's iter */
static
int
bus_rescan_devices_helper
(
struct
device
*
dev
,
void
*
data
)
static
int
bus_rescan_devices_helper
(
struct
device
*
dev
,
void
*
data
)
{
{
int
*
count
=
data
;
if
(
!
dev
->
driver
)
device_attach
(
dev
);
if
(
!
dev
->
driver
&&
(
device_attach
(
dev
)
>
0
))
(
*
count
)
++
;
return
0
;
return
0
;
}
}
/**
/**
*
bus_rescan_devices - rescan devices on the bus for possible drivers
*
bus_rescan_devices - rescan devices on the bus for possible drivers
*
@bus:
the bus to scan.
*
@bus:
the bus to scan.
*
*
* This function will look for devices on the bus with no driver
* This function will look for devices on the bus with no driver
* attached and rescan it against existing drivers to see if it
* attached and rescan it against existing drivers to see if it matches
* matches any. Calls device_attach(). Returns the number of devices
* any by calling device_attach() for the unbound devices.
* that were sucessfully bound to a driver.
*/
*/
int
bus_rescan_devices
(
struct
bus_type
*
bus
)
void
bus_rescan_devices
(
struct
bus_type
*
bus
)
{
{
int
count
=
0
;
bus_for_each_dev
(
bus
,
NULL
,
NULL
,
bus_rescan_devices_helper
);
bus_for_each_dev
(
bus
,
NULL
,
&
count
,
bus_rescan_devices_helper
);
return
count
;
}
}
...
@@ -557,6 +637,7 @@ int __init buses_init(void)
...
@@ -557,6 +637,7 @@ int __init buses_init(void)
EXPORT_SYMBOL_GPL
(
bus_for_each_dev
);
EXPORT_SYMBOL_GPL
(
bus_for_each_dev
);
EXPORT_SYMBOL_GPL
(
bus_find_device
);
EXPORT_SYMBOL_GPL
(
bus_for_each_drv
);
EXPORT_SYMBOL_GPL
(
bus_for_each_drv
);
EXPORT_SYMBOL_GPL
(
bus_add_device
);
EXPORT_SYMBOL_GPL
(
bus_add_device
);
...
...
drivers/base/core.c
View file @
bd53d127
...
@@ -333,7 +333,7 @@ void device_del(struct device * dev)
...
@@ -333,7 +333,7 @@ void device_del(struct device * dev)
struct
device
*
parent
=
dev
->
parent
;
struct
device
*
parent
=
dev
->
parent
;
if
(
parent
)
if
(
parent
)
klist_
remove
(
&
dev
->
knode_parent
);
klist_
del
(
&
dev
->
knode_parent
);
/* 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...
...
...
drivers/base/dd.c
View file @
bd53d127
...
@@ -65,7 +65,7 @@ void device_bind_driver(struct device * dev)
...
@@ -65,7 +65,7 @@ void device_bind_driver(struct device * dev)
*
*
* This function must be called with @dev->sem held.
* This function must be called with @dev->sem held.
*/
*/
static
int
driver_probe_device
(
struct
device_driver
*
drv
,
struct
device
*
dev
)
int
driver_probe_device
(
struct
device_driver
*
drv
,
struct
device
*
dev
)
{
{
int
ret
=
0
;
int
ret
=
0
;
...
...
drivers/base/driver.c
View file @
bd53d127
...
@@ -55,6 +55,41 @@ int driver_for_each_device(struct device_driver * drv, struct device * start,
...
@@ -55,6 +55,41 @@ int driver_for_each_device(struct device_driver * drv, struct device * start,
EXPORT_SYMBOL_GPL
(
driver_for_each_device
);
EXPORT_SYMBOL_GPL
(
driver_for_each_device
);
/**
* driver_find_device - device iterator for locating a particular device.
* @driver: The device's driver
* @start: Device to begin with
* @data: Data to pass to match function
* @match: Callback function to check device
*
* This is similar to the driver_for_each_device() function above, but
* it returns a reference to a device that is 'found' for later use, as
* determined by the @match callback.
*
* The callback should return 0 if the device doesn't match and non-zero
* if it does. If the callback returns non-zero, this function will
* return to the caller and not iterate over any more devices.
*/
struct
device
*
driver_find_device
(
struct
device_driver
*
drv
,
struct
device
*
start
,
void
*
data
,
int
(
*
match
)(
struct
device
*
,
void
*
))
{
struct
klist_iter
i
;
struct
device
*
dev
;
if
(
!
drv
)
return
NULL
;
klist_iter_init_node
(
&
drv
->
klist_devices
,
&
i
,
(
start
?
&
start
->
knode_driver
:
NULL
));
while
((
dev
=
next_device
(
&
i
)))
if
(
match
(
dev
,
data
)
&&
get_device
(
dev
))
break
;
klist_iter_exit
(
&
i
);
return
dev
;
}
EXPORT_SYMBOL_GPL
(
driver_find_device
);
/**
/**
* driver_create_file - create sysfs file for driver.
* driver_create_file - create sysfs file for driver.
* @drv: driver.
* @drv: driver.
...
...
include/linux/device.h
View file @
bd53d127
...
@@ -69,7 +69,7 @@ struct bus_type {
...
@@ -69,7 +69,7 @@ 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
);
extern
void
bus_unregister
(
struct
bus_type
*
bus
);
extern
int
bus_rescan_devices
(
struct
bus_type
*
bus
);
extern
void
bus_rescan_devices
(
struct
bus_type
*
bus
);
extern
struct
bus_type
*
get_bus
(
struct
bus_type
*
bus
);
extern
struct
bus_type
*
get_bus
(
struct
bus_type
*
bus
);
extern
void
put_bus
(
struct
bus_type
*
bus
);
extern
void
put_bus
(
struct
bus_type
*
bus
);
...
@@ -80,6 +80,8 @@ extern struct bus_type * find_bus(char * name);
...
@@ -80,6 +80,8 @@ extern struct bus_type * find_bus(char * name);
int
bus_for_each_dev
(
struct
bus_type
*
bus
,
struct
device
*
start
,
void
*
data
,
int
bus_for_each_dev
(
struct
bus_type
*
bus
,
struct
device
*
start
,
void
*
data
,
int
(
*
fn
)(
struct
device
*
,
void
*
));
int
(
*
fn
)(
struct
device
*
,
void
*
));
struct
device
*
bus_find_device
(
struct
bus_type
*
bus
,
struct
device
*
start
,
void
*
data
,
int
(
*
match
)(
struct
device
*
,
void
*
));
int
bus_for_each_drv
(
struct
bus_type
*
bus
,
struct
device_driver
*
start
,
int
bus_for_each_drv
(
struct
bus_type
*
bus
,
struct
device_driver
*
start
,
void
*
data
,
int
(
*
fn
)(
struct
device_driver
*
,
void
*
));
void
*
data
,
int
(
*
fn
)(
struct
device_driver
*
,
void
*
));
...
@@ -142,6 +144,9 @@ extern void driver_remove_file(struct device_driver *, struct driver_attribute *
...
@@ -142,6 +144,9 @@ extern void driver_remove_file(struct device_driver *, struct driver_attribute *
extern
int
driver_for_each_device
(
struct
device_driver
*
drv
,
struct
device
*
start
,
extern
int
driver_for_each_device
(
struct
device_driver
*
drv
,
struct
device
*
start
,
void
*
data
,
int
(
*
fn
)(
struct
device
*
,
void
*
));
void
*
data
,
int
(
*
fn
)(
struct
device
*
,
void
*
));
struct
device
*
driver_find_device
(
struct
device_driver
*
drv
,
struct
device
*
start
,
void
*
data
,
int
(
*
match
)(
struct
device
*
,
void
*
));
/*
/*
...
...
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