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
6b150fab
Commit
6b150fab
authored
Jan 14, 2004
by
Ben Collins
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[IEEE1394]: Rework highlevel list locking to avoid blocking under spinlocks.
parent
3d315130
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
43 additions
and
55 deletions
+43
-55
drivers/ieee1394/highlevel.c
drivers/ieee1394/highlevel.c
+36
-49
drivers/ieee1394/highlevel.h
drivers/ieee1394/highlevel.h
+7
-6
No files found.
drivers/ieee1394/highlevel.c
View file @
6b150fab
...
...
@@ -39,8 +39,12 @@ struct hl_host_info {
static
LIST_HEAD
(
hl_drivers
);
static
rwlock_t
hl_drivers_lock
=
RW_LOCK_UNLOCKED
;
static
DECLARE_RWSEM
(
hl_drivers_sem
)
;
static
LIST_HEAD
(
hl_irqs
);
static
rwlock_t
hl_irqs_lock
=
RW_LOCK_UNLOCKED
;
static
LIST_HEAD
(
addr_space
);
static
rwlock_t
addr_space_lock
=
RW_LOCK_UNLOCKED
;
/* addr_space list will have zero and max already included as bounds */
...
...
@@ -238,20 +242,22 @@ static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data)
void
hpsb_register_highlevel
(
struct
hpsb_highlevel
*
hl
)
{
unsigned
long
flags
;
INIT_LIST_HEAD
(
&
hl
->
addr_list
);
INIT_LIST_HEAD
(
&
hl
->
host_info_list
);
rwlock_init
(
&
hl
->
host_info_lock
);
write_lock_irqsave
(
&
hl_drivers_lock
,
flags
);
down_write
(
&
hl_drivers_sem
);
list_add_tail
(
&
hl
->
hl_list
,
&
hl_drivers
);
write_unlock_irqrestore
(
&
hl_drivers_lock
,
flags
);
up_write
(
&
hl_drivers_sem
);
if
(
hl
->
add_host
)
nodemgr_for_each_host
(
hl
,
highlevel_for_each_host_reg
);
write_lock
(
&
hl_irqs_lock
);
list_add_tail
(
&
hl
->
irq_list
,
&
hl_irqs
);
write_unlock
(
&
hl_irqs_lock
);
return
;
}
...
...
@@ -279,9 +285,13 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
}
write_unlock_irqrestore
(
&
addr_space_lock
,
flags
);
write_lock_irqsave
(
&
hl_drivers_lock
,
flags
);
write_lock
(
&
hl_irqs_lock
);
list_del
(
&
hl
->
irq_list
);
write_unlock
(
&
hl_irqs_lock
);
down_write
(
&
hl_drivers_sem
);
list_del
(
&
hl
->
hl_list
);
write_unlock_irqrestore
(
&
hl_drivers_lock
,
flags
);
up_write
(
&
hl_drivers_sem
);
if
(
hl
->
remove_host
)
nodemgr_for_each_host
(
hl
,
highlevel_for_each_host_unreg
);
...
...
@@ -395,38 +405,31 @@ void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
void
highlevel_add_host
(
struct
hpsb_host
*
host
)
{
struct
list_head
*
entry
;
struct
hpsb_highlevel
*
hl
;
init_hpsb_highlevel
(
host
);
read_lock
(
&
hl_drivers_lock
);
list_for_each
(
entry
,
&
hl_drivers
)
{
hl
=
list_entry
(
entry
,
struct
hpsb_highlevel
,
hl_list
);
down_read
(
&
hl_drivers_sem
);
list_for_each_entry
(
hl
,
&
hl_drivers
,
hl_list
)
{
if
(
hl
->
add_host
)
hl
->
add_host
(
host
);
}
read_unlock
(
&
hl_drivers_lock
);
up_read
(
&
hl_drivers_sem
);
}
void
highlevel_remove_host
(
struct
hpsb_host
*
host
)
{
struct
list_head
*
entry
;
struct
hpsb_highlevel
*
hl
;
struct
list_head
*
lh
,
*
next
;
struct
hpsb_address_serve
*
as
;
unsigned
long
flags
;
read_lock
(
&
hl_drivers_lock
);
list_for_each
(
entry
,
&
hl_drivers
)
{
hl
=
list_entry
(
entry
,
struct
hpsb_highlevel
,
hl_list
);
down_read
(
&
hl_drivers_sem
);
list_for_each_entry
(
hl
,
&
hl_drivers
,
hl_list
)
{
if
(
hl
->
remove_host
)
{
hl
->
remove_host
(
host
);
hpsb_destroy_hostinfo
(
hl
,
host
);
}
}
read_unlock
(
&
hl_drivers_lock
);
up_read
(
&
hl_drivers_sem
);
/* Free up 1394 address space left behind by high level drivers. */
write_lock_irqsave
(
&
addr_space_lock
,
flags
);
...
...
@@ -442,58 +445,42 @@ void highlevel_remove_host(struct hpsb_host *host)
void
highlevel_host_reset
(
struct
hpsb_host
*
host
)
{
struct
list_head
*
entry
;
struct
hpsb_highlevel
*
hl
;
read_lock
(
&
hl_drivers_lock
);
list_for_each
(
entry
,
&
hl_drivers
)
{
hl
=
list_entry
(
entry
,
struct
hpsb_highlevel
,
hl_list
);
read_lock
(
&
hl_irqs_lock
);
list_for_each_entry
(
hl
,
&
hl_irqs
,
hl_list
)
{
if
(
hl
->
host_reset
)
hl
->
host_reset
(
host
);
}
read_unlock
(
&
hl_
driver
s_lock
);
read_unlock
(
&
hl_
irq
s_lock
);
}
void
highlevel_iso_receive
(
struct
hpsb_host
*
host
,
void
*
data
,
size_t
length
)
void
highlevel_iso_receive
(
struct
hpsb_host
*
host
,
void
*
data
,
size_t
length
)
{
struct
list_head
*
entry
;
struct
hpsb_highlevel
*
hl
;
int
channel
=
(((
quadlet_t
*
)
data
)[
0
]
>>
8
)
&
0x3f
;
read_lock
(
&
hl_drivers_lock
);
entry
=
hl_drivers
.
next
;
while
(
entry
!=
&
hl_drivers
)
{
hl
=
list_entry
(
entry
,
struct
hpsb_highlevel
,
hl_list
);
if
(
hl
->
iso_receive
)
{
read_lock
(
&
hl_irqs_lock
);
list_for_each_entry
(
hl
,
&
hl_irqs
,
irq_list
)
{
if
(
hl
->
iso_receive
)
hl
->
iso_receive
(
host
,
channel
,
data
,
length
);
}
entry
=
entry
->
next
;
}
read_unlock
(
&
hl_
driver
s_lock
);
read_unlock
(
&
hl_
irq
s_lock
);
}
void
highlevel_fcp_request
(
struct
hpsb_host
*
host
,
int
nodeid
,
int
direction
,
void
*
data
,
size_t
length
)
{
struct
list_head
*
entry
;
struct
hpsb_highlevel
*
hl
;
int
cts
=
((
quadlet_t
*
)
data
)[
0
]
>>
4
;
read_lock
(
&
hl_drivers_lock
);
entry
=
hl_drivers
.
next
;
while
(
entry
!=
&
hl_drivers
)
{
hl
=
list_entry
(
entry
,
struct
hpsb_highlevel
,
hl_list
);
if
(
hl
->
fcp_request
)
{
read_lock
(
&
hl_irqs_lock
);
list_for_each_entry
(
hl
,
&
hl_irqs
,
irq_list
)
{
if
(
hl
->
fcp_request
)
hl
->
fcp_request
(
host
,
nodeid
,
direction
,
cts
,
data
,
length
);
}
entry
=
entry
->
next
;
length
);
}
read_unlock
(
&
hl_
driver
s_lock
);
read_unlock
(
&
hl_
irq
s_lock
);
}
int
highlevel_read
(
struct
hpsb_host
*
host
,
int
nodeid
,
void
*
data
,
...
...
drivers/ieee1394/highlevel.h
View file @
6b150fab
...
...
@@ -38,9 +38,9 @@ struct hpsb_highlevel {
* hpsb_unregister_highlevel once for each host. */
void
(
*
remove_host
)
(
struct
hpsb_host
*
host
);
/* Host experienced bus reset with possible configuration changes.
Note
* that this one may occur during interrupt/bottom half handling. You
*
can not expect to be able to do stock hpsb_reads. */
/* Host experienced bus reset with possible configuration changes.
* Note that this one may occur during interrupt/bottom half handling.
* You
can not expect to be able to do stock hpsb_reads. */
void
(
*
host_reset
)
(
struct
hpsb_host
*
host
);
/* An isochronous packet was received. Channel contains the channel
...
...
@@ -52,13 +52,14 @@ struct hpsb_highlevel {
/* A write request was received on either the FCP_COMMAND (direction =
* 0) or the FCP_RESPONSE (direction = 1) register. The cts arg
* contains the cts field (first byte of data).
*/
* contains the cts field (first byte of data). */
void
(
*
fcp_request
)
(
struct
hpsb_host
*
host
,
int
nodeid
,
int
direction
,
int
cts
,
u8
*
data
,
size_t
length
);
/* These are initialized by the subsystem when the
* hpsb_higlevel is registered. */
struct
list_head
hl_list
;
struct
list_head
irq_list
;
struct
list_head
addr_list
;
struct
list_head
host_info_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