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
5bb8ea44
Commit
5bb8ea44
authored
May 27, 2004
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Plain Diff
Merge kroah.com:/home/greg/linux/BK/bleed-2.6
into kroah.com:/home/greg/linux/BK/driver-2.6
parents
e743bea2
3eb68d24
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
138 additions
and
370 deletions
+138
-370
drivers/base/power/resume.c
drivers/base/power/resume.c
+4
-1
drivers/base/power/runtime.c
drivers/base/power/runtime.c
+3
-1
drivers/base/power/suspend.c
drivers/base/power/suspend.c
+15
-13
drivers/firmware/Kconfig
drivers/firmware/Kconfig
+0
-8
drivers/firmware/Makefile
drivers/firmware/Makefile
+0
-1
drivers/firmware/smbios.c
drivers/firmware/smbios.c
+0
-248
drivers/firmware/smbios.h
drivers/firmware/smbios.h
+0
-53
fs/sysfs/dir.c
fs/sysfs/dir.c
+11
-1
fs/sysfs/inode.c
fs/sysfs/inode.c
+6
-1
fs/sysfs/symlink.c
fs/sysfs/symlink.c
+94
-41
fs/sysfs/sysfs.h
fs/sysfs/sysfs.h
+5
-2
No files found.
drivers/base/power/resume.c
View file @
5bb8ea44
...
@@ -35,7 +35,10 @@ void dpm_resume(void)
...
@@ -35,7 +35,10 @@ void dpm_resume(void)
struct
list_head
*
entry
=
dpm_off
.
next
;
struct
list_head
*
entry
=
dpm_off
.
next
;
struct
device
*
dev
=
to_device
(
entry
);
struct
device
*
dev
=
to_device
(
entry
);
list_del_init
(
entry
);
list_del_init
(
entry
);
if
(
!
dev
->
power
.
power_state
)
resume_device
(
dev
);
resume_device
(
dev
);
list_add_tail
(
entry
,
&
dpm_active
);
list_add_tail
(
entry
,
&
dpm_active
);
}
}
}
}
...
...
drivers/base/power/runtime.c
View file @
5bb8ea44
...
@@ -12,9 +12,11 @@
...
@@ -12,9 +12,11 @@
static
void
runtime_resume
(
struct
device
*
dev
)
static
void
runtime_resume
(
struct
device
*
dev
)
{
{
dev_dbg
(
dev
,
"resuming
\n
"
);
if
(
!
dev
->
power
.
power_state
)
if
(
!
dev
->
power
.
power_state
)
return
;
return
;
resume_device
(
dev
);
if
(
!
resume_device
(
dev
))
dev
->
power
.
power_state
=
0
;
}
}
...
...
drivers/base/power/suspend.c
View file @
5bb8ea44
...
@@ -39,16 +39,11 @@ int suspend_device(struct device * dev, u32 state)
...
@@ -39,16 +39,11 @@ int suspend_device(struct device * dev, u32 state)
{
{
int
error
=
0
;
int
error
=
0
;
if
(
dev
->
bus
&&
dev
->
bus
->
suspend
)
dev_dbg
(
dev
,
"suspending
\n
"
);
if
(
dev
->
bus
&&
dev
->
bus
->
suspend
&&
!
dev
->
power
.
power_state
)
error
=
dev
->
bus
->
suspend
(
dev
,
state
);
error
=
dev
->
bus
->
suspend
(
dev
,
state
);
if
(
!
error
)
{
list_del
(
&
dev
->
power
.
entry
);
list_add
(
&
dev
->
power
.
entry
,
&
dpm_off
);
}
else
if
(
error
==
-
EAGAIN
)
{
list_del
(
&
dev
->
power
.
entry
);
list_add
(
&
dev
->
power
.
entry
,
&
dpm_off_irq
);
}
return
error
;
return
error
;
}
}
...
@@ -81,11 +76,18 @@ int device_suspend(u32 state)
...
@@ -81,11 +76,18 @@ int device_suspend(u32 state)
while
(
!
list_empty
(
&
dpm_active
))
{
while
(
!
list_empty
(
&
dpm_active
))
{
struct
list_head
*
entry
=
dpm_active
.
prev
;
struct
list_head
*
entry
=
dpm_active
.
prev
;
struct
device
*
dev
=
to_device
(
entry
);
struct
device
*
dev
=
to_device
(
entry
);
if
((
error
=
suspend_device
(
dev
,
state
)))
{
error
=
suspend_device
(
dev
,
state
);
if
(
error
!=
-
EAGAIN
)
if
(
!
error
)
{
list_del
(
&
dev
->
power
.
entry
);
list_add
(
&
dev
->
power
.
entry
,
&
dpm_off
);
}
else
if
(
error
==
-
EAGAIN
)
{
list_del
(
&
dev
->
power
.
entry
);
list_add
(
&
dev
->
power
.
entry
,
&
dpm_off_irq
);
}
else
{
printk
(
KERN_ERR
"Could not suspend device %s: "
"error %d
\n
"
,
kobject_name
(
&
dev
->
kobj
),
error
);
goto
Error
;
goto
Error
;
else
error
=
0
;
}
}
}
}
Done:
Done:
...
...
drivers/firmware/Kconfig
View file @
5bb8ea44
...
@@ -34,12 +34,4 @@ config EFI_VARS
...
@@ -34,12 +34,4 @@ config EFI_VARS
Subsequent efibootmgr releases may be found at:
Subsequent efibootmgr releases may be found at:
http://linux.dell.com/efibootmgr
http://linux.dell.com/efibootmgr
config SMBIOS
tristate "BIOS SMBIOS table access driver."
help
Say Y or M here if you want to enable access to the SMBIOS table
via driverfs. It exposes /sys/firmware/smbios/ subdirectory tree
containing a binary dump of the SMBIOS table header as well as the SMBIOS
table.
endmenu
endmenu
drivers/firmware/Makefile
View file @
5bb8ea44
...
@@ -3,4 +3,3 @@
...
@@ -3,4 +3,3 @@
#
#
obj-$(CONFIG_EDD)
+=
edd.o
obj-$(CONFIG_EDD)
+=
edd.o
obj-$(CONFIG_EFI_VARS)
+=
efivars.o
obj-$(CONFIG_EFI_VARS)
+=
efivars.o
obj-$(CONFIG_SMBIOS)
+=
smbios.o
drivers/firmware/smbios.c
deleted
100644 → 0
View file @
e743bea2
/*
* linux/drivers/firmware/smbios.c
* Copyright (C) 2004 Dell Inc.
* by Michael Brown <Michael_E_Brown@dell.com>
* vim:noet:ts=8:sw=8:filetype=c:textwidth=80:
*
* BIOS SMBIOS Table access
* conformant to DMTF SMBIOS definition
* at http://www.dmtf.org/standards/smbios
*
* This code takes information provided by SMBIOS tables
* and presents it in sysfs as:
* /sys/firmware/smbios
* |--> /table_entry_point
* |--> /table
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License v2.0 as published by
* the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include "smbios.h"
MODULE_AUTHOR
(
"Michael Brown <Michael_E_Brown@Dell.com>"
);
MODULE_DESCRIPTION
(
"sysfs interface to SMBIOS information"
);
MODULE_LICENSE
(
"GPL"
);
#define SMBIOS_VERSION "1.0 2004-04-19"
struct
smbios_device
{
struct
smbios_table_entry_point
table_eps
;
unsigned
int
smbios_table_real_length
;
};
/* there shall be only one */
static
struct
smbios_device
the_smbios_device
;
#define to_smbios_device(obj) container_of(obj,struct smbios_device,kobj)
/* don't currently have any "normal" attributes, so we don't need a way to
* show them. */
static
struct
sysfs_ops
smbios_attr_ops
=
{
};
static
__init
int
checksum_eps
(
struct
smbios_table_entry_point
*
table_eps
)
{
u8
*
p
=
(
u8
*
)
table_eps
;
u8
checksum
=
0
;
int
i
=
0
;
for
(
i
=
0
;
i
<
table_eps
->
eps_length
&&
i
<
sizeof
(
*
table_eps
);
++
i
)
{
checksum
+=
p
[
i
];
}
return
(
checksum
==
0
);
}
static
__init
int
find_table_entry_point
(
struct
smbios_device
*
sdev
)
{
struct
smbios_table_entry_point
*
table_eps
=
&
(
sdev
->
table_eps
);
u32
fp
=
0xF0000
;
while
(
fp
<
0xFFFFF
)
{
isa_memcpy_fromio
(
table_eps
,
fp
,
sizeof
(
*
table_eps
));
if
(
memcmp
(
table_eps
->
anchor
,
"_SM_"
,
4
)
==
0
&&
checksum_eps
(
table_eps
))
{
return
0
;
}
fp
+=
16
;
}
printk
(
KERN_INFO
"SMBIOS table entry point not found in "
"0xF0000 - 0xFFFFF
\n
"
);
return
-
ENODEV
;
}
static
__init
int
find_table_max_address
(
struct
smbios_device
*
sdev
)
{
/* break out on one of three conditions:
* -- hit table_eps.table_length
* -- hit number of items that table claims we have
* -- hit structure type 127
*/
u8
*
buf
=
ioremap
(
sdev
->
table_eps
.
table_address
,
sdev
->
table_eps
.
table_length
);
u8
*
ptr
=
buf
;
int
count
=
0
,
keep_going
=
1
;
int
max_count
=
sdev
->
table_eps
.
table_num_structs
;
int
max_length
=
sdev
->
table_eps
.
table_length
;
while
(
keep_going
&&
((
ptr
-
buf
)
<=
max_length
)
&&
count
<
max_count
){
if
(
ptr
[
0
]
==
0x7F
)
/* ptr[0] is type */
keep_going
=
0
;
ptr
+=
ptr
[
1
];
/* ptr[1] is length, skip structure */
/* skip strings at end of structure */
while
((
ptr
-
buf
)
<
max_length
&&
(
ptr
[
0
]
||
ptr
[
1
]))
++
ptr
;
/* string area ends in double-null. skip it. */
ptr
+=
2
;
++
count
;
}
sdev
->
smbios_table_real_length
=
(
ptr
-
buf
);
iounmap
(
buf
);
if
(
count
!=
max_count
)
printk
(
KERN_INFO
"Warning: SMBIOS table structure count"
" does not match count specified in the"
" table entry point.
\n
"
" Table entry point count: %d
\n
"
" Actual count: %d
\n
"
,
max_count
,
count
);
if
(
keep_going
!=
0
)
printk
(
KERN_INFO
"Warning: SMBIOS table does not end with a"
" structure type 127. This may indicate a"
" truncated table."
);
if
(
sdev
->
smbios_table_real_length
!=
max_length
)
printk
(
KERN_INFO
"Warning: BIOS specified SMBIOS table length"
" does not match calculated length.
\n
"
" BIOS specified: %d
\n
"
" calculated length: %d
\n
"
,
max_length
,
sdev
->
smbios_table_real_length
);
return
sdev
->
smbios_table_real_length
;
}
static
ssize_t
smbios_read_table_entry_point
(
struct
kobject
*
kobj
,
char
*
buffer
,
loff_t
pos
,
size_t
size
)
{
struct
smbios_device
*
sdev
=
&
the_smbios_device
;
const
char
*
p
=
(
const
char
*
)
&
(
sdev
->
table_eps
);
unsigned
int
count
=
size
>
sizeof
(
sdev
->
table_eps
)
?
sizeof
(
sdev
->
table_eps
)
:
size
;
memcpy
(
buffer
,
p
,
count
);
return
count
;
}
static
ssize_t
smbios_read_table
(
struct
kobject
*
kobj
,
char
*
buffer
,
loff_t
pos
,
size_t
size
)
{
struct
smbios_device
*
sdev
=
&
the_smbios_device
;
u8
*
buf
;
unsigned
int
count
=
sdev
->
smbios_table_real_length
-
pos
;
int
i
=
0
;
count
=
count
<
size
?
count
:
size
;
if
(
pos
>
sdev
->
smbios_table_real_length
)
return
0
;
buf
=
ioremap
(
sdev
->
table_eps
.
table_address
,
sdev
->
smbios_table_real_length
);
if
(
buf
==
NULL
)
return
-
ENXIO
;
/* memcpy( buffer, buf+pos, count ); */
for
(
i
=
0
;
i
<
count
;
++
i
)
{
buffer
[
i
]
=
readb
(
buf
+
pos
+
i
);
}
iounmap
(
buf
);
return
count
;
}
static
struct
bin_attribute
tep_attr
=
{
.
attr
=
{.
name
=
"table_entry_point"
,
.
owner
=
THIS_MODULE
,
.
mode
=
0444
},
.
size
=
sizeof
(
struct
smbios_table_entry_point
),
.
read
=
smbios_read_table_entry_point
,
/* not writeable */
};
static
struct
bin_attribute
table_attr
=
{
.
attr
=
{
.
name
=
"table"
,
.
owner
=
THIS_MODULE
,
.
mode
=
0444
},
/* size set later, we don't know it here. */
.
read
=
smbios_read_table
,
/* not writeable */
};
/* no default attributes yet. */
static
struct
attribute
*
def_attrs
[]
=
{
NULL
,
};
static
struct
kobj_type
ktype_smbios
=
{
.
sysfs_ops
=
&
smbios_attr_ops
,
.
default_attrs
=
def_attrs
,
/* statically allocated, no release method necessary */
};
static
decl_subsys
(
smbios
,
&
ktype_smbios
,
NULL
);
static
void
smbios_device_unregister
(
void
)
{
sysfs_remove_bin_file
(
&
smbios_subsys
.
kset
.
kobj
,
&
tep_attr
);
sysfs_remove_bin_file
(
&
smbios_subsys
.
kset
.
kobj
,
&
table_attr
);
}
static
void
__init
smbios_device_register
(
void
)
{
sysfs_create_bin_file
(
&
smbios_subsys
.
kset
.
kobj
,
&
tep_attr
);
sysfs_create_bin_file
(
&
smbios_subsys
.
kset
.
kobj
,
&
table_attr
);
}
static
int
__init
smbios_init
(
void
)
{
int
rc
=
0
;
printk
(
KERN_INFO
"SMBIOS facility v%s
\n
"
,
SMBIOS_VERSION
);
rc
=
find_table_entry_point
(
&
the_smbios_device
);
if
(
rc
)
return
rc
;
table_attr
.
size
=
find_table_max_address
(
&
the_smbios_device
);
rc
=
firmware_register
(
&
smbios_subsys
);
if
(
rc
)
return
rc
;
smbios_device_register
();
return
rc
;
}
static
void
__exit
smbios_exit
(
void
)
{
smbios_device_unregister
();
firmware_unregister
(
&
smbios_subsys
);
}
late_initcall
(
smbios_init
);
module_exit
(
smbios_exit
);
drivers/firmware/smbios.h
deleted
100644 → 0
View file @
e743bea2
/*
* linux/drivers/firmware/smbios.c
* Copyright (C) 2002, 2003, 2004 Dell Inc.
* by Michael Brown <Michael_E_Brown@dell.com>
* vim:noet:ts=8:sw=8:filetype=c:textwidth=80:
*
* BIOS SMBIOS Table access
* conformant to DMTF SMBIOS definition
* at http://www.dmtf.org/standards/smbios
*
* This code takes information provided by SMBIOS tables
* and presents it in sysfs.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License v2.0 as published by
* the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _LINUX_SMBIOS_H
#define _LINUX_SMBIOS_H
#include <linux/types.h>
struct
smbios_table_entry_point
{
u8
anchor
[
4
];
u8
checksum
;
u8
eps_length
;
u8
major_ver
;
u8
minor_ver
;
u16
max_struct_size
;
u8
revision
;
u8
formatted_area
[
5
];
u8
dmi_anchor
[
5
];
u8
intermediate_checksum
;
u16
table_length
;
u32
table_address
;
u16
table_num_structs
;
u8
smbios_bcd_revision
;
}
__attribute__
((
packed
));
struct
smbios_structure_header
{
u8
type
;
u8
length
;
u16
handle
;
}
__attribute__
((
packed
));
#endif
/* _LINUX_SMBIOS_H */
fs/sysfs/dir.c
View file @
5bb8ea44
...
@@ -10,6 +10,8 @@
...
@@ -10,6 +10,8 @@
#include <linux/kobject.h>
#include <linux/kobject.h>
#include "sysfs.h"
#include "sysfs.h"
DECLARE_RWSEM
(
sysfs_rename_sem
);
static
int
init_dir
(
struct
inode
*
inode
)
static
int
init_dir
(
struct
inode
*
inode
)
{
{
inode
->
i_op
=
&
simple_dir_inode_operations
;
inode
->
i_op
=
&
simple_dir_inode_operations
;
...
@@ -134,8 +136,14 @@ void sysfs_remove_dir(struct kobject * kobj)
...
@@ -134,8 +136,14 @@ void sysfs_remove_dir(struct kobject * kobj)
/**
/**
* Unlink and unhash.
* Unlink and unhash.
*/
*/
__d_drop
(
d
);
spin_unlock
(
&
dcache_lock
);
spin_unlock
(
&
dcache_lock
);
d_delete
(
d
);
/* release the target kobject in case of
* a symlink
*/
if
(
S_ISLNK
(
d
->
d_inode
->
i_mode
))
kobject_put
(
d
->
d_fsdata
);
simple_unlink
(
dentry
->
d_inode
,
d
);
simple_unlink
(
dentry
->
d_inode
,
d
);
dput
(
d
);
dput
(
d
);
pr_debug
(
" done
\n
"
);
pr_debug
(
" done
\n
"
);
...
@@ -165,6 +173,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
...
@@ -165,6 +173,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
if
(
!
kobj
->
parent
)
if
(
!
kobj
->
parent
)
return
-
EINVAL
;
return
-
EINVAL
;
down_write
(
&
sysfs_rename_sem
);
parent
=
kobj
->
parent
->
dentry
;
parent
=
kobj
->
parent
->
dentry
;
down
(
&
parent
->
d_inode
->
i_sem
);
down
(
&
parent
->
d_inode
->
i_sem
);
...
@@ -179,6 +188,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
...
@@ -179,6 +188,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
dput
(
new_dentry
);
dput
(
new_dentry
);
}
}
up
(
&
parent
->
d_inode
->
i_sem
);
up
(
&
parent
->
d_inode
->
i_sem
);
up_write
(
&
sysfs_rename_sem
);
return
error
;
return
error
;
}
}
...
...
fs/sysfs/inode.c
View file @
5bb8ea44
...
@@ -96,7 +96,12 @@ void sysfs_hash_and_remove(struct dentry * dir, const char * name)
...
@@ -96,7 +96,12 @@ void sysfs_hash_and_remove(struct dentry * dir, const char * name)
pr_debug
(
"sysfs: Removing %s (%d)
\n
"
,
victim
->
d_name
.
name
,
pr_debug
(
"sysfs: Removing %s (%d)
\n
"
,
victim
->
d_name
.
name
,
atomic_read
(
&
victim
->
d_count
));
atomic_read
(
&
victim
->
d_count
));
d_delete
(
victim
);
d_drop
(
victim
);
/* release the target kobject in case of
* a symlink
*/
if
(
S_ISLNK
(
victim
->
d_inode
->
i_mode
))
kobject_put
(
victim
->
d_fsdata
);
simple_unlink
(
dir
->
d_inode
,
victim
);
simple_unlink
(
dir
->
d_inode
,
victim
);
}
}
/*
/*
...
...
fs/sysfs/symlink.c
View file @
5bb8ea44
...
@@ -8,27 +8,17 @@
...
@@ -8,27 +8,17 @@
#include "sysfs.h"
#include "sysfs.h"
static
struct
inode_operations
sysfs_symlink_inode_operations
=
{
.
readlink
=
sysfs_readlink
,
.
follow_link
=
sysfs_follow_link
,
};
static
int
init_symlink
(
struct
inode
*
inode
)
static
int
init_symlink
(
struct
inode
*
inode
)
{
{
inode
->
i_op
=
&
page
_symlink_inode_operations
;
inode
->
i_op
=
&
sysfs
_symlink_inode_operations
;
return
0
;
return
0
;
}
}
static
int
sysfs_symlink
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
const
char
*
symname
)
{
int
error
;
error
=
sysfs_create
(
dentry
,
S_IFLNK
|
S_IRWXUGO
,
init_symlink
);
if
(
!
error
)
{
int
l
=
strlen
(
symname
)
+
1
;
error
=
page_symlink
(
dentry
->
d_inode
,
symname
,
l
);
if
(
error
)
iput
(
dentry
->
d_inode
);
}
return
error
;
}
static
int
object_depth
(
struct
kobject
*
kobj
)
static
int
object_depth
(
struct
kobject
*
kobj
)
{
{
struct
kobject
*
p
=
kobj
;
struct
kobject
*
p
=
kobj
;
...
@@ -74,37 +64,20 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * nam
...
@@ -74,37 +64,20 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * nam
struct
dentry
*
dentry
=
kobj
->
dentry
;
struct
dentry
*
dentry
=
kobj
->
dentry
;
struct
dentry
*
d
;
struct
dentry
*
d
;
int
error
=
0
;
int
error
=
0
;
int
size
;
int
depth
;
char
*
path
;
char
*
s
;
depth
=
object_depth
(
kobj
);
size
=
object_path_length
(
target
)
+
depth
*
3
-
1
;
if
(
size
>
PATH_MAX
)
return
-
ENAMETOOLONG
;
pr_debug
(
"%s: depth = %d, size = %d
\n
"
,
__FUNCTION__
,
depth
,
size
);
path
=
kmalloc
(
size
,
GFP_KERNEL
);
if
(
!
path
)
return
-
ENOMEM
;
memset
(
path
,
0
,
size
);
for
(
s
=
path
;
depth
--
;
s
+=
3
)
strcpy
(
s
,
"../"
);
fill_object_path
(
target
,
path
,
size
);
pr_debug
(
"%s: path = '%s'
\n
"
,
__FUNCTION__
,
path
);
down
(
&
dentry
->
d_inode
->
i_sem
);
down
(
&
dentry
->
d_inode
->
i_sem
);
d
=
sysfs_get_dentry
(
dentry
,
name
);
d
=
sysfs_get_dentry
(
dentry
,
name
);
if
(
!
IS_ERR
(
d
))
if
(
!
IS_ERR
(
d
))
{
error
=
sysfs_symlink
(
dentry
->
d_inode
,
d
,
path
);
error
=
sysfs_create
(
d
,
S_IFLNK
|
S_IRWXUGO
,
init_symlink
);
else
if
(
!
error
)
error
=
PTR_ERR
(
d
);
/*
* associate the link dentry with the target kobject
*/
d
->
d_fsdata
=
kobject_get
(
target
);
dput
(
d
);
dput
(
d
);
}
else
error
=
PTR_ERR
(
d
);
up
(
&
dentry
->
d_inode
->
i_sem
);
up
(
&
dentry
->
d_inode
->
i_sem
);
kfree
(
path
);
return
error
;
return
error
;
}
}
...
@@ -120,6 +93,86 @@ void sysfs_remove_link(struct kobject * kobj, char * name)
...
@@ -120,6 +93,86 @@ void sysfs_remove_link(struct kobject * kobj, char * name)
sysfs_hash_and_remove
(
kobj
->
dentry
,
name
);
sysfs_hash_and_remove
(
kobj
->
dentry
,
name
);
}
}
static
int
sysfs_get_target_path
(
struct
kobject
*
kobj
,
struct
kobject
*
target
,
char
*
path
)
{
char
*
s
;
int
depth
,
size
;
depth
=
object_depth
(
kobj
);
size
=
object_path_length
(
target
)
+
depth
*
3
-
1
;
if
(
size
>
PATH_MAX
)
return
-
ENAMETOOLONG
;
pr_debug
(
"%s: depth = %d, size = %d
\n
"
,
__FUNCTION__
,
depth
,
size
);
for
(
s
=
path
;
depth
--
;
s
+=
3
)
strcpy
(
s
,
"../"
);
fill_object_path
(
target
,
path
,
size
);
pr_debug
(
"%s: path = '%s'
\n
"
,
__FUNCTION__
,
path
);
return
0
;
}
static
int
sysfs_getlink
(
struct
dentry
*
dentry
,
char
*
path
)
{
struct
kobject
*
kobj
,
*
target_kobj
;
int
error
=
0
;
kobj
=
sysfs_get_kobject
(
dentry
->
d_parent
);
if
(
!
kobj
)
return
-
EINVAL
;
target_kobj
=
sysfs_get_kobject
(
dentry
);
if
(
!
target_kobj
)
{
kobject_put
(
kobj
);
return
-
EINVAL
;
}
down_read
(
&
sysfs_rename_sem
);
error
=
sysfs_get_target_path
(
kobj
,
target_kobj
,
path
);
up_read
(
&
sysfs_rename_sem
);
kobject_put
(
kobj
);
kobject_put
(
target_kobj
);
return
error
;
}
int
sysfs_readlink
(
struct
dentry
*
dentry
,
char
__user
*
buffer
,
int
buflen
)
{
int
error
=
0
;
unsigned
long
page
=
get_zeroed_page
(
GFP_KERNEL
);
if
(
!
page
)
return
-
ENOMEM
;
error
=
sysfs_getlink
(
dentry
,
(
char
*
)
page
);
if
(
!
error
)
error
=
vfs_readlink
(
dentry
,
buffer
,
buflen
,
(
char
*
)
page
);
free_page
(
page
);
return
error
;
}
int
sysfs_follow_link
(
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
{
int
error
=
0
;
unsigned
long
page
=
get_zeroed_page
(
GFP_KERNEL
);
if
(
!
page
)
return
-
ENOMEM
;
error
=
sysfs_getlink
(
dentry
,
(
char
*
)
page
);
if
(
!
error
)
error
=
vfs_follow_link
(
nd
,
(
char
*
)
page
);
free_page
(
page
);
return
error
;
}
EXPORT_SYMBOL
(
sysfs_create_link
);
EXPORT_SYMBOL
(
sysfs_create_link
);
EXPORT_SYMBOL
(
sysfs_remove_link
);
EXPORT_SYMBOL
(
sysfs_remove_link
);
...
...
fs/sysfs/sysfs.h
View file @
5bb8ea44
...
@@ -12,15 +12,18 @@ extern void sysfs_hash_and_remove(struct dentry * dir, const char * name);
...
@@ -12,15 +12,18 @@ extern void sysfs_hash_and_remove(struct dentry * dir, const char * name);
extern
int
sysfs_create_subdir
(
struct
kobject
*
,
const
char
*
,
struct
dentry
**
);
extern
int
sysfs_create_subdir
(
struct
kobject
*
,
const
char
*
,
struct
dentry
**
);
extern
void
sysfs_remove_subdir
(
struct
dentry
*
);
extern
void
sysfs_remove_subdir
(
struct
dentry
*
);
extern
int
sysfs_readlink
(
struct
dentry
*
,
char
__user
*
,
int
);
extern
int
sysfs_follow_link
(
struct
dentry
*
,
struct
nameidata
*
);
extern
struct
rw_semaphore
sysfs_rename_sem
;
static
inline
struct
kobject
*
sysfs_get_kobject
(
struct
dentry
*
dentry
)
static
inline
struct
kobject
*
sysfs_get_kobject
(
struct
dentry
*
dentry
)
{
{
struct
kobject
*
kobj
=
NULL
;
struct
kobject
*
kobj
=
NULL
;
spin_lock
(
&
d
entry
->
d
_lock
);
spin_lock
(
&
d
cache
_lock
);
if
(
!
d_unhashed
(
dentry
))
if
(
!
d_unhashed
(
dentry
))
kobj
=
kobject_get
(
dentry
->
d_fsdata
);
kobj
=
kobject_get
(
dentry
->
d_fsdata
);
spin_unlock
(
&
d
entry
->
d
_lock
);
spin_unlock
(
&
d
cache
_lock
);
return
kobj
;
return
kobj
;
}
}
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