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
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