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
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
...
@@ -5,20 +5,21 @@ Definition
~~~~~~~~~~
~~~~~~~~~~
struct bus_type {
struct bus_type {
char * name;
char * name;
rwlock_t lock;
atomic_t refcount;
struct list_head node
;
struct subsystem subsys
;
struct list_head device
s;
struct kset driver
s;
struct list_head driver
s;
struct kset device
s;
struct driver_dir_entry dir
;
struct bus_attribute * bus_attrs
;
struct driver_dir_entry device_dir
;
struct device_attribute * dev_attrs
;
struct driver_dir_entry driver_dir
;
struct driver_attribute * drv_attrs
;
int (*match) (struct device * dev, struct device_driver * drv);
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);
int (*resume)(struct device * dev);
};
};
int bus_register(struct bus_type * bus);
int bus_register(struct bus_type * bus);
...
@@ -47,7 +48,7 @@ Registration
...
@@ -47,7 +48,7 @@ Registration
When a bus driver is initialized, it calls bus_register. This
When a bus driver is initialized, it calls bus_register. This
initializes the rest of the fields in the bus object and inserts it
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,
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
Callbacks
...
@@ -71,40 +72,6 @@ When a driver is registered with the bus, the bus's list of devices is
...
@@ -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
iterated over, and the match callback is called for each device that
does not have a driver associated with it.
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
Device and Driver Lists
...
@@ -118,10 +85,11 @@ necessary.
...
@@ -118,10 +85,11 @@ necessary.
The LDM core provides helper functions for iterating over each list.
The LDM core provides helper functions for iterating over each list.
int bus_for_each_dev(struct bus_type * bus, void * data,
int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data,
int (*callback)(struct device * dev, void * data));
int (*fn)(struct device *, void *));
int bus_for_each_drv(struct bus_type * bus, void * data,
int (*callback)(struct device_driver * drv, void * data));
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
These helpers iterate over the respective list, and call the callback
for each device or driver in the list. All list accesses are
for each device or driver in the list. All list accesses are
...
@@ -168,9 +136,9 @@ hierarchy:
...
@@ -168,9 +136,9 @@ hierarchy:
Exporting Attributes
Exporting Attributes
~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~
struct bus_attribute {
struct bus_attribute {
struct attribute
attr;
struct attribute
attr;
ssize_t (*show)(struct bus_type *, char * buf, size_t count, loff_t of
f);
ssize_t (*show)(struct bus_type *, char * bu
f);
ssize_t (*store)(struct bus_type *, const char * buf, size_t count, loff_t off
);
ssize_t (*store)(struct bus_type *, const char * buf, size_t count
);
};
};
Bus drivers can export attributes using the BUS_ATTR macro that works
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)
...
@@ -349,14 +349,19 @@ void class_device_initialize(struct class_device *class_dev)
int
class_device_add
(
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
;
struct
class_interface
*
class_intf
;
int
error
;
int
error
;
class_dev
=
class_device_get
(
class_dev
);
class_dev
=
class_device_get
(
class_dev
);
if
(
!
class_dev
||
!
strlen
(
class_dev
->
class_id
)
)
if
(
!
class_dev
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
!
strlen
(
class_dev
->
class_id
))
{
error
=
-
EINVAL
;
goto
register_done
;
}
parent
=
class_get
(
class_dev
->
class
);
parent
=
class_get
(
class_dev
->
class
);
pr_debug
(
"CLASS: registering class device: ID = '%s'
\n
"
,
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
...
@@ -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
);
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
)
static
inline
void
tty_line_name
(
struct
tty_driver
*
driver
,
int
index
,
char
*
p
)
{
{
sprintf
(
p
,
"%s%d"
,
driver
->
name
,
index
+
driver
->
name_base
);
sprintf
(
p
,
"%s%d"
,
driver
->
name
,
index
+
driver
->
name_base
);
...
@@ -2175,6 +2186,7 @@ static struct class_simple *tty_class;
...
@@ -2175,6 +2186,7 @@ static struct class_simple *tty_class;
void
tty_register_device
(
struct
tty_driver
*
driver
,
unsigned
index
,
void
tty_register_device
(
struct
tty_driver
*
driver
,
unsigned
index
,
struct
device
*
device
)
struct
device
*
device
)
{
{
char
name
[
64
];
dev_t
dev
=
MKDEV
(
driver
->
major
,
driver
->
minor_start
)
+
index
;
dev_t
dev
=
MKDEV
(
driver
->
major
,
driver
->
minor_start
)
+
index
;
if
(
index
>=
driver
->
num
)
{
if
(
index
>=
driver
->
num
)
{
...
@@ -2186,13 +2198,11 @@ void tty_register_device(struct tty_driver *driver, unsigned index,
...
@@ -2186,13 +2198,11 @@ void tty_register_device(struct tty_driver *driver, unsigned index,
devfs_mk_cdev
(
dev
,
S_IFCHR
|
S_IRUSR
|
S_IWUSR
,
devfs_mk_cdev
(
dev
,
S_IFCHR
|
S_IRUSR
|
S_IWUSR
,
"%s%d"
,
driver
->
devfs_name
,
index
+
driver
->
name_base
);
"%s%d"
,
driver
->
devfs_name
,
index
+
driver
->
name_base
);
/* we don't care about the ptys */
if
(
driver
->
type
==
TTY_DRIVER_TYPE_PTY
)
/* how nice to hide this behind some crappy interface.. */
pty_line_name
(
driver
,
index
,
name
);
if
(
driver
->
type
!=
TTY_DRIVER_TYPE_PTY
)
{
else
char
name
[
64
];
tty_line_name
(
driver
,
index
,
name
);
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)
...
@@ -182,16 +182,14 @@ static struct scsi_disk *scsi_disk_get(struct gendisk *disk)
if
(
disk
->
private_data
==
NULL
)
if
(
disk
->
private_data
==
NULL
)
goto
out
;
goto
out
;
sdkp
=
scsi_disk
(
disk
);
sdkp
=
scsi_disk
(
disk
);
if
(
!
kref_get
(
&
sdkp
->
kref
))
kref_get
(
&
sdkp
->
kref
);
goto
out_sdkp
;
if
(
scsi_device_get
(
sdkp
->
device
))
if
(
scsi_device_get
(
sdkp
->
device
))
goto
out_put
;
goto
out_put
;
up
(
&
sd_ref_sem
);
up
(
&
sd_ref_sem
);
return
sdkp
;
return
sdkp
;
out_put:
out_put:
kref_put
(
&
sdkp
->
kref
);
kref_put
(
&
sdkp
->
kref
,
scsi_disk_release
);
out_sdkp:
sdkp
=
NULL
;
sdkp
=
NULL
;
out:
out:
up
(
&
sd_ref_sem
);
up
(
&
sd_ref_sem
);
...
@@ -202,7 +200,7 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
...
@@ -202,7 +200,7 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
{
{
down
(
&
sd_ref_sem
);
down
(
&
sd_ref_sem
);
scsi_device_put
(
sdkp
->
device
);
scsi_device_put
(
sdkp
->
device
);
kref_put
(
&
sdkp
->
kref
);
kref_put
(
&
sdkp
->
kref
,
scsi_disk_release
);
up
(
&
sd_ref_sem
);
up
(
&
sd_ref_sem
);
}
}
...
@@ -1420,7 +1418,7 @@ static int sd_probe(struct device *dev)
...
@@ -1420,7 +1418,7 @@ static int sd_probe(struct device *dev)
goto
out
;
goto
out
;
memset
(
sdkp
,
0
,
sizeof
(
*
sdkp
));
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
/* Note: We can accomodate 64 partitions, but the genhd code
* assumes partitions allocate consecutive minors, which they don't.
* assumes partitions allocate consecutive minors, which they don't.
...
@@ -1522,7 +1520,7 @@ static int sd_remove(struct device *dev)
...
@@ -1522,7 +1520,7 @@ static int sd_remove(struct device *dev)
del_gendisk
(
sdkp
->
disk
);
del_gendisk
(
sdkp
->
disk
);
sd_shutdown
(
dev
);
sd_shutdown
(
dev
);
down
(
&
sd_ref_sem
);
down
(
&
sd_ref_sem
);
kref_put
(
&
sdkp
->
kref
);
kref_put
(
&
sdkp
->
kref
,
scsi_disk_release
);
up
(
&
sd_ref_sem
);
up
(
&
sd_ref_sem
);
return
0
;
return
0
;
...
...
drivers/scsi/sr.c
View file @
f75bdb62
...
@@ -140,15 +140,13 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
...
@@ -140,15 +140,13 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
if
(
disk
->
private_data
==
NULL
)
if
(
disk
->
private_data
==
NULL
)
goto
out
;
goto
out
;
cd
=
scsi_cd
(
disk
);
cd
=
scsi_cd
(
disk
);
if
(
!
kref_get
(
&
cd
->
kref
))
kref_get
(
&
cd
->
kref
);
goto
out_null
;
if
(
scsi_device_get
(
cd
->
device
))
if
(
scsi_device_get
(
cd
->
device
))
goto
out_put
;
goto
out_put
;
goto
out
;
goto
out
;
out_put:
out_put:
kref_put
(
&
cd
->
kref
);
kref_put
(
&
cd
->
kref
,
sr_kref_release
);
out_null:
cd
=
NULL
;
cd
=
NULL
;
out:
out:
up
(
&
sr_ref_sem
);
up
(
&
sr_ref_sem
);
...
@@ -159,7 +157,7 @@ static inline void scsi_cd_put(struct scsi_cd *cd)
...
@@ -159,7 +157,7 @@ static inline void scsi_cd_put(struct scsi_cd *cd)
{
{
down
(
&
sr_ref_sem
);
down
(
&
sr_ref_sem
);
scsi_device_put
(
cd
->
device
);
scsi_device_put
(
cd
->
device
);
kref_put
(
&
cd
->
kref
);
kref_put
(
&
cd
->
kref
,
sr_kref_release
);
up
(
&
sr_ref_sem
);
up
(
&
sr_ref_sem
);
}
}
...
@@ -576,7 +574,7 @@ static int sr_probe(struct device *dev)
...
@@ -576,7 +574,7 @@ static int sr_probe(struct device *dev)
goto
fail
;
goto
fail
;
memset
(
cd
,
0
,
sizeof
(
*
cd
));
memset
(
cd
,
0
,
sizeof
(
*
cd
));
kref_init
(
&
cd
->
kref
,
sr_kref_release
);
kref_init
(
&
cd
->
kref
);
disk
=
alloc_disk
(
1
);
disk
=
alloc_disk
(
1
);
if
(
!
disk
)
if
(
!
disk
)
...
@@ -937,7 +935,7 @@ static int sr_remove(struct device *dev)
...
@@ -937,7 +935,7 @@ static int sr_remove(struct device *dev)
del_gendisk
(
cd
->
disk
);
del_gendisk
(
cd
->
disk
);
down
(
&
sr_ref_sem
);
down
(
&
sr_ref_sem
);
kref_put
(
&
cd
->
kref
);
kref_put
(
&
cd
->
kref
,
sr_kref_release
);
up
(
&
sr_ref_sem
);
up
(
&
sr_ref_sem
);
return
0
;
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,
...
@@ -106,7 +106,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
return
buffer
-
buffer0
+
i
;
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
);
struct
usb_interface_cache
*
intfc
=
ref_to_usb_interface_cache
(
ref
);
int
j
;
int
j
;
...
@@ -356,7 +356,7 @@ int usb_parse_configuration(struct device *ddev, int cfgidx,
...
@@ -356,7 +356,7 @@ int usb_parse_configuration(struct device *ddev, int cfgidx,
if
(
!
intfc
)
if
(
!
intfc
)
return
-
ENOMEM
;
return
-
ENOMEM
;
memset
(
intfc
,
0
,
len
);
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;
/* Skip over any Class Specific or Vendor Specific descriptors;
...
@@ -422,7 +422,8 @@ void usb_destroy_configuration(struct usb_device *dev)
...
@@ -422,7 +422,8 @@ void usb_destroy_configuration(struct usb_device *dev)
for
(
i
=
0
;
i
<
cf
->
desc
.
bNumInterfaces
;
i
++
)
{
for
(
i
=
0
;
i
<
cf
->
desc
.
bNumInterfaces
;
i
++
)
{
if
(
cf
->
intf_cache
[
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
);
kfree
(
dev
->
config
);
...
...
drivers/usb/core/message.c
View file @
f75bdb62
...
@@ -1196,7 +1196,7 @@ static void release_interface(struct device *dev)
...
@@ -1196,7 +1196,7 @@ static void release_interface(struct device *dev)
struct
usb_interface_cache
*
intfc
=
struct
usb_interface_cache
*
intfc
=
altsetting_to_usb_interface_cache
(
intf
->
altsetting
);
altsetting_to_usb_interface_cache
(
intf
->
altsetting
);
kref_put
(
&
intfc
->
ref
);
kref_put
(
&
intfc
->
ref
,
usb_release_interface_cache
);
kfree
(
intf
);
kfree
(
intf
);
}
}
...
...
drivers/usb/core/urb.c
View file @
f75bdb62
...
@@ -39,7 +39,7 @@ void usb_init_urb(struct urb *urb)
...
@@ -39,7 +39,7 @@ void usb_init_urb(struct urb *urb)
{
{
if
(
urb
)
{
if
(
urb
)
{
memset
(
urb
,
0
,
sizeof
(
*
urb
));
memset
(
urb
,
0
,
sizeof
(
*
urb
));
kref_init
(
&
urb
->
kref
,
urb_destroy
);
kref_init
(
&
urb
->
kref
);
spin_lock_init
(
&
urb
->
lock
);
spin_lock_init
(
&
urb
->
lock
);
}
}
}
}
...
@@ -88,7 +88,7 @@ struct urb *usb_alloc_urb(int iso_packets, int mem_flags)
...
@@ -88,7 +88,7 @@ struct urb *usb_alloc_urb(int iso_packets, int mem_flags)
void
usb_free_urb
(
struct
urb
*
urb
)
void
usb_free_urb
(
struct
urb
*
urb
)
{
{
if
(
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);
...
@@ -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_endpoint
(
struct
usb_device
*
dev
,
unsigned
int
epaddr
);
extern
void
usb_disable_interface
(
struct
usb_device
*
dev
,
extern
void
usb_disable_interface
(
struct
usb_device
*
dev
,
struct
usb_interface
*
intf
);
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_disable_device
(
struct
usb_device
*
dev
,
int
skip_ep0
);
extern
void
usb_enable_endpoint
(
struct
usb_device
*
dev
,
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)
...
@@ -114,7 +114,7 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
return
qh
;
return
qh
;
memset
(
qh
,
0
,
sizeof
*
qh
);
memset
(
qh
,
0
,
sizeof
*
qh
);
kref_init
(
&
qh
->
kref
,
qh_destroy
);
kref_init
(
&
qh
->
kref
);
qh
->
ehci
=
ehci
;
qh
->
ehci
=
ehci
;
qh
->
qh_dma
=
dma
;
qh
->
qh_dma
=
dma
;
// INIT_LIST_HEAD (&qh->qh_list);
// INIT_LIST_HEAD (&qh->qh_list);
...
@@ -139,7 +139,7 @@ static inline struct ehci_qh *qh_get (struct ehci_qh *qh)
...
@@ -139,7 +139,7 @@ static inline struct ehci_qh *qh_get (struct ehci_qh *qh)
static
inline
void
qh_put
(
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)
...
@@ -421,6 +421,63 @@ static void return_serial (struct usb_serial *serial)
return
;
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
* Driver tty interface functions
*****************************************************************************/
*****************************************************************************/
...
@@ -465,7 +522,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
...
@@ -465,7 +522,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
if
(
retval
)
{
if
(
retval
)
{
port
->
open_count
=
0
;
port
->
open_count
=
0
;
module_put
(
serial
->
type
->
owner
);
module_put
(
serial
->
type
->
owner
);
kref_put
(
&
serial
->
kref
);
kref_put
(
&
serial
->
kref
,
destroy_serial
);
}
}
}
}
bailout:
bailout:
...
@@ -496,7 +553,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
...
@@ -496,7 +553,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
}
}
module_put
(
port
->
serial
->
type
->
owner
);
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
)
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)
...
@@ -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
)
static
int
serial_read_proc
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
{
struct
usb_serial
*
serial
;
struct
usb_serial
*
serial
;
...
@@ -694,7 +744,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
...
@@ -694,7 +744,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
begin
+=
length
;
begin
+=
length
;
length
=
0
;
length
=
0
;
}
}
kref_put
(
&
serial
->
kref
);
kref_put
(
&
serial
->
kref
,
destroy_serial
);
}
}
*
eof
=
1
;
*
eof
=
1
;
done:
done:
...
@@ -763,62 +813,6 @@ void usb_serial_port_softint(void *private)
...
@@ -763,62 +813,6 @@ void usb_serial_port_softint(void *private)
wake_up_interruptible
(
&
tty
->
write_wait
);
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
)
static
void
port_release
(
struct
device
*
dev
)
{
{
struct
usb_serial_port
*
port
=
to_usb_serial_port
(
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,
...
@@ -859,7 +853,7 @@ static struct usb_serial * create_serial (struct usb_device *dev,
serial
->
interface
=
interface
;
serial
->
interface
=
interface
;
serial
->
vendor
=
dev
->
descriptor
.
idVendor
;
serial
->
vendor
=
dev
->
descriptor
.
idVendor
;
serial
->
product
=
dev
->
descriptor
.
idProduct
;
serial
->
product
=
dev
->
descriptor
.
idProduct
;
kref_init
(
&
serial
->
kref
,
destroy_serial
);
kref_init
(
&
serial
->
kref
);
return
serial
;
return
serial
;
}
}
...
@@ -1209,7 +1203,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
...
@@ -1209,7 +1203,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
if
(
serial
)
{
if
(
serial
)
{
/* let the last holder of this object
/* let the last holder of this object
* cause it to be cleaned up */
* cause it to be cleaned up */
kref_put
(
&
serial
->
kref
);
kref_put
(
&
serial
->
kref
,
destroy_serial
);
}
}
dev_info
(
dev
,
"device disconnected
\n
"
);
dev_info
(
dev
,
"device disconnected
\n
"
);
}
}
...
...
include/linux/device.h
View file @
f75bdb62
...
@@ -59,7 +59,6 @@ struct bus_type {
...
@@ -59,7 +59,6 @@ struct bus_type {
struct
driver_attribute
*
drv_attrs
;
struct
driver_attribute
*
drv_attrs
;
int
(
*
match
)(
struct
device
*
dev
,
struct
device_driver
*
drv
);
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
(
*
hotplug
)
(
struct
device
*
dev
,
char
**
envp
,
int
num_envp
,
char
*
buffer
,
int
buffer_size
);
int
num_envp
,
char
*
buffer
,
int
buffer_size
);
int
(
*
suspend
)(
struct
device
*
dev
,
u32
state
);
int
(
*
suspend
)(
struct
device
*
dev
,
u32
state
);
...
...
include/linux/kobject.h
View file @
f75bdb62
...
@@ -19,6 +19,7 @@
...
@@ -19,6 +19,7 @@
#include <linux/list.h>
#include <linux/list.h>
#include <linux/sysfs.h>
#include <linux/sysfs.h>
#include <linux/rwsem.h>
#include <linux/rwsem.h>
#include <linux/kref.h>
#include <asm/atomic.h>
#include <asm/atomic.h>
#define KOBJ_NAME_LEN 20
#define KOBJ_NAME_LEN 20
...
@@ -26,7 +27,7 @@
...
@@ -26,7 +27,7 @@
struct
kobject
{
struct
kobject
{
char
*
k_name
;
char
*
k_name
;
char
name
[
KOBJ_NAME_LEN
];
char
name
[
KOBJ_NAME_LEN
];
atomic_t
refcount
;
struct
kref
kref
;
struct
list_head
entry
;
struct
list_head
entry
;
struct
kobject
*
parent
;
struct
kobject
*
parent
;
struct
kset
*
kset
;
struct
kset
*
kset
;
...
@@ -58,6 +59,8 @@ extern void kobject_put(struct kobject *);
...
@@ -58,6 +59,8 @@ extern void kobject_put(struct kobject *);
extern
void
kobject_hotplug
(
const
char
*
action
,
struct
kobject
*
);
extern
void
kobject_hotplug
(
const
char
*
action
,
struct
kobject
*
);
extern
char
*
kobject_get_path
(
struct
kset
*
,
struct
kobject
*
,
int
);
struct
kobj_type
{
struct
kobj_type
{
void
(
*
release
)(
struct
kobject
*
);
void
(
*
release
)(
struct
kobject
*
);
struct
sysfs_ops
*
sysfs_ops
;
struct
sysfs_ops
*
sysfs_ops
;
...
...
include/linux/kref.h
View file @
f75bdb62
...
@@ -18,15 +18,12 @@
...
@@ -18,15 +18,12 @@
#include <linux/types.h>
#include <linux/types.h>
#include <asm/atomic.h>
#include <asm/atomic.h>
struct
kref
{
struct
kref
{
atomic_t
refcount
;
atomic_t
refcount
;
void
(
*
release
)(
struct
kref
*
kref
);
};
};
void
kref_init
(
struct
kref
*
kref
,
void
(
*
release
)(
struct
kref
*
));
void
kref_init
(
struct
kref
*
kref
);
struct
kref
*
kref_get
(
struct
kref
*
kref
);
void
kref_get
(
struct
kref
*
kref
);
void
kref_put
(
struct
kref
*
kref
);
void
kref_put
(
struct
kref
*
kref
,
void
(
*
release
)
(
struct
kref
*
kref
));
#endif
/* _KREF_H_ */
#endif
/* _KREF_H_ */
lib/Makefile
View file @
f75bdb62
...
@@ -5,12 +5,9 @@
...
@@ -5,12 +5,9 @@
lib-y
:=
errno.o ctype.o string.o vsprintf.o cmdline.o
\
lib-y
:=
errno.o ctype.o string.o vsprintf.o cmdline.o
\
bust_spinlocks.o rbtree.o radix-tree.o dump_stack.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
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_GENERIC_SPINLOCK)
+=
rwsem-spinlock.o
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM)
+=
rwsem.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)
...
@@ -58,14 +58,11 @@ static int create_dir(struct kobject * kobj)
return
error
;
return
error
;
}
}
static
inline
struct
kobject
*
to_kobj
(
struct
list_head
*
entry
)
static
inline
struct
kobject
*
to_kobj
(
struct
list_head
*
entry
)
{
{
return
container_of
(
entry
,
struct
kobject
,
entry
);
return
container_of
(
entry
,
struct
kobject
,
entry
);
}
}
#ifdef CONFIG_HOTPLUG
static
int
get_kobj_path_length
(
struct
kset
*
kset
,
struct
kobject
*
kobj
)
static
int
get_kobj_path_length
(
struct
kset
*
kset
,
struct
kobject
*
kobj
)
{
{
int
length
=
1
;
int
length
=
1
;
...
@@ -98,6 +95,31 @@ static void fill_kobj_path(struct kset *kset, struct kobject *kobj, char *path,
...
@@ -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
);
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 BUFFER_SIZE 1024
/* should be enough memory for the env */
#define NUM_ENVP 32
/* number of env pointers */
#define NUM_ENVP 32
/* number of env pointers */
static
unsigned
long
sequence_num
;
static
unsigned
long
sequence_num
;
...
@@ -112,7 +134,6 @@ static void kset_hotplug(const char *action, struct kset *kset,
...
@@ -112,7 +134,6 @@ static void kset_hotplug(const char *action, struct kset *kset,
char
*
scratch
;
char
*
scratch
;
int
i
=
0
;
int
i
=
0
;
int
retval
;
int
retval
;
int
kobj_path_length
;
char
*
kobj_path
=
NULL
;
char
*
kobj_path
=
NULL
;
char
*
name
=
NULL
;
char
*
name
=
NULL
;
unsigned
long
seq
;
unsigned
long
seq
;
...
@@ -163,12 +184,9 @@ static void kset_hotplug(const char *action, struct kset *kset,
...
@@ -163,12 +184,9 @@ static void kset_hotplug(const char *action, struct kset *kset,
envp
[
i
++
]
=
scratch
;
envp
[
i
++
]
=
scratch
;
scratch
+=
sprintf
(
scratch
,
"SEQNUM=%ld"
,
seq
)
+
1
;
scratch
+=
sprintf
(
scratch
,
"SEQNUM=%ld"
,
seq
)
+
1
;
kobj_path_length
=
get_kobj_path_length
(
kset
,
kobj
);
kobj_path
=
kobject_get_path
(
kset
,
kobj
,
GFP_KERNEL
);
kobj_path
=
kmalloc
(
kobj_path_length
,
GFP_KERNEL
);
if
(
!
kobj_path
)
if
(
!
kobj_path
)
goto
exit
;
goto
exit
;
memset
(
kobj_path
,
0x00
,
kobj_path_length
);
fill_kobj_path
(
kset
,
kobj
,
kobj_path
,
kobj_path_length
);
envp
[
i
++
]
=
scratch
;
envp
[
i
++
]
=
scratch
;
scratch
+=
sprintf
(
scratch
,
"DEVPATH=%s"
,
kobj_path
)
+
1
;
scratch
+=
sprintf
(
scratch
,
"DEVPATH=%s"
,
kobj_path
)
+
1
;
...
@@ -225,10 +243,9 @@ void kobject_hotplug(const char *action, struct kobject *kobj)
...
@@ -225,10 +243,9 @@ void kobject_hotplug(const char *action, struct kobject *kobj)
* kobject_init - initialize object.
* kobject_init - initialize object.
* @kobj: object in question.
* @kobj: object in question.
*/
*/
void
kobject_init
(
struct
kobject
*
kobj
)
void
kobject_init
(
struct
kobject
*
kobj
)
{
{
atomic_set
(
&
kobj
->
refcount
,
1
);
kref_init
(
&
kobj
->
kref
);
INIT_LIST_HEAD
(
&
kobj
->
entry
);
INIT_LIST_HEAD
(
&
kobj
->
entry
);
kobj
->
kset
=
kset_get
(
kobj
->
kset
);
kobj
->
kset
=
kset_get
(
kobj
->
kset
);
}
}
...
@@ -325,7 +342,7 @@ int kobject_register(struct kobject * kobj)
...
@@ -325,7 +342,7 @@ int kobject_register(struct kobject * kobj)
* @kobj: object.
* @kobj: object.
* @name: name.
* @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
* string that @kobj->k_name points to. Otherwise, use the static
* @kobj->name array.
* @kobj->name array.
*/
*/
...
@@ -429,10 +446,8 @@ void kobject_unregister(struct kobject * kobj)
...
@@ -429,10 +446,8 @@ void kobject_unregister(struct kobject * kobj)
struct
kobject
*
kobject_get
(
struct
kobject
*
kobj
)
struct
kobject
*
kobject_get
(
struct
kobject
*
kobj
)
{
{
if
(
kobj
)
{
if
(
kobj
)
WARN_ON
(
!
atomic_read
(
&
kobj
->
refcount
));
kref_get
(
&
kobj
->
kref
);
atomic_inc
(
&
kobj
->
refcount
);
}
return
kobj
;
return
kobj
;
}
}
...
@@ -459,17 +474,21 @@ void kobject_cleanup(struct kobject * kobj)
...
@@ -459,17 +474,21 @@ void kobject_cleanup(struct kobject * kobj)
kobject_put
(
parent
);
kobject_put
(
parent
);
}
}
static
void
kobject_release
(
struct
kref
*
kref
)
{
kobject_cleanup
(
container_of
(
kref
,
struct
kobject
,
kref
));
}
/**
/**
* kobject_put - decrement refcount for object.
* kobject_put - decrement refcount for object.
* @kobj: object.
* @kobj: object.
*
*
* Decrement the refcount, and if 0, call kobject_cleanup().
* Decrement the refcount, and if 0, call kobject_cleanup().
*/
*/
void
kobject_put
(
struct
kobject
*
kobj
)
void
kobject_put
(
struct
kobject
*
kobj
)
{
{
if
(
atomic_dec_and_test
(
&
kobj
->
refcount
)
)
if
(
kobj
)
k
object_cleanup
(
kobj
);
k
ref_put
(
&
kobj
->
kref
,
kobject_release
);
}
}
...
@@ -626,7 +645,7 @@ void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
...
@@ -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_init
);
EXPORT_SYMBOL
(
kobject_register
);
EXPORT_SYMBOL
(
kobject_register
);
EXPORT_SYMBOL
(
kobject_unregister
);
EXPORT_SYMBOL
(
kobject_unregister
);
...
...
lib/kref.c
View file @
f75bdb62
...
@@ -11,48 +11,45 @@
...
@@ -11,48 +11,45 @@
*
*
*/
*/
/* #define DEBUG */
#include <linux/kref.h>
#include <linux/kref.h>
#include <linux/module.h>
#include <linux/module.h>
/**
/**
* kref_init - initialize object.
* kref_init - initialize object.
* @kref: object in question.
* @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
);
atomic_set
(
&
kref
->
refcount
,
1
);
kref
->
release
=
release
;
}
}
/**
/**
* kref_get - increment refcount for object.
* kref_get - increment refcount for object.
* @kref: object.
* @kref: object.
*/
*/
struct
kref
*
kref_get
(
struct
kref
*
kref
)
void
kref_get
(
struct
kref
*
kref
)
{
{
WARN_ON
(
!
atomic_read
(
&
kref
->
refcount
));
WARN_ON
(
!
atomic_read
(
&
kref
->
refcount
));
atomic_inc
(
&
kref
->
refcount
);
atomic_inc
(
&
kref
->
refcount
);
return
kref
;
}
}
/**
/**
* kref_put - decrement refcount for object.
* kref_put - decrement refcount for object.
* @kref: 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
))
{
WARN_ON
(
release
==
NULL
);
pr_debug
(
"kref cleaning up
\n
"
);
WARN_ON
(
release
==
(
void
(
*
)(
struct
kref
*
))
kfree
);
kref
->
release
(
kref
);
}
if
(
atomic_dec_and_test
(
&
kref
->
refcount
))
release
(
kref
);
}
}
EXPORT_SYMBOL
(
kref_init
);
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