Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
F
FPGA Configuration Space
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
FPGA Configuration Space
Commits
04b4ceac
Commit
04b4ceac
authored
Apr 27, 2016
by
Wesley W. Terpstra
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wishbone: deliver MSIs
parent
7160ddbb
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
117 additions
and
6 deletions
+117
-6
wishbone.c
pcie-wb/wishbone.c
+112
-5
wishbone.h
pcie-wb/wishbone.h
+5
-1
No files found.
pcie-wb/wishbone.c
View file @
04b4ceac
...
...
@@ -134,6 +134,85 @@ static void claim_msi(struct etherbone_master_context* context)
mutex_unlock
(
&
wb
->
mutex
);
}
/* Must be called with wb->mutex held */
static
void
advance_msi
(
struct
wishbone
*
wb
)
{
struct
wishbone_request
request
;
struct
etherbone_master_context
*
context
;
uint8_t
*
wptr
;
int
index
;
/* Don't process a second MSI while a previous is inflight */
if
(
wb
->
msi_pending
)
return
;
retry:
/* If nothing to do, stop */
if
(
wb
->
wops
->
request
(
wb
,
&
request
)
==
0
)
return
;
/* The hardware should already have done this, but be safe */
request
.
addr
&=
wb
->
mask
;
/* If no MSI handler, handle it immediately */
index
=
request
.
addr
/
((
wb
->
mask
/
WISHBONE_MAX_MSI_OPEN
)
+
1
);
if
(
!
wb
->
msi_map
[
index
])
{
wb
->
wops
->
reply
(
wb
,
1
,
~
(
wb_data_t
)
0
);
goto
retry
;
}
/* Fill in the MSI data */
context
=
wb
->
msi_map
[
index
];
wptr
=
&
context
->
msi
[
0
];
wptr
[
0
]
=
ETHERBONE_BCA
;
wptr
[
1
]
=
request
.
mask
;
if
(
request
.
write
)
{
wptr
[
2
]
=
1
;
wptr
[
3
]
=
0
;
wptr
+=
sizeof
(
wb_data_t
);
eb_from_cpu
(
wptr
,
request
.
addr
);
wptr
+=
sizeof
(
wb_data_t
);
eb_from_cpu
(
wptr
,
request
.
data
);
wptr
+=
sizeof
(
wb_data_t
);
}
else
{
wptr
[
2
]
=
0
;
wptr
[
3
]
=
1
;
wptr
+=
sizeof
(
wb_data_t
);
eb_from_cpu
(
wptr
,
WBA_DATA
);
wptr
+=
sizeof
(
wb_data_t
);
eb_from_cpu
(
wptr
,
request
.
addr
);
wptr
+=
sizeof
(
wb_data_t
);
}
wptr
[
0
]
=
ETHERBONE_CYC
|
ETHERBONE_BCA
|
ETHERBONE_RCA
;
wptr
[
1
]
=
0xf
;
wptr
[
2
]
=
0
;
wptr
[
3
]
=
1
;
wptr
+=
sizeof
(
wb_data_t
);
eb_from_cpu
(
wptr
,
WBA_ERR
);
wptr
+=
sizeof
(
wb_data_t
);
eb_from_cpu
(
wptr
,
4
);
/* low bits of error status register */
wptr
+=
sizeof
(
wb_data_t
);
/* Mark the MSI pending */
context
->
msi_unread
=
wptr
-
&
context
->
msi
[
0
];
context
->
msi_pending
=
1
;
wb
->
msi_pending
=
1
;
/* Wake-up any reader of the device */
wake_up_interruptible
(
&
context
->
waitq
);
kill_fasync
(
&
context
->
fasync
,
SIGIO
,
POLL_IN
);
}
static
void
respond_msi
(
struct
wishbone
*
wb
,
int
error
)
{
mutex_lock
(
&
wb
->
mutex
);
wb
->
wops
->
reply
(
wb
,
error
,
wb
->
msi_data
);
wb
->
msi_pending
=
0
;
advance_msi
(
wb
);
mutex_unlock
(
&
wb
->
mutex
);
}
static
wb_data_t
handle_read_cfg
(
struct
etherbone_master_context
*
context
,
wb_addr_t
addr
)
{
struct
wishbone
*
wb
=
context
->
wishbone
;
...
...
@@ -153,9 +232,28 @@ static wb_data_t handle_read_cfg(struct etherbone_master_context* context, wb_ad
static
void
handle_write_cfg
(
struct
etherbone_master_context
*
context
,
wb_addr_t
addr
,
wb_data_t
data
)
{
struct
wishbone
*
wb
=
context
->
wishbone
;
switch
(
addr
)
{
case
36
:
if
(
data
==
1
)
claim_msi
(
context
);
break
;
default:
break
;
case
36
:
if
(
data
==
1
)
{
claim_msi
(
context
);
}
break
;
case
WBA_DATA
:
if
(
context
->
msi_pending
)
{
mutex_lock
(
&
wb
->
mutex
);
wb
->
msi_data
=
data
;
mutex_unlock
(
&
wb
->
mutex
);
}
break
;
case
WBA_ERR
:
if
(
context
->
msi_pending
)
{
context
->
msi_pending
=
0
;
respond_msi
(
wb
,
data
&
1
);
}
break
;
}
}
...
...
@@ -293,8 +391,9 @@ static int char_master_open(struct inode *inode, struct file *filep)
context
->
sent
=
0
;
context
->
processed
=
0
;
context
->
received
=
0
;
context
->
msi_unread
=
0
;
context
->
msi_index
=
-
1
;
context
->
msi_unread
=
0
;
context
->
msi_pending
=
0
;
filep
->
private_data
=
context
;
...
...
@@ -311,6 +410,12 @@ static int char_master_release(struct inode *inode, struct file *filep)
wb
->
wops
->
cycle
(
wb
,
0
);
}
/* Finish any unhandled MSI */
if
(
context
->
msi_pending
)
{
context
->
msi_pending
=
0
;
respond_msi
(
wb
,
1
);
}
/* Unhook any MSI access */
if
(
context
->
msi_index
!=
-
1
)
{
mutex_lock
(
&
wb
->
mutex
);
...
...
@@ -457,6 +562,7 @@ int wishbone_register(struct wishbone* wb)
for
(
i
=
0
;
i
<
WISHBONE_MAX_MSI_OPEN
;
++
i
)
{
wb
->
msi_map
[
i
]
=
0
;
}
wb
->
msi_pending
=
0
;
mutex_lock
(
&
wishbone_mutex
);
...
...
@@ -530,8 +636,9 @@ int wishbone_unregister(struct wishbone* wb)
void
wishbone_slave_ready
(
struct
wishbone
*
wb
)
{
// wake_up_interruptible(&wb->waitq);
// kill_fasync(&wb->fasync, SIGIO, POLL_IN);
mutex_lock
(
&
wb
->
mutex
);
advance_msi
(
wb
);
mutex_unlock
(
&
wb
->
mutex
);
}
static
int
__init
wishbone_init
(
void
)
...
...
pcie-wb/wishbone.h
View file @
04b4ceac
...
...
@@ -67,6 +67,8 @@ struct wishbone
/* internal (EB-MSI mapping for this hardware) */
struct
mutex
mutex
;
struct
etherbone_master_context
*
msi_map
[
WISHBONE_MAX_MSI_OPEN
];
wb_data_t
msi_data
;
int
msi_pending
;
};
#define RING_SIZE 8192
...
...
@@ -86,10 +88,12 @@ struct etherbone_master_context
unsigned
char
buf
[
RING_SIZE
];
/* Ring buffer */
/* MSI resource ownership; -1 = nothing */
int
msi_index
;
/* MSI record data */
unsigned
char
msi
[
sizeof
(
wb_data_t
)
*
6
];
int
msi_unread
;
int
msi_
index
;
int
msi_
pending
;
};
#define RING_READ_LEN(ctx) RING_POS((ctx)->processed - (ctx)->sent)
...
...
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