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
9cd52d59
Commit
9cd52d59
authored
Oct 30, 2002
by
Patrick Mochel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
driver model: convert device classes to use struct kobject and sysfs.
parent
117e6adf
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
110 additions
and
162 deletions
+110
-162
drivers/base/class.c
drivers/base/class.c
+107
-0
drivers/base/fs/class.c
drivers/base/fs/class.c
+0
-162
include/linux/device.h
include/linux/device.h
+3
-0
No files found.
drivers/base/class.c
View file @
9cd52d59
...
...
@@ -4,10 +4,98 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
#include "base.h"
static
LIST_HEAD
(
class_list
);
#define to_class_attr(_attr) container_of(_attr,struct devclass_attribute,attr)
#define to_class(obj) container_of(obj,struct device_class,subsys.kobj)
static
ssize_t
devclass_attr_show
(
struct
kobject
*
kobj
,
struct
attribute
*
attr
,
char
*
buf
,
size_t
count
,
loff_t
off
)
{
struct
devclass_attribute
*
class_attr
=
to_class_attr
(
attr
);
struct
device_class
*
dc
=
to_class
(
kobj
);
ssize_t
ret
=
0
;
if
(
class_attr
->
show
)
ret
=
class_attr
->
show
(
dc
,
buf
,
count
,
off
);
return
ret
;
}
static
ssize_t
devclass_attr_store
(
struct
kobject
*
kobj
,
struct
attribute
*
attr
,
const
char
*
buf
,
size_t
count
,
loff_t
off
)
{
struct
devclass_attribute
*
class_attr
=
to_class_attr
(
attr
);
struct
device_class
*
dc
=
to_class
(
kobj
);
ssize_t
ret
=
0
;
if
(
class_attr
->
store
)
ret
=
class_attr
->
store
(
dc
,
buf
,
count
,
off
);
return
ret
;
}
static
struct
sysfs_ops
class_sysfs_ops
=
{
show:
devclass_attr_show
,
store:
devclass_attr_store
,
};
static
struct
subsystem
class_subsys
=
{
.
kobj
=
{
.
name
=
"class"
,
},
.
sysfs_ops
=
&
class_sysfs_ops
,
};
int
devclass_dev_link
(
struct
device_class
*
cls
,
struct
device
*
dev
)
{
char
linkname
[
16
];
snprintf
(
linkname
,
16
,
"%u"
,
dev
->
class_num
);
return
sysfs_create_link
(
&
cls
->
devsubsys
.
kobj
,
&
dev
->
kobj
,
linkname
);
}
void
devclass_dev_unlink
(
struct
device_class
*
cls
,
struct
device
*
dev
)
{
char
linkname
[
16
];
snprintf
(
linkname
,
16
,
"%u"
,
dev
->
class_num
);
sysfs_remove_link
(
&
cls
->
devsubsys
.
kobj
,
linkname
);
}
int
devclass_drv_link
(
struct
device_driver
*
drv
)
{
char
name
[
KOBJ_NAME_LEN
*
3
];
snprintf
(
name
,
KOBJ_NAME_LEN
*
3
,
"%s:%s"
,
drv
->
bus
->
name
,
drv
->
name
);
return
sysfs_create_link
(
&
drv
->
devclass
->
drvsubsys
.
kobj
,
&
drv
->
kobj
,
name
);
}
void
devclass_drv_unlink
(
struct
device_driver
*
drv
)
{
char
name
[
KOBJ_NAME_LEN
*
3
];
snprintf
(
name
,
KOBJ_NAME_LEN
*
3
,
"%s:%s"
,
drv
->
bus
->
name
,
drv
->
name
);
return
sysfs_remove_link
(
&
drv
->
devclass
->
drvsubsys
.
kobj
,
name
);
}
int
devclass_create_file
(
struct
device_class
*
cls
,
struct
devclass_attribute
*
attr
)
{
int
error
;
if
(
cls
)
{
error
=
sysfs_create_file
(
&
cls
->
subsys
.
kobj
,
&
attr
->
attr
);
}
else
error
=
-
EINVAL
;
return
error
;
}
void
devclass_remove_file
(
struct
device_class
*
cls
,
struct
devclass_attribute
*
attr
)
{
if
(
cls
)
sysfs_remove_file
(
&
cls
->
subsys
.
kobj
,
&
attr
->
attr
);
}
int
devclass_add_driver
(
struct
device_driver
*
drv
)
{
struct
device_class
*
cls
=
get_devclass
(
drv
->
devclass
);
...
...
@@ -150,6 +238,18 @@ int devclass_register(struct device_class * cls)
cls
->
present
=
1
;
pr_debug
(
"device class '%s': registering
\n
"
,
cls
->
name
);
strncpy
(
cls
->
subsys
.
kobj
.
name
,
cls
->
name
,
KOBJ_NAME_LEN
);
cls
->
subsys
.
parent
=
&
class_subsys
;
subsystem_register
(
&
cls
->
subsys
);
snprintf
(
cls
->
devsubsys
.
kobj
.
name
,
"devices"
,
KOBJ_NAME_LEN
);
cls
->
devsubsys
.
parent
=
&
cls
->
subsys
;
subsystem_register
(
&
cls
->
devsubsys
);
snprintf
(
cls
->
drvsubsys
.
kobj
.
name
,
"drivers"
,
KOBJ_NAME_LEN
);
cls
->
drvsubsys
.
parent
=
&
cls
->
subsys
;
subsystem_register
(
&
cls
->
drvsubsys
);
spin_lock
(
&
device_lock
);
list_add_tail
(
&
cls
->
node
,
&
class_list
);
spin_unlock
(
&
device_lock
);
...
...
@@ -167,6 +267,13 @@ void devclass_unregister(struct device_class * cls)
put_devclass
(
cls
);
}
static
int
__init
class_subsys_init
(
void
)
{
return
subsystem_register
(
&
class_subsys
);
}
core_initcall
(
class_subsys_init
);
EXPORT_SYMBOL
(
devclass_register
);
EXPORT_SYMBOL
(
devclass_unregister
);
EXPORT_SYMBOL
(
get_devclass
);
...
...
drivers/base/fs/class.c
View file @
9cd52d59
...
...
@@ -11,167 +11,6 @@
static
struct
driver_dir_entry
class_dir
;
#define to_class_attr(_attr) container_of(_attr,struct devclass_attribute,attr)
#define to_class(d) container_of(d,struct device_class,dir)
static
ssize_t
devclass_attr_show
(
struct
driver_dir_entry
*
dir
,
struct
attribute
*
attr
,
char
*
buf
,
size_t
count
,
loff_t
off
)
{
struct
devclass_attribute
*
class_attr
=
to_class_attr
(
attr
);
struct
device_class
*
dc
=
to_class
(
dir
);
ssize_t
ret
=
0
;
if
(
class_attr
->
show
)
ret
=
class_attr
->
show
(
dc
,
buf
,
count
,
off
);
return
ret
;
}
static
ssize_t
devclass_attr_store
(
struct
driver_dir_entry
*
dir
,
struct
attribute
*
attr
,
const
char
*
buf
,
size_t
count
,
loff_t
off
)
{
struct
devclass_attribute
*
class_attr
=
to_class_attr
(
attr
);
struct
device_class
*
dc
=
to_class
(
dir
);
ssize_t
ret
=
0
;
if
(
class_attr
->
store
)
ret
=
class_attr
->
store
(
dc
,
buf
,
count
,
off
);
return
ret
;
}
static
struct
driverfs_ops
devclass_attr_ops
=
{
show:
devclass_attr_show
,
store:
devclass_attr_store
,
};
int
devclass_create_file
(
struct
device_class
*
dc
,
struct
devclass_attribute
*
attr
)
{
int
error
;
if
(
dc
)
{
error
=
driverfs_create_file
(
&
attr
->
attr
,
&
dc
->
dir
);
}
else
error
=
-
EINVAL
;
return
error
;
}
void
devclass_remove_file
(
struct
device_class
*
dc
,
struct
devclass_attribute
*
attr
)
{
if
(
dc
)
driverfs_remove_file
(
&
dc
->
dir
,
attr
->
attr
.
name
);
}
/**
* devclass_dev_link - create symlink to device's directory
* @cls - device class we're a part of
* @dev - device we're linking to
*
* Create a symlink in the class's devices/ directory to @dev's
* directory in the physical hierarchy. The name is the device's
* class-enumerated value (struct device::class_num). We're
* creating:
* class/<class name>/devices/<link name> ->
* root/<path to device>/<device's dir>
* So, the link looks like:
* ../../../root/<path to device>/
*/
int
devclass_dev_link
(
struct
device_class
*
cls
,
struct
device
*
dev
)
{
char
linkname
[
16
];
char
*
path
;
int
length
;
int
error
;
length
=
get_devpath_length
(
dev
);
length
+=
strlen
(
"../../../root"
);
if
(
length
>
PATH_MAX
)
return
-
ENAMETOOLONG
;
if
(
!
(
path
=
kmalloc
(
length
,
GFP_KERNEL
)))
return
-
ENOMEM
;
memset
(
path
,
0
,
length
);
strcpy
(
path
,
"../../../root"
);
fill_devpath
(
dev
,
path
,
length
);
snprintf
(
linkname
,
16
,
"%u"
,
dev
->
class_num
);
error
=
driverfs_create_symlink
(
&
cls
->
device_dir
,
linkname
,
path
);
kfree
(
path
);
return
error
;
}
void
devclass_dev_unlink
(
struct
device_class
*
cls
,
struct
device
*
dev
)
{
char
linkname
[
16
];
snprintf
(
linkname
,
16
,
"%u"
,
dev
->
class_num
);
driverfs_remove_file
(
&
cls
->
device_dir
,
linkname
);
}
/**
* devclass_drv_link - create symlink to driver's directory
* @drv: driver we're linking up
*
* Create a symlink in the class's drivers/ directory to @drv's
* directory (in the bus's directory). It's name is <bus>:<driver>
* to prevent naming conflicts.
*
* We're creating
* class/<class name>/drivers/<link name> ->
* bus/<bus name>/drivers/<driver name>/
* So, the link looks like:
* ../../../bus/<bus name>/drivers/<driver name>
*/
int
devclass_drv_link
(
struct
device_driver
*
drv
)
{
char
*
name
;
char
*
path
;
int
namelen
;
int
pathlen
;
int
error
=
0
;
namelen
=
strlen
(
drv
->
name
)
+
strlen
(
drv
->
bus
->
name
)
+
2
;
name
=
kmalloc
(
namelen
,
GFP_KERNEL
);
if
(
!
name
)
return
-
ENOMEM
;
snprintf
(
name
,
namelen
,
"%s:%s"
,
drv
->
bus
->
name
,
drv
->
name
);
pathlen
=
strlen
(
"../../../bus/"
)
+
strlen
(
drv
->
bus
->
name
)
+
strlen
(
"/drivers/"
)
+
strlen
(
drv
->
name
)
+
1
;
if
(
!
(
path
=
kmalloc
(
pathlen
,
GFP_KERNEL
)))
{
error
=
-
ENOMEM
;
goto
Done
;
}
snprintf
(
path
,
pathlen
,
"%s%s%s%s"
,
"../../../bus/"
,
drv
->
bus
->
name
,
"/drivers/"
,
drv
->
name
);
error
=
driverfs_create_symlink
(
&
drv
->
devclass
->
driver_dir
,
name
,
path
);
Done:
kfree
(
name
);
kfree
(
path
);
return
error
;
}
void
devclass_drv_unlink
(
struct
device_driver
*
drv
)
{
char
*
name
;
int
length
;
length
=
strlen
(
drv
->
name
)
+
strlen
(
drv
->
bus
->
name
)
+
2
;
if
((
name
=
kmalloc
(
length
,
GFP_KERNEL
)))
{
driverfs_remove_file
(
&
drv
->
devclass
->
driver_dir
,
name
);
kfree
(
name
);
}
}
void
devclass_remove_dir
(
struct
device_class
*
dc
)
{
driverfs_remove_dir
(
&
dc
->
device_dir
);
...
...
@@ -184,7 +23,6 @@ int devclass_make_dir(struct device_class * dc)
int
error
;
dc
->
dir
.
name
=
dc
->
name
;
dc
->
dir
.
ops
=
&
devclass_attr_ops
;
error
=
device_create_dir
(
&
dc
->
dir
,
&
class_dir
);
if
(
!
error
)
{
dc
->
driver_dir
.
name
=
"drivers"
;
...
...
include/linux/device.h
View file @
9cd52d59
...
...
@@ -182,6 +182,9 @@ struct device_class {
u32
devnum
;
struct
subsystem
subsys
;
struct
subsystem
devsubsys
;
struct
subsystem
drvsubsys
;
struct
list_head
node
;
struct
list_head
drivers
;
struct
list_head
intf_list
;
...
...
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