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
f75bdb62
Commit
f75bdb62
authored
Aug 24, 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
32a8ed45
764dfe0b
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
185 additions
and
198 deletions
+185
-198
Documentation/driver-model/bus.txt
Documentation/driver-model/bus.txt
+21
-53
drivers/base/class.c
drivers/base/class.c
+7
-2
drivers/char/tty_io.c
drivers/char/tty_io.c
+16
-6
drivers/scsi/sd.c
drivers/scsi/sd.c
+5
-7
drivers/scsi/sr.c
drivers/scsi/sr.c
+5
-7
drivers/usb/core/config.c
drivers/usb/core/config.c
+4
-3
drivers/usb/core/message.c
drivers/usb/core/message.c
+1
-1
drivers/usb/core/urb.c
drivers/usb/core/urb.c
+2
-2
drivers/usb/core/usb.h
drivers/usb/core/usb.h
+1
-0
drivers/usb/host/ehci-mem.c
drivers/usb/host/ehci-mem.c
+2
-2
drivers/usb/serial/usb-serial.c
drivers/usb/serial/usb-serial.c
+62
-68
include/linux/device.h
include/linux/device.h
+0
-1
include/linux/kobject.h
include/linux/kobject.h
+4
-1
include/linux/kref.h
include/linux/kref.h
+3
-6
lib/Makefile
lib/Makefile
+1
-4
lib/kobject.c
lib/kobject.c
+38
-19
lib/kref.c
lib/kref.c
+13
-16
No files found.
Documentation/driver-model/bus.txt
View file @
f75bdb62
...
...
@@ -5,20 +5,21 @@ Definition
~~~~~~~~~~
struct bus_type {
char * name;
rwlock_t lock;
atomic_t refcount;
char * name;
struct list_head node
;
struct list_head device
s;
struct list_head driver
s;
struct subsystem subsys
;
struct kset driver
s;
struct kset device
s;
struct driver_dir_entry dir
;
struct driver_dir_entry device_dir
;
struct driver_dir_entry driver_dir
;
struct bus_attribute * bus_attrs
;
struct device_attribute * dev_attrs
;
struct driver_attribute * drv_attrs
;
int (*match) (struct device * dev, struct device_driver * drv);
struct device (*add) (struct device * parent, char * bus_id);
int (*match)(struct device * dev, struct device_driver * drv);
int (*hotplug) (struct device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
int (*suspend)(struct device * dev, u32 state);
int (*resume)(struct device * dev);
};
int bus_register(struct bus_type * bus);
...
...
@@ -47,7 +48,7 @@ Registration
When a bus driver is initialized, it calls bus_register. This
initializes the rest of the fields in the bus object and inserts it
into a global list of bus types. Once the bus object is registered,
the fields in it
(e.g. the rwlock_t)
are usable by the bus driver.
the fields in it are usable by the bus driver.
Callbacks
...
...
@@ -71,40 +72,6 @@ When a driver is registered with the bus, the bus's list of devices is
iterated over, and the match callback is called for each device that
does not have a driver associated with it.
add(): Adding a child device
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The add callback is available to notify the bus about a child device
at a particular location.
The parent parameter is the parent device of the child to be added. If
parent == NULL, the bus should add the device as a child of a default
parent device or as a child of the root. This policy decision is up to
the bus driver.
The format of the bus_id field should be consistent with the format of
the bus_id field of the rest of the devices on the bus. This requires
the caller to know the format.
On return, the bus driver should return a pointer to the device that
was created. If the device was not created, the bus driver should
return an appropriate error code. Refer to include/linux/err.h for
helper functions to encode errors. Some sample code:
struct device * pci_bus_add(struct device * parent, char * bus_id)
{
...
/* the device already exists */
return ERR_PTR(-EEXIST);
...
}
The caller can check the return value using IS_ERR():
struct device * newdev = pci_bus_type.add(parent,bus_id);
if (IS_ERR(newdev)) {
...
}
Device and Driver Lists
...
...
@@ -118,10 +85,11 @@ necessary.
The LDM core provides helper functions for iterating over each list.
int bus_for_each_dev(struct bus_type * bus, void * data,
int (*callback)(struct device * dev, void * data));
int bus_for_each_drv(struct bus_type * bus, void * data,
int (*callback)(struct device_driver * drv, void * data));
int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data,
int (*fn)(struct device *, void *));
int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
void * data, int (*fn)(struct device_driver *, void *));
These helpers iterate over the respective list, and call the callback
for each device or driver in the list. All list accesses are
...
...
@@ -168,9 +136,9 @@ hierarchy:
Exporting Attributes
~~~~~~~~~~~~~~~~~~~~
struct bus_attribute {
struct attribute
attr;
ssize_t (*show)(struct bus_type *, char * buf, size_t count, loff_t of
f);
ssize_t (*store)(struct bus_type *, const char * buf, size_t count, loff_t off
);
struct attribute
attr;
ssize_t (*show)(struct bus_type *, char * bu
f);
ssize_t (*store)(struct bus_type *, const char * buf, size_t count
);
};
Bus drivers can export attributes using the BUS_ATTR macro that works
...
...
drivers/base/class.c
View file @
f75bdb62
...
...
@@ -349,14 +349,19 @@ void class_device_initialize(struct class_device *class_dev)
int
class_device_add
(
struct
class_device
*
class_dev
)
{
struct
class
*
parent
;
struct
class
*
parent
=
NULL
;
struct
class_interface
*
class_intf
;
int
error
;
class_dev
=
class_device_get
(
class_dev
);
if
(
!
class_dev
||
!
strlen
(
class_dev
->
class_id
)
)
if
(
!
class_dev
)
return
-
EINVAL
;
if
(
!
strlen
(
class_dev
->
class_id
))
{
error
=
-
EINVAL
;
goto
register_done
;
}
parent
=
class_get
(
class_dev
->
class
);
pr_debug
(
"CLASS: registering class device: ID = '%s'
\n
"
,
...
...
drivers/char/tty_io.c
View file @
f75bdb62
...
...
@@ -763,6 +763,17 @@ ssize_t redirected_tty_write(struct file * file, const char __user * buf, size_t
return
tty_write
(
file
,
buf
,
count
,
ppos
);
}
static
char
ptychar
[]
=
"pqrstuvwxyzabcde"
;
static
inline
void
pty_line_name
(
struct
tty_driver
*
driver
,
int
index
,
char
*
p
)
{
int
i
=
index
+
driver
->
name_base
;
/* ->name is initialized to "ttyp", but "tty" is expected */
sprintf
(
p
,
"%s%c%x"
,
driver
->
subtype
==
PTY_TYPE_SLAVE
?
"tty"
:
driver
->
name
,
ptychar
[
i
>>
4
&
0xf
],
i
&
0xf
);
}
static
inline
void
tty_line_name
(
struct
tty_driver
*
driver
,
int
index
,
char
*
p
)
{
sprintf
(
p
,
"%s%d"
,
driver
->
name
,
index
+
driver
->
name_base
);
...
...
@@ -2175,6 +2186,7 @@ static struct class_simple *tty_class;
void
tty_register_device
(
struct
tty_driver
*
driver
,
unsigned
index
,
struct
device
*
device
)
{
char
name
[
64
];
dev_t
dev
=
MKDEV
(
driver
->
major
,
driver
->
minor_start
)
+
index
;
if
(
index
>=
driver
->
num
)
{
...
...
@@ -2186,13 +2198,11 @@ void tty_register_device(struct tty_driver *driver, unsigned index,
devfs_mk_cdev
(
dev
,
S_IFCHR
|
S_IRUSR
|
S_IWUSR
,
"%s%d"
,
driver
->
devfs_name
,
index
+
driver
->
name_base
);
/* we don't care about the ptys */
/* how nice to hide this behind some crappy interface.. */
if
(
driver
->
type
!=
TTY_DRIVER_TYPE_PTY
)
{
char
name
[
64
];
if
(
driver
->
type
==
TTY_DRIVER_TYPE_PTY
)
pty_line_name
(
driver
,
index
,
name
);
else
tty_line_name
(
driver
,
index
,
name
);
class_simple_device_add
(
tty_class
,
dev
,
device
,
name
);
}
class_simple_device_add
(
tty_class
,
dev
,
device
,
name
);
}
/**
...
...
drivers/scsi/sd.c
View file @
f75bdb62
...
...
@@ -182,16 +182,14 @@ static struct scsi_disk *scsi_disk_get(struct gendisk *disk)
if
(
disk
->
private_data
==
NULL
)
goto
out
;
sdkp
=
scsi_disk
(
disk
);
if
(
!
kref_get
(
&
sdkp
->
kref
))
goto
out_sdkp
;
kref_get
(
&
sdkp
->
kref
);
if
(
scsi_device_get
(
sdkp
->
device
))
goto
out_put
;
up
(
&
sd_ref_sem
);
return
sdkp
;
out_put:
kref_put
(
&
sdkp
->
kref
);
out_sdkp:
kref_put
(
&
sdkp
->
kref
,
scsi_disk_release
);
sdkp
=
NULL
;
out:
up
(
&
sd_ref_sem
);
...
...
@@ -202,7 +200,7 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
{
down
(
&
sd_ref_sem
);
scsi_device_put
(
sdkp
->
device
);
kref_put
(
&
sdkp
->
kref
);
kref_put
(
&
sdkp
->
kref
,
scsi_disk_release
);
up
(
&
sd_ref_sem
);
}
...
...
@@ -1420,7 +1418,7 @@ static int sd_probe(struct device *dev)
goto
out
;
memset
(
sdkp
,
0
,
sizeof
(
*
sdkp
));
kref_init
(
&
sdkp
->
kref
,
scsi_disk_release
);
kref_init
(
&
sdkp
->
kref
);
/* Note: We can accomodate 64 partitions, but the genhd code
* assumes partitions allocate consecutive minors, which they don't.
...
...
@@ -1522,7 +1520,7 @@ static int sd_remove(struct device *dev)
del_gendisk
(
sdkp
->
disk
);
sd_shutdown
(
dev
);
down
(
&
sd_ref_sem
);
kref_put
(
&
sdkp
->
kref
);
kref_put
(
&
sdkp
->
kref
,
scsi_disk_release
);
up
(
&
sd_ref_sem
);
return
0
;
...
...
drivers/scsi/sr.c
View file @
f75bdb62
...
...
@@ -140,15 +140,13 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
if
(
disk
->
private_data
==
NULL
)
goto
out
;
cd
=
scsi_cd
(
disk
);
if
(
!
kref_get
(
&
cd
->
kref
))
goto
out_null
;
kref_get
(
&
cd
->
kref
);
if
(
scsi_device_get
(
cd
->
device
))
goto
out_put
;
goto
out
;
out_put:
kref_put
(
&
cd
->
kref
);
out_null:
kref_put
(
&
cd
->
kref
,
sr_kref_release
);
cd
=
NULL
;
out:
up
(
&
sr_ref_sem
);
...
...
@@ -159,7 +157,7 @@ static inline void scsi_cd_put(struct scsi_cd *cd)
{
down
(
&
sr_ref_sem
);
scsi_device_put
(
cd
->
device
);
kref_put
(
&
cd
->
kref
);
kref_put
(
&
cd
->
kref
,
sr_kref_release
);
up
(
&
sr_ref_sem
);
}
...
...
@@ -576,7 +574,7 @@ static int sr_probe(struct device *dev)
goto
fail
;
memset
(
cd
,
0
,
sizeof
(
*
cd
));
kref_init
(
&
cd
->
kref
,
sr_kref_release
);
kref_init
(
&
cd
->
kref
);
disk
=
alloc_disk
(
1
);
if
(
!
disk
)
...
...
@@ -937,7 +935,7 @@ static int sr_remove(struct device *dev)
del_gendisk
(
cd
->
disk
);
down
(
&
sr_ref_sem
);
kref_put
(
&
cd
->
kref
);
kref_put
(
&
cd
->
kref
,
sr_kref_release
);
up
(
&
sr_ref_sem
);
return
0
;
...
...
drivers/usb/core/config.c
View file @
f75bdb62
...
...
@@ -106,7 +106,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
return
buffer
-
buffer0
+
i
;
}
static
void
usb_release_interface_cache
(
struct
kref
*
ref
)
void
usb_release_interface_cache
(
struct
kref
*
ref
)
{
struct
usb_interface_cache
*
intfc
=
ref_to_usb_interface_cache
(
ref
);
int
j
;
...
...
@@ -356,7 +356,7 @@ int usb_parse_configuration(struct device *ddev, int cfgidx,
if
(
!
intfc
)
return
-
ENOMEM
;
memset
(
intfc
,
0
,
len
);
kref_init
(
&
intfc
->
ref
,
usb_release_interface_cache
);
kref_init
(
&
intfc
->
ref
);
}
/* Skip over any Class Specific or Vendor Specific descriptors;
...
...
@@ -422,7 +422,8 @@ void usb_destroy_configuration(struct usb_device *dev)
for
(
i
=
0
;
i
<
cf
->
desc
.
bNumInterfaces
;
i
++
)
{
if
(
cf
->
intf_cache
[
i
])
kref_put
(
&
cf
->
intf_cache
[
i
]
->
ref
);
kref_put
(
&
cf
->
intf_cache
[
i
]
->
ref
,
usb_release_interface_cache
);
}
}
kfree
(
dev
->
config
);
...
...
drivers/usb/core/message.c
View file @
f75bdb62
...
...
@@ -1196,7 +1196,7 @@ static void release_interface(struct device *dev)
struct
usb_interface_cache
*
intfc
=
altsetting_to_usb_interface_cache
(
intf
->
altsetting
);
kref_put
(
&
intfc
->
ref
);
kref_put
(
&
intfc
->
ref
,
usb_release_interface_cache
);
kfree
(
intf
);
}
...
...
drivers/usb/core/urb.c
View file @
f75bdb62
...
...
@@ -39,7 +39,7 @@ void usb_init_urb(struct urb *urb)
{
if
(
urb
)
{
memset
(
urb
,
0
,
sizeof
(
*
urb
));
kref_init
(
&
urb
->
kref
,
urb_destroy
);
kref_init
(
&
urb
->
kref
);
spin_lock_init
(
&
urb
->
lock
);
}
}
...
...
@@ -88,7 +88,7 @@ struct urb *usb_alloc_urb(int iso_packets, int mem_flags)
void
usb_free_urb
(
struct
urb
*
urb
)
{
if
(
urb
)
kref_put
(
&
urb
->
kref
);
kref_put
(
&
urb
->
kref
,
urb_destroy
);
}
/**
...
...
drivers/usb/core/usb.h
View file @
f75bdb62
...
...
@@ -10,6 +10,7 @@ extern int usb_unbind_interface (struct device *dev);
extern
void
usb_disable_endpoint
(
struct
usb_device
*
dev
,
unsigned
int
epaddr
);
extern
void
usb_disable_interface
(
struct
usb_device
*
dev
,
struct
usb_interface
*
intf
);
extern
void
usb_release_interface_cache
(
struct
kref
*
ref
);
extern
void
usb_disable_device
(
struct
usb_device
*
dev
,
int
skip_ep0
);
extern
void
usb_enable_endpoint
(
struct
usb_device
*
dev
,
...
...
drivers/usb/host/ehci-mem.c
View file @
f75bdb62
...
...
@@ -114,7 +114,7 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
return
qh
;
memset
(
qh
,
0
,
sizeof
*
qh
);
kref_init
(
&
qh
->
kref
,
qh_destroy
);
kref_init
(
&
qh
->
kref
);
qh
->
ehci
=
ehci
;
qh
->
qh_dma
=
dma
;
// INIT_LIST_HEAD (&qh->qh_list);
...
...
@@ -139,7 +139,7 @@ static inline struct ehci_qh *qh_get (struct ehci_qh *qh)
static
inline
void
qh_put
(
struct
ehci_qh
*
qh
)
{
kref_put
(
&
qh
->
kref
);
kref_put
(
&
qh
->
kref
,
qh_destroy
);
}
/*-------------------------------------------------------------------------*/
...
...
drivers/usb/serial/usb-serial.c
View file @
f75bdb62
...
...
@@ -421,6 +421,63 @@ static void return_serial (struct usb_serial *serial)
return
;
}
static
void
destroy_serial
(
struct
kref
*
kref
)
{
struct
usb_serial
*
serial
;
struct
usb_serial_port
*
port
;
int
i
;
serial
=
to_usb_serial
(
kref
);
dbg
(
"%s - %s"
,
__FUNCTION__
,
serial
->
type
->
name
);
serial
->
type
->
shutdown
(
serial
);
/* return the minor range that this device had */
return_serial
(
serial
);
for
(
i
=
0
;
i
<
serial
->
num_ports
;
++
i
)
serial
->
port
[
i
]
->
open_count
=
0
;
/* the ports are cleaned up and released in port_release() */
for
(
i
=
0
;
i
<
serial
->
num_ports
;
++
i
)
if
(
serial
->
port
[
i
]
->
dev
.
parent
!=
NULL
)
{
device_unregister
(
&
serial
->
port
[
i
]
->
dev
);
serial
->
port
[
i
]
=
NULL
;
}
/* If this is a "fake" port, we have to clean it up here, as it will
* not get cleaned up in port_release() as it was never registered with
* the driver core */
if
(
serial
->
num_ports
<
serial
->
num_port_pointers
)
{
for
(
i
=
serial
->
num_ports
;
i
<
serial
->
num_port_pointers
;
++
i
)
{
port
=
serial
->
port
[
i
];
if
(
!
port
)
continue
;
if
(
port
->
read_urb
)
{
usb_unlink_urb
(
port
->
read_urb
);
usb_free_urb
(
port
->
read_urb
);
}
if
(
port
->
write_urb
)
{
usb_unlink_urb
(
port
->
write_urb
);
usb_free_urb
(
port
->
write_urb
);
}
if
(
port
->
interrupt_in_urb
)
{
usb_unlink_urb
(
port
->
interrupt_in_urb
);
usb_free_urb
(
port
->
interrupt_in_urb
);
}
kfree
(
port
->
bulk_in_buffer
);
kfree
(
port
->
bulk_out_buffer
);
kfree
(
port
->
interrupt_in_buffer
);
}
}
usb_put_dev
(
serial
->
dev
);
/* free up any memory that we allocated */
kfree
(
serial
);
}
/*****************************************************************************
* Driver tty interface functions
*****************************************************************************/
...
...
@@ -465,7 +522,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
if
(
retval
)
{
port
->
open_count
=
0
;
module_put
(
serial
->
type
->
owner
);
kref_put
(
&
serial
->
kref
);
kref_put
(
&
serial
->
kref
,
destroy_serial
);
}
}
bailout:
...
...
@@ -496,7 +553,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
}
module_put
(
port
->
serial
->
type
->
owner
);
kref_put
(
&
port
->
serial
->
kref
);
kref_put
(
&
port
->
serial
->
kref
,
destroy_serial
);
}
static
int
serial_write
(
struct
tty_struct
*
tty
,
int
from_user
,
const
unsigned
char
*
buf
,
int
count
)
...
...
@@ -654,13 +711,6 @@ static void serial_break (struct tty_struct *tty, int break_state)
;
}
static
void
serial_shutdown
(
struct
usb_serial
*
serial
)
{
dbg
(
"%s"
,
__FUNCTION__
);
serial
->
type
->
shutdown
(
serial
);
}
static
int
serial_read_proc
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
struct
usb_serial
*
serial
;
...
...
@@ -694,7 +744,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
begin
+=
length
;
length
=
0
;
}
kref_put
(
&
serial
->
kref
);
kref_put
(
&
serial
->
kref
,
destroy_serial
);
}
*
eof
=
1
;
done:
...
...
@@ -763,62 +813,6 @@ void usb_serial_port_softint(void *private)
wake_up_interruptible
(
&
tty
->
write_wait
);
}
static
void
destroy_serial
(
struct
kref
*
kref
)
{
struct
usb_serial
*
serial
;
struct
usb_serial_port
*
port
;
int
i
;
serial
=
to_usb_serial
(
kref
);
dbg
(
"%s - %s"
,
__FUNCTION__
,
serial
->
type
->
name
);
serial_shutdown
(
serial
);
/* return the minor range that this device had */
return_serial
(
serial
);
for
(
i
=
0
;
i
<
serial
->
num_ports
;
++
i
)
serial
->
port
[
i
]
->
open_count
=
0
;
/* the ports are cleaned up and released in port_release() */
for
(
i
=
0
;
i
<
serial
->
num_ports
;
++
i
)
if
(
serial
->
port
[
i
]
->
dev
.
parent
!=
NULL
)
{
device_unregister
(
&
serial
->
port
[
i
]
->
dev
);
serial
->
port
[
i
]
=
NULL
;
}
/* If this is a "fake" port, we have to clean it up here, as it will
* not get cleaned up in port_release() as it was never registered with
* the driver core */
if
(
serial
->
num_ports
<
serial
->
num_port_pointers
)
{
for
(
i
=
serial
->
num_ports
;
i
<
serial
->
num_port_pointers
;
++
i
)
{
port
=
serial
->
port
[
i
];
if
(
!
port
)
continue
;
if
(
port
->
read_urb
)
{
usb_unlink_urb
(
port
->
read_urb
);
usb_free_urb
(
port
->
read_urb
);
}
if
(
port
->
write_urb
)
{
usb_unlink_urb
(
port
->
write_urb
);
usb_free_urb
(
port
->
write_urb
);
}
if
(
port
->
interrupt_in_urb
)
{
usb_unlink_urb
(
port
->
interrupt_in_urb
);
usb_free_urb
(
port
->
interrupt_in_urb
);
}
kfree
(
port
->
bulk_in_buffer
);
kfree
(
port
->
bulk_out_buffer
);
kfree
(
port
->
interrupt_in_buffer
);
}
}
usb_put_dev
(
serial
->
dev
);
/* free up any memory that we allocated */
kfree
(
serial
);
}
static
void
port_release
(
struct
device
*
dev
)
{
struct
usb_serial_port
*
port
=
to_usb_serial_port
(
dev
);
...
...
@@ -859,7 +853,7 @@ static struct usb_serial * create_serial (struct usb_device *dev,
serial
->
interface
=
interface
;
serial
->
vendor
=
dev
->
descriptor
.
idVendor
;
serial
->
product
=
dev
->
descriptor
.
idProduct
;
kref_init
(
&
serial
->
kref
,
destroy_serial
);
kref_init
(
&
serial
->
kref
);
return
serial
;
}
...
...
@@ -1209,7 +1203,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
if
(
serial
)
{
/* let the last holder of this object
* cause it to be cleaned up */
kref_put
(
&
serial
->
kref
);
kref_put
(
&
serial
->
kref
,
destroy_serial
);
}
dev_info
(
dev
,
"device disconnected
\n
"
);
}
...
...
include/linux/device.h
View file @
f75bdb62
...
...
@@ -59,7 +59,6 @@ struct bus_type {
struct
driver_attribute
*
drv_attrs
;
int
(
*
match
)(
struct
device
*
dev
,
struct
device_driver
*
drv
);
struct
device
*
(
*
add
)
(
struct
device
*
parent
,
char
*
bus_id
);
int
(
*
hotplug
)
(
struct
device
*
dev
,
char
**
envp
,
int
num_envp
,
char
*
buffer
,
int
buffer_size
);
int
(
*
suspend
)(
struct
device
*
dev
,
u32
state
);
...
...
include/linux/kobject.h
View file @
f75bdb62
...
...
@@ -19,6 +19,7 @@
#include <linux/list.h>
#include <linux/sysfs.h>
#include <linux/rwsem.h>
#include <linux/kref.h>
#include <asm/atomic.h>
#define KOBJ_NAME_LEN 20
...
...
@@ -26,7 +27,7 @@
struct
kobject
{
char
*
k_name
;
char
name
[
KOBJ_NAME_LEN
];
atomic_t
refcount
;
struct
kref
kref
;
struct
list_head
entry
;
struct
kobject
*
parent
;
struct
kset
*
kset
;
...
...
@@ -58,6 +59,8 @@ extern void kobject_put(struct kobject *);
extern
void
kobject_hotplug
(
const
char
*
action
,
struct
kobject
*
);
extern
char
*
kobject_get_path
(
struct
kset
*
,
struct
kobject
*
,
int
);
struct
kobj_type
{
void
(
*
release
)(
struct
kobject
*
);
struct
sysfs_ops
*
sysfs_ops
;
...
...
include/linux/kref.h
View file @
f75bdb62
...
...
@@ -18,15 +18,12 @@
#include <linux/types.h>
#include <asm/atomic.h>
struct
kref
{
atomic_t
refcount
;
void
(
*
release
)(
struct
kref
*
kref
);
};
void
kref_init
(
struct
kref
*
kref
,
void
(
*
release
)(
struct
kref
*
));
struct
kref
*
kref_get
(
struct
kref
*
kref
);
void
kref_put
(
struct
kref
*
kref
);
void
kref_init
(
struct
kref
*
kref
);
void
kref_get
(
struct
kref
*
kref
);
void
kref_put
(
struct
kref
*
kref
,
void
(
*
release
)
(
struct
kref
*
kref
));
#endif
/* _KREF_H_ */
lib/Makefile
View file @
f75bdb62
...
...
@@ -5,12 +5,9 @@
lib-y
:=
errno.o ctype.o string.o vsprintf.o cmdline.o
\
bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o
\
kobject.o idr.o div64.o parser.o int_sqrt.o
\
kobject.o
kref.o
idr.o div64.o parser.o int_sqrt.o
\
bitmap.o extable.o
# hack for now till some static code uses krefs, then it can move up above...
obj-y
+=
kref.o
lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK)
+=
rwsem-spinlock.o
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM)
+=
rwsem.o
...
...
lib/kobject.c
View file @
f75bdb62
...
...
@@ -58,14 +58,11 @@ static int create_dir(struct kobject * kobj)
return
error
;
}
static
inline
struct
kobject
*
to_kobj
(
struct
list_head
*
entry
)
{
return
container_of
(
entry
,
struct
kobject
,
entry
);
}
#ifdef CONFIG_HOTPLUG
static
int
get_kobj_path_length
(
struct
kset
*
kset
,
struct
kobject
*
kobj
)
{
int
length
=
1
;
...
...
@@ -98,6 +95,31 @@ static void fill_kobj_path(struct kset *kset, struct kobject *kobj, char *path,
pr_debug
(
"%s: path = '%s'
\n
"
,
__FUNCTION__
,
path
);
}
/**
* kobject_get_path - generate and return the path associated with a given kobj
* and kset pair. The result must be freed by the caller with kfree().
*
* @kset: kset in question, with which to build the path
* @kobj: kobject in question, with which to build the path
* @gfp_mask: the allocation type used to allocate the path
*/
char
*
kobject_get_path
(
struct
kset
*
kset
,
struct
kobject
*
kobj
,
int
gfp_mask
)
{
char
*
path
;
int
len
;
len
=
get_kobj_path_length
(
kset
,
kobj
);
path
=
kmalloc
(
len
,
gfp_mask
);
if
(
!
path
)
return
NULL
;
memset
(
path
,
0x00
,
len
);
fill_kobj_path
(
kset
,
kobj
,
path
,
len
);
return
path
;
}
#ifdef CONFIG_HOTPLUG
#define BUFFER_SIZE 1024
/* should be enough memory for the env */
#define NUM_ENVP 32
/* number of env pointers */
static
unsigned
long
sequence_num
;
...
...
@@ -112,7 +134,6 @@ static void kset_hotplug(const char *action, struct kset *kset,
char
*
scratch
;
int
i
=
0
;
int
retval
;
int
kobj_path_length
;
char
*
kobj_path
=
NULL
;
char
*
name
=
NULL
;
unsigned
long
seq
;
...
...
@@ -163,12 +184,9 @@ static void kset_hotplug(const char *action, struct kset *kset,
envp
[
i
++
]
=
scratch
;
scratch
+=
sprintf
(
scratch
,
"SEQNUM=%ld"
,
seq
)
+
1
;
kobj_path_length
=
get_kobj_path_length
(
kset
,
kobj
);
kobj_path
=
kmalloc
(
kobj_path_length
,
GFP_KERNEL
);
kobj_path
=
kobject_get_path
(
kset
,
kobj
,
GFP_KERNEL
);
if
(
!
kobj_path
)
goto
exit
;
memset
(
kobj_path
,
0x00
,
kobj_path_length
);
fill_kobj_path
(
kset
,
kobj
,
kobj_path
,
kobj_path_length
);
envp
[
i
++
]
=
scratch
;
scratch
+=
sprintf
(
scratch
,
"DEVPATH=%s"
,
kobj_path
)
+
1
;
...
...
@@ -225,10 +243,9 @@ void kobject_hotplug(const char *action, struct kobject *kobj)
* kobject_init - initialize object.
* @kobj: object in question.
*/
void
kobject_init
(
struct
kobject
*
kobj
)
{
atomic_set
(
&
kobj
->
refcount
,
1
);
kref_init
(
&
kobj
->
kref
);
INIT_LIST_HEAD
(
&
kobj
->
entry
);
kobj
->
kset
=
kset_get
(
kobj
->
kset
);
}
...
...
@@ -325,7 +342,7 @@ int kobject_register(struct kobject * kobj)
* @kobj: object.
* @name: name.
*
* If strlen(name)
<
KOBJ_NAME_LEN, then use a dynamically allocated
* If strlen(name)
>=
KOBJ_NAME_LEN, then use a dynamically allocated
* string that @kobj->k_name points to. Otherwise, use the static
* @kobj->name array.
*/
...
...
@@ -429,10 +446,8 @@ void kobject_unregister(struct kobject * kobj)
struct
kobject
*
kobject_get
(
struct
kobject
*
kobj
)
{
if
(
kobj
)
{
WARN_ON
(
!
atomic_read
(
&
kobj
->
refcount
));
atomic_inc
(
&
kobj
->
refcount
);
}
if
(
kobj
)
kref_get
(
&
kobj
->
kref
);
return
kobj
;
}
...
...
@@ -459,17 +474,21 @@ void kobject_cleanup(struct kobject * kobj)
kobject_put
(
parent
);
}
static
void
kobject_release
(
struct
kref
*
kref
)
{
kobject_cleanup
(
container_of
(
kref
,
struct
kobject
,
kref
));
}
/**
* kobject_put - decrement refcount for object.
* @kobj: object.
*
* Decrement the refcount, and if 0, call kobject_cleanup().
*/
void
kobject_put
(
struct
kobject
*
kobj
)
{
if
(
atomic_dec_and_test
(
&
kobj
->
refcount
)
)
k
object_cleanup
(
kobj
);
if
(
kobj
)
k
ref_put
(
&
kobj
->
kref
,
kobject_release
);
}
...
...
@@ -626,7 +645,7 @@ void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
}
}
EXPORT_SYMBOL
(
kobject_get_path
);
EXPORT_SYMBOL
(
kobject_init
);
EXPORT_SYMBOL
(
kobject_register
);
EXPORT_SYMBOL
(
kobject_unregister
);
...
...
lib/kref.c
View file @
f75bdb62
...
...
@@ -11,48 +11,45 @@
*
*/
/* #define DEBUG */
#include <linux/kref.h>
#include <linux/module.h>
/**
* kref_init - initialize object.
* @kref: object in question.
* @release: pointer to a function that will clean up the object
* when the last reference to the object is released.
* This pointer is required.
*/
void
kref_init
(
struct
kref
*
kref
,
void
(
*
release
)(
struct
kref
*
kref
)
)
void
kref_init
(
struct
kref
*
kref
)
{
WARN_ON
(
release
==
NULL
);
atomic_set
(
&
kref
->
refcount
,
1
);
kref
->
release
=
release
;
}
/**
* kref_get - increment refcount for object.
* @kref: object.
*/
struct
kref
*
kref_get
(
struct
kref
*
kref
)
void
kref_get
(
struct
kref
*
kref
)
{
WARN_ON
(
!
atomic_read
(
&
kref
->
refcount
));
atomic_inc
(
&
kref
->
refcount
);
return
kref
;
}
/**
* kref_put - decrement refcount for object.
* @kref: object.
* @release: pointer to the function that will clean up the object when the
* last reference to the object is released.
* This pointer is required, and it is not acceptable to pass kfree
* in as this function.
*
* Decrement the refcount, and if 0, call
kref->
release().
* Decrement the refcount, and if 0, call release().
*/
void
kref_put
(
struct
kref
*
kref
)
void
kref_put
(
struct
kref
*
kref
,
void
(
*
release
)
(
struct
kref
*
kref
)
)
{
if
(
atomic_dec_and_test
(
&
kref
->
refcount
))
{
pr_debug
(
"kref cleaning up
\n
"
);
kref
->
release
(
kref
);
}
WARN_ON
(
release
==
NULL
);
WARN_ON
(
release
==
(
void
(
*
)(
struct
kref
*
))
kfree
);
if
(
atomic_dec_and_test
(
&
kref
->
refcount
))
release
(
kref
);
}
EXPORT_SYMBOL
(
kref_init
);
...
...
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