Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
S
Simple PCIe FMC carrier SPEC
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
50
Issues
50
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
Simple PCIe FMC carrier SPEC
Commits
a509cbd7
Commit
a509cbd7
authored
Jul 08, 2020
by
Federico Vaga
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
sw: enforce scatterlist using a module parameter
Signed-off-by:
Federico Vaga
<
federico.vaga@cern.ch
>
parent
6bf976cb
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
50 additions
and
3 deletions
+50
-3
sw-driver.rst
doc/sw-driver.rst
+5
-0
test_dma.py
pytest/test_dma.py
+24
-0
PySPEC.py
software/PySPEC/PySPEC/PySPEC.py
+12
-2
spec-core-fpga.c
software/kernel/spec-core-fpga.c
+6
-0
spec_dma_throughput.py
software/tools/spec_dma_throughput.py
+3
-1
No files found.
doc/sw-driver.rst
View file @
a509cbd7
...
...
@@ -246,6 +246,11 @@ Module Parameters
change to this value is applied on ``open(2)``
(file ``<pci-id>/spec-<pci-id>/dma``).
``user_dma_max_segment`` [RW]
It sets the maximum size for a DMA transfer in a scatterlist. A
change to this value is applied on the next ``read(2)`` or ``write(2)``
(file ``<pci-id>/spec-<pci-id>/dma``).
DMA
---
...
...
pytest/test_dma.py
View file @
a509cbd7
...
...
@@ -174,6 +174,30 @@ class TestDma(object):
data_rb
=
dma
.
read
(
offset
,
split
)
assert
data
[
offset
:
min
(
offset
+
split
,
buffer_size
)]
==
data_rb
@
pytest
.
mark
.
parametrize
(
"segment_size"
,
[
2
**
i
for
i
in
range
(
3
,
20
)])
def
test_dma_scatterlist_read
(
self
,
spec
,
segment_size
):
"""
Enforce a scatterlist on known size to read 1MiB.
"""
buffer_size
=
2
**
20
data
=
bytes
([
random
.
randrange
(
0
,
0xFF
,
1
)
for
i
in
range
(
buffer_size
)])
with
spec
.
dma
()
as
dma
:
dma
.
write
(
0
,
data
)
assert
data
==
dma
.
read
(
0
,
len
(
data
),
segment_size
)
@
pytest
.
mark
.
parametrize
(
"segment_size"
,
[
2
**
i
for
i
in
range
(
3
,
12
)])
def
test_dma_scatterlist_write
(
self
,
spec
,
segment_size
):
"""
Enforce a scatterlist on known size to write 1MiB.
Remember: on write the scatterlist is enforced by the driver
on buffers bigger than 4KiB
"""
buffer_size
=
2
**
20
data
=
bytes
([
random
.
randrange
(
0
,
0xFF
,
1
)
for
i
in
range
(
buffer_size
)])
with
spec
.
dma
()
as
dma
:
dma
.
write
(
0
,
data
,
segment_size
)
assert
data
==
dma
.
read
(
0
,
len
(
data
))
@
pytest
.
mark
.
parametrize
(
"ddr_offset"
,
[
0x0
]
+
\
[
2
**
i
for
i
in
range
(
int
(
math
.
log2
(
PySPEC
.
DDR_ALIGN
)),
int
(
math
.
log2
(
PySPEC
.
DDR_SIZE
)))]
+
\
...
...
software/PySPEC/PySPEC/PySPEC.py
View file @
a509cbd7
...
...
@@ -120,30 +120,40 @@ class PySPEC:
if
hasattr
(
self
,
"dma_file"
):
self
.
dma_file
.
close
()
def
read
(
self
,
offset
,
size
):
def
read
(
self
,
offset
,
size
,
max_segment
=
0
):
"""
Trigger a *device to memory* DMA transfer
:var offset: offset within the DDR
:var size: number of bytes to be transferred
:var max_segment: maximum size of a single transfer in a
scatterlist. Default is 0, it means to use
the DMA engine's default.
:return: the data transfered as bytes() array
:raise OSError: if the read(2) or the driver fails
"""
with
open
(
"/sys/module/spec_fmc_carrier/parameters/user_dma_max_segment"
,
"w"
)
as
f
:
f
.
write
(
str
(
max_segment
))
self
.
__seek
(
offset
)
data
=
[]
while
size
-
len
(
data
)
>
0
:
data
+=
self
.
dma_file
.
read
(
size
-
len
(
data
))
return
bytes
(
data
)
def
write
(
self
,
offset
,
data
):
def
write
(
self
,
offset
,
data
,
max_segment
=
0
):
"""
Trigger a *memory to device* DMA transfer
:var offset: offset within the DDR
:var size: number of bytes to be transferred
:var max_segment: maximum size of a single transfer in a
scatterlist. Default is 0, it means to use
the DMA engine's default.
:return: the number of transfered bytes
:raise OSError: if the write(2) or the driver fails
"""
with
open
(
"/sys/module/spec_fmc_carrier/parameters/user_dma_max_segment"
,
"w"
)
as
f
:
f
.
write
(
str
(
max_segment
))
self
.
__seek
(
offset
)
start
=
0
while
len
(
data
)
-
start
>
0
:
...
...
software/kernel/spec-core-fpga.c
View file @
a509cbd7
...
...
@@ -29,6 +29,10 @@ static int user_dma_coherent_size = 4 * 1024 * 1024;
module_param
(
user_dma_coherent_size
,
int
,
0644
);
MODULE_PARM_DESC
(
user_dma_coherent_size
,
"DMA coherent allocation's size in bytes (default 4MiB)"
);
static
size_t
user_dma_max_segment
;
module_param
(
user_dma_max_segment
,
long
,
0644
);
MODULE_PARM_DESC
(
user_dma_max_segment
,
"Maximum DMA segment size in bytes (default 0, meaning whatever supported by the DMA engine)"
);
enum
spec_fpga_irq_lines
{
SPEC_FPGA_IRQ_FMC_I2C
=
0
,
...
...
@@ -179,6 +183,8 @@ static int spec_fpga_dbg_dma_transfer(struct spec_fpga_dbg_dma *dbgdma,
max_segment
=
dma_get_max_seg_size
(
dbgdma
->
dchan
->
device
->
dev
);
else
max_segment
=
4096
;
if
(
user_dma_max_segment
)
max_segment
=
min
(
user_dma_max_segment
,
max_segment
);
err
=
sg_alloc_table
(
&
sgt
,
(
count
/
max_segment
)
+
!!
(
count
%
max_segment
),
GFP_KERNEL
);
...
...
software/tools/spec_dma_throughput.py
View file @
a509cbd7
...
...
@@ -24,6 +24,8 @@ def main():
help
=
'Minimum transfer size in Bytes (default: 4096 Bytes). It is rounded to the lower power of 2.'
)
parser
.
add_argument
(
'--max'
,
default
=
4
*
1024
*
1024
,
type
=
int
,
help
=
'Maximum transfer size in Bytes (default: 4194304 Bytes). It is rounded to the lower power of 2.'
)
parser
.
add_argument
(
'--seg'
,
default
=
0
,
type
=
int
,
help
=
'Overwrite scatterlist segment size.'
)
args
=
parser
.
parse_args
()
tracing_path
=
"/sys/kernel/debug/tracing"
...
...
@@ -41,7 +43,7 @@ def main():
with
open
(
os
.
path
.
join
(
tracing_path
,
"trace"
),
"w"
)
as
f
:
f
.
write
(
""
)
with
spec
.
dma
(
size
)
as
dma
:
dma
.
read
(
0
,
size
)
dma
.
read
(
0
,
size
,
args
.
seg
)
with
open
(
os
.
path
.
join
(
tracing_path
,
"trace"
),
"r"
)
as
f
:
throughput
.
append
((
float
(
size
)
/
1024
/
1024
)
/
dma_time_get
(
f
.
read
()))
print
(
"{:d} Bytes -> {:f} MBps"
.
format
(
size
,
throughput
[
-
1
]))
...
...
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