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
f65e7769
Commit
f65e7769
authored
Sep 06, 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
8566cfc9
d856f1e3
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
178 additions
and
70 deletions
+178
-70
Documentation/filesystems/sysfs.txt
Documentation/filesystems/sysfs.txt
+14
-14
drivers/base/bus.c
drivers/base/bus.c
+5
-3
drivers/base/class.c
drivers/base/class.c
+33
-6
drivers/base/core.c
drivers/base/core.c
+1
-1
drivers/base/dd.c
drivers/base/dd.c
+1
-1
drivers/base/sys.c
drivers/base/sys.c
+85
-25
drivers/block/floppy.c
drivers/block/floppy.c
+28
-13
drivers/usb/core/hcd.c
drivers/usb/core/hcd.c
+1
-1
include/linux/klist.h
include/linux/klist.h
+6
-2
lib/klist.c
lib/klist.c
+4
-4
No files found.
Documentation/filesystems/sysfs.txt
View file @
f65e7769
...
...
@@ -90,7 +90,7 @@ void device_remove_file(struct device *, struct device_attribute *);
It also defines this helper for defining device attributes:
#define DEVICE_ATTR(_name,
_mode,_show,
_store) \
#define DEVICE_ATTR(_name,
_mode, _show,
_store) \
struct device_attribute dev_attr_##_name = { \
.attr = {.name = __stringify(_name) , .mode = _mode }, \
.show = _show, \
...
...
@@ -99,14 +99,14 @@ struct device_attribute dev_attr_##_name = { \
For example, declaring
static DEVICE_ATTR(foo,
0644,show_foo,
store_foo);
static DEVICE_ATTR(foo,
S_IWUSR | S_IRUGO, show_foo,
store_foo);
is equivalent to doing:
static struct device_attribute dev_attr_foo = {
.attr = {
.name = "foo",
.mode =
0644
,
.mode =
S_IWUSR | S_IRUGO
,
},
.show = show_foo,
.store = store_foo,
...
...
@@ -121,8 +121,8 @@ set of sysfs operations for forwarding read and write calls to the
show and store methods of the attribute owners.
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *,char *);
ssize_t (*store)(struct kobject *,
struct attribute *,
const char *);
ssize_t (*show)(struct kobject *, struct attribute *,
char *);
ssize_t (*store)(struct kobject *,
struct attribute *,
const char *);
};
[ Subsystems should have already defined a struct kobj_type as a
...
...
@@ -137,7 +137,7 @@ calls the associated methods.
To illustrate:
#define to_dev_attr(_attr) container_of(_attr,
struct device_attribute,
attr)
#define to_dev_attr(_attr) container_of(_attr,
struct device_attribute,
attr)
#define to_dev(d) container_of(d, struct device, kobj)
static ssize_t
...
...
@@ -148,7 +148,7 @@ dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
ssize_t ret = 0;
if (dev_attr->show)
ret = dev_attr->show(dev,buf);
ret = dev_attr->show(dev,
buf);
return ret;
}
...
...
@@ -216,16 +216,16 @@ A very simple (and naive) implementation of a device attribute is:
static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"%s\n",
dev->name);
return snprintf(buf, PAGE_SIZE, "%s\n",
dev->name);
}
static ssize_t store_name(struct device * dev, const char * buf)
{
sscanf(buf,
"%20s",
dev->name);
return str
len(buf
);
sscanf(buf,
"%20s",
dev->name);
return str
nlen(buf, PAGE_SIZE
);
}
static DEVICE_ATTR(name,
S_IRUGO,show_name,
store_name);
static DEVICE_ATTR(name,
S_IRUGO, show_name,
store_name);
(Note that the real implementation doesn't allow userspace to set the
...
...
@@ -290,7 +290,7 @@ struct device_attribute {
Declaring:
DEVICE_ATTR(_name,
_str,_mode,_show,
_store);
DEVICE_ATTR(_name,
_str, _mode, _show,
_store);
Creation/Removal:
...
...
@@ -310,7 +310,7 @@ struct bus_attribute {
Declaring:
BUS_ATTR(_name,
_mode,_show,
_store)
BUS_ATTR(_name,
_mode, _show,
_store)
Creation/Removal:
...
...
@@ -331,7 +331,7 @@ struct driver_attribute {
Declaring:
DRIVER_ATTR(_name,
_mode,_show,
_store)
DRIVER_ATTR(_name,
_mode, _show,
_store)
Creation/Removal:
...
...
drivers/base/bus.c
View file @
f65e7769
...
...
@@ -156,7 +156,9 @@ static ssize_t driver_unbind(struct device_driver *drv,
device_release_driver
(
dev
);
err
=
count
;
}
if
(
err
)
return
err
;
return
count
;
}
static
DRIVER_ATTR
(
unbind
,
S_IWUSR
,
NULL
,
driver_unbind
);
...
...
@@ -358,7 +360,7 @@ int bus_add_device(struct device * dev)
if
(
bus
)
{
pr_debug
(
"bus %s: add device %s
\n
"
,
bus
->
name
,
dev
->
bus_id
);
device_attach
(
dev
);
klist_add_tail
(
&
bus
->
klist_devices
,
&
dev
->
knode_bu
s
);
klist_add_tail
(
&
dev
->
knode_bus
,
&
bus
->
klist_device
s
);
error
=
device_add_attrs
(
bus
,
dev
);
if
(
!
error
)
{
sysfs_create_link
(
&
bus
->
devices
.
kobj
,
&
dev
->
kobj
,
dev
->
bus_id
);
...
...
@@ -446,7 +448,7 @@ int bus_add_driver(struct device_driver * drv)
}
driver_attach
(
drv
);
klist_add_tail
(
&
bus
->
klist_drivers
,
&
drv
->
knode_bu
s
);
klist_add_tail
(
&
drv
->
knode_bus
,
&
bus
->
klist_driver
s
);
module_add_driver
(
drv
->
owner
,
drv
);
driver_add_attrs
(
bus
,
drv
);
...
...
drivers/base/class.c
View file @
f65e7769
...
...
@@ -299,10 +299,8 @@ static void class_dev_release(struct kobject * kobj)
pr_debug
(
"device class '%s': release.
\n
"
,
cd
->
class_id
);
if
(
cd
->
devt_attr
)
{
kfree
(
cd
->
devt_attr
);
cd
->
devt_attr
=
NULL
;
}
if
(
cls
->
release
)
cls
->
release
(
cd
);
...
...
@@ -452,10 +450,29 @@ void class_device_initialize(struct class_device *class_dev)
INIT_LIST_HEAD
(
&
class_dev
->
node
);
}
static
char
*
make_class_name
(
struct
class_device
*
class_dev
)
{
char
*
name
;
int
size
;
size
=
strlen
(
class_dev
->
class
->
name
)
+
strlen
(
kobject_name
(
&
class_dev
->
kobj
))
+
2
;
name
=
kmalloc
(
size
,
GFP_KERNEL
);
if
(
!
name
)
return
ERR_PTR
(
-
ENOMEM
);
strcpy
(
name
,
class_dev
->
class
->
name
);
strcat
(
name
,
":"
);
strcat
(
name
,
kobject_name
(
&
class_dev
->
kobj
));
return
name
;
}
int
class_device_add
(
struct
class_device
*
class_dev
)
{
struct
class
*
parent
=
NULL
;
struct
class_interface
*
class_intf
;
char
*
class_name
=
NULL
;
int
error
;
class_dev
=
class_device_get
(
class_dev
);
...
...
@@ -500,9 +517,13 @@ int class_device_add(struct class_device *class_dev)
}
class_device_add_attrs
(
class_dev
);
if
(
class_dev
->
dev
)
if
(
class_dev
->
dev
)
{
class_name
=
make_class_name
(
class_dev
);
sysfs_create_link
(
&
class_dev
->
kobj
,
&
class_dev
->
dev
->
kobj
,
"device"
);
sysfs_create_link
(
&
class_dev
->
dev
->
kobj
,
&
class_dev
->
kobj
,
class_name
);
}
/* notify any interfaces this device is now here */
if
(
parent
)
{
...
...
@@ -519,6 +540,7 @@ int class_device_add(struct class_device *class_dev)
if
(
error
&&
parent
)
class_put
(
parent
);
class_device_put
(
class_dev
);
kfree
(
class_name
);
return
error
;
}
...
...
@@ -584,6 +606,7 @@ void class_device_del(struct class_device *class_dev)
{
struct
class
*
parent
=
class_dev
->
class
;
struct
class_interface
*
class_intf
;
char
*
class_name
=
NULL
;
if
(
parent
)
{
down
(
&
parent
->
sem
);
...
...
@@ -594,8 +617,11 @@ void class_device_del(struct class_device *class_dev)
up
(
&
parent
->
sem
);
}
if
(
class_dev
->
dev
)
if
(
class_dev
->
dev
)
{
class_name
=
make_class_name
(
class_dev
);
sysfs_remove_link
(
&
class_dev
->
kobj
,
"device"
);
sysfs_remove_link
(
&
class_dev
->
dev
->
kobj
,
class_name
);
}
if
(
class_dev
->
devt_attr
)
class_device_remove_file
(
class_dev
,
class_dev
->
devt_attr
);
class_device_remove_attrs
(
class_dev
);
...
...
@@ -605,6 +631,7 @@ void class_device_del(struct class_device *class_dev)
if
(
parent
)
class_put
(
parent
);
kfree
(
class_name
);
}
void
class_device_unregister
(
struct
class_device
*
class_dev
)
...
...
drivers/base/core.c
View file @
f65e7769
...
...
@@ -249,7 +249,7 @@ int device_add(struct device *dev)
if
((
error
=
bus_add_device
(
dev
)))
goto
BusError
;
if
(
parent
)
klist_add_tail
(
&
parent
->
klist_children
,
&
dev
->
knode_parent
);
klist_add_tail
(
&
dev
->
knode_parent
,
&
parent
->
klist_children
);
/* notify platform of device entry */
if
(
platform_notify
)
...
...
drivers/base/dd.c
View file @
f65e7769
...
...
@@ -42,7 +42,7 @@ void device_bind_driver(struct device * dev)
{
pr_debug
(
"bound device '%s' to driver '%s'
\n
"
,
dev
->
bus_id
,
dev
->
driver
->
name
);
klist_add_tail
(
&
dev
->
driver
->
klist_devices
,
&
dev
->
knode_driver
);
klist_add_tail
(
&
dev
->
knode_driver
,
&
dev
->
driver
->
klist_devices
);
sysfs_create_link
(
&
dev
->
driver
->
kobj
,
&
dev
->
kobj
,
kobject_name
(
&
dev
->
kobj
));
sysfs_create_link
(
&
dev
->
kobj
,
&
dev
->
driver
->
kobj
,
"driver"
);
...
...
drivers/base/sys.c
View file @
f65e7769
...
...
@@ -288,6 +288,27 @@ void sysdev_shutdown(void)
up
(
&
sysdev_drivers_lock
);
}
static
void
__sysdev_resume
(
struct
sys_device
*
dev
)
{
struct
sysdev_class
*
cls
=
dev
->
cls
;
struct
sysdev_driver
*
drv
;
/* First, call the class-specific one */
if
(
cls
->
resume
)
cls
->
resume
(
dev
);
/* Call auxillary drivers next. */
list_for_each_entry
(
drv
,
&
cls
->
drivers
,
entry
)
{
if
(
drv
->
resume
)
drv
->
resume
(
dev
);
}
/* Call global drivers. */
list_for_each_entry
(
drv
,
&
sysdev_drivers
,
entry
)
{
if
(
drv
->
resume
)
drv
->
resume
(
dev
);
}
}
/**
* sysdev_suspend - Suspend all system devices.
...
...
@@ -305,38 +326,93 @@ void sysdev_shutdown(void)
int
sysdev_suspend
(
pm_message_t
state
)
{
struct
sysdev_class
*
cls
;
struct
sys_device
*
sysdev
,
*
err_dev
;
struct
sysdev_driver
*
drv
,
*
err_drv
;
int
ret
;
pr_debug
(
"Suspending System Devices
\n
"
);
list_for_each_entry_reverse
(
cls
,
&
system_subsys
.
kset
.
list
,
kset
.
kobj
.
entry
)
{
struct
sys_device
*
sysdev
;
pr_debug
(
"Suspending type '%s':
\n
"
,
kobject_name
(
&
cls
->
kset
.
kobj
));
list_for_each_entry
(
sysdev
,
&
cls
->
kset
.
list
,
kobj
.
entry
)
{
struct
sysdev_driver
*
drv
;
pr_debug
(
" %s
\n
"
,
kobject_name
(
&
sysdev
->
kobj
));
/* Call global drivers first. */
list_for_each_entry
(
drv
,
&
sysdev_drivers
,
entry
)
{
if
(
drv
->
suspend
)
drv
->
suspend
(
sysdev
,
state
);
if
(
drv
->
suspend
)
{
ret
=
drv
->
suspend
(
sysdev
,
state
);
if
(
ret
)
goto
gbl_driver
;
}
}
/* Call auxillary drivers next. */
list_for_each_entry
(
drv
,
&
cls
->
drivers
,
entry
)
{
if
(
drv
->
suspend
)
drv
->
suspend
(
sysdev
,
state
);
if
(
drv
->
suspend
)
{
ret
=
drv
->
suspend
(
sysdev
,
state
);
if
(
ret
)
goto
aux_driver
;
}
}
/* Now call the generic one */
if
(
cls
->
suspend
)
cls
->
suspend
(
sysdev
,
state
);
if
(
cls
->
suspend
)
{
ret
=
cls
->
suspend
(
sysdev
,
state
);
if
(
ret
)
goto
cls_driver
;
}
}
}
return
0
;
/* resume current sysdev */
cls_driver:
drv
=
NULL
;
printk
(
KERN_ERR
"Class suspend failed for %s
\n
"
,
kobject_name
(
&
sysdev
->
kobj
));
aux_driver:
if
(
drv
)
printk
(
KERN_ERR
"Class driver suspend failed for %s
\n
"
,
kobject_name
(
&
sysdev
->
kobj
));
list_for_each_entry
(
err_drv
,
&
cls
->
drivers
,
entry
)
{
if
(
err_drv
==
drv
)
break
;
if
(
err_drv
->
resume
)
err_drv
->
resume
(
sysdev
);
}
drv
=
NULL
;
gbl_driver:
if
(
drv
)
printk
(
KERN_ERR
"sysdev driver suspend failed for %s
\n
"
,
kobject_name
(
&
sysdev
->
kobj
));
list_for_each_entry
(
err_drv
,
&
sysdev_drivers
,
entry
)
{
if
(
err_drv
==
drv
)
break
;
if
(
err_drv
->
resume
)
err_drv
->
resume
(
sysdev
);
}
/* resume other sysdevs in current class */
list_for_each_entry
(
err_dev
,
&
cls
->
kset
.
list
,
kobj
.
entry
)
{
if
(
err_dev
==
sysdev
)
break
;
pr_debug
(
" %s
\n
"
,
kobject_name
(
&
err_dev
->
kobj
));
__sysdev_resume
(
err_dev
);
}
/* resume other classes */
list_for_each_entry_continue
(
cls
,
&
system_subsys
.
kset
.
list
,
kset
.
kobj
.
entry
)
{
list_for_each_entry
(
err_dev
,
&
cls
->
kset
.
list
,
kobj
.
entry
)
{
pr_debug
(
" %s
\n
"
,
kobject_name
(
&
err_dev
->
kobj
));
__sysdev_resume
(
err_dev
);
}
}
return
ret
;
}
...
...
@@ -362,25 +438,9 @@ int sysdev_resume(void)
kobject_name
(
&
cls
->
kset
.
kobj
));
list_for_each_entry
(
sysdev
,
&
cls
->
kset
.
list
,
kobj
.
entry
)
{
struct
sysdev_driver
*
drv
;
pr_debug
(
" %s
\n
"
,
kobject_name
(
&
sysdev
->
kobj
));
/* First, call the class-specific one */
if
(
cls
->
resume
)
cls
->
resume
(
sysdev
);
/* Call auxillary drivers next. */
list_for_each_entry
(
drv
,
&
cls
->
drivers
,
entry
)
{
if
(
drv
->
resume
)
drv
->
resume
(
sysdev
);
}
/* Call global drivers. */
list_for_each_entry
(
drv
,
&
sysdev_drivers
,
entry
)
{
if
(
drv
->
resume
)
drv
->
resume
(
sysdev
);
}
__sysdev_resume
(
sysdev
);
}
}
return
0
;
...
...
drivers/block/floppy.c
View file @
f65e7769
...
...
@@ -493,6 +493,8 @@ static struct floppy_struct user_params[N_DRIVE];
static
sector_t
floppy_sizes
[
256
];
static
char
floppy_device_name
[]
=
"floppy"
;
/*
* The driver is trying to determine the correct media format
* while probing is set. rw_interrupt() clears it after a
...
...
@@ -4191,18 +4193,24 @@ static int __init floppy_setup(char *str)
static
int
have_no_fdc
=
-
ENODEV
;
static
ssize_t
floppy_cmos_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
platform_device
*
p
;
int
drive
;
p
=
container_of
(
dev
,
struct
platform_device
,
dev
);
drive
=
p
->
id
;
return
sprintf
(
buf
,
"%X
\n
"
,
UDP
->
cmos
);
}
DEVICE_ATTR
(
cmos
,
S_IRUGO
,
floppy_cmos_show
,
NULL
);
static
void
floppy_device_release
(
struct
device
*
dev
)
{
complete
(
&
device_release
);
}
static
struct
platform_device
floppy_device
=
{
.
name
=
"floppy"
,
.
id
=
0
,
.
dev
=
{
.
release
=
floppy_device_release
,
}
};
static
struct
platform_device
floppy_device
[
N_DRIVE
];
static
struct
kobject
*
floppy_find
(
dev_t
dev
,
int
*
part
,
void
*
data
)
{
...
...
@@ -4370,20 +4378,26 @@ static int __init floppy_init(void)
goto
out_flush_work
;
}
err
=
platform_device_register
(
&
floppy_device
);
if
(
err
)
goto
out_flush_work
;
for
(
drive
=
0
;
drive
<
N_DRIVE
;
drive
++
)
{
if
(
!
(
allowed_drive_mask
&
(
1
<<
drive
)))
continue
;
if
(
fdc_state
[
FDC
(
drive
)].
version
==
FDC_NONE
)
continue
;
floppy_device
[
drive
].
name
=
floppy_device_name
;
floppy_device
[
drive
].
id
=
drive
;
floppy_device
[
drive
].
dev
.
release
=
floppy_device_release
;
err
=
platform_device_register
(
&
floppy_device
[
drive
]);
if
(
err
)
goto
out_flush_work
;
device_create_file
(
&
floppy_device
[
drive
].
dev
,
&
dev_attr_cmos
);
/* to be cleaned up... */
disks
[
drive
]
->
private_data
=
(
void
*
)(
long
)
drive
;
disks
[
drive
]
->
queue
=
floppy_queue
;
disks
[
drive
]
->
flags
|=
GENHD_FL_REMOVABLE
;
disks
[
drive
]
->
driverfs_dev
=
&
floppy_device
.
dev
;
disks
[
drive
]
->
driverfs_dev
=
&
floppy_device
[
drive
]
.
dev
;
add_disk
(
disks
[
drive
]);
}
...
...
@@ -4603,10 +4617,11 @@ void cleanup_module(void)
fdc_state
[
FDC
(
drive
)].
version
!=
FDC_NONE
)
{
del_gendisk
(
disks
[
drive
]);
unregister_devfs_entries
(
drive
);
device_remove_file
(
&
floppy_device
[
drive
].
dev
,
&
dev_attr_cmos
);
platform_device_unregister
(
&
floppy_device
[
drive
]);
}
put_disk
(
disks
[
drive
]);
}
platform_device_unregister
(
&
floppy_device
);
devfs_remove
(
"floppy"
);
del_timer_sync
(
&
fd_timeout
);
...
...
drivers/usb/core/hcd.c
View file @
f65e7769
...
...
@@ -782,7 +782,7 @@ static int usb_register_bus(struct usb_bus *bus)
return
-
E2BIG
;
}
bus
->
class_dev
=
class_device_create
(
usb_host_class
,
MKDEV
(
0
,
0
),
bus
->
controller
,
"usb%d"
,
busnum
);
bus
->
class_dev
=
class_device_create
(
usb_host_class
,
MKDEV
(
0
,
0
),
bus
->
controller
,
"usb
_host
%d"
,
busnum
);
if
(
IS_ERR
(
bus
->
class_dev
))
{
clear_bit
(
busnum
,
busmap
.
busmap
);
up
(
&
usb_bus_list_lock
);
...
...
include/linux/klist.h
View file @
f65e7769
...
...
@@ -9,6 +9,9 @@
* This file is rleased under the GPL v2.
*/
#ifndef _LINUX_KLIST_H
#define _LINUX_KLIST_H
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/kref.h>
...
...
@@ -31,8 +34,8 @@ struct klist_node {
struct
completion
n_removed
;
};
extern
void
klist_add_tail
(
struct
klist
*
k
,
struct
klist_node
*
n
);
extern
void
klist_add_head
(
struct
klist
*
k
,
struct
klist_node
*
n
);
extern
void
klist_add_tail
(
struct
klist
_node
*
n
,
struct
klist
*
k
);
extern
void
klist_add_head
(
struct
klist
_node
*
n
,
struct
klist
*
k
);
extern
void
klist_del
(
struct
klist_node
*
n
);
extern
void
klist_remove
(
struct
klist_node
*
n
);
...
...
@@ -53,3 +56,4 @@ extern void klist_iter_init_node(struct klist * k, struct klist_iter * i,
extern
void
klist_iter_exit
(
struct
klist_iter
*
i
);
extern
struct
klist_node
*
klist_next
(
struct
klist_iter
*
i
);
#endif
lib/klist.c
View file @
f65e7769
...
...
@@ -79,11 +79,11 @@ static void klist_node_init(struct klist * k, struct klist_node * n)
/**
* klist_add_head - Initialize a klist_node and add it to front.
* @k: klist it's going on.
* @n: node we're adding.
* @k: klist it's going on.
*/
void
klist_add_head
(
struct
klist
*
k
,
struct
klist_node
*
n
)
void
klist_add_head
(
struct
klist
_node
*
n
,
struct
klist
*
k
)
{
klist_node_init
(
k
,
n
);
add_head
(
k
,
n
);
...
...
@@ -94,11 +94,11 @@ EXPORT_SYMBOL_GPL(klist_add_head);
/**
* klist_add_tail - Initialize a klist_node and add it to back.
* @k: klist it's going on.
* @n: node we're adding.
* @k: klist it's going on.
*/
void
klist_add_tail
(
struct
klist
*
k
,
struct
klist_node
*
n
)
void
klist_add_tail
(
struct
klist
_node
*
n
,
struct
klist
*
k
)
{
klist_node_init
(
k
,
n
);
add_tail
(
k
,
n
);
...
...
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