Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
D
dma_ip_drivers
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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
dma_ip_drivers
Commits
2c01de22
Commit
2c01de22
authored
Oct 30, 2020
by
Karen Xie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
XDMA v2020.1.08: allow ST c2h to end a dma transfer when EOP is received
parent
7642657b
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
242 additions
and
137 deletions
+242
-137
XDMA/linux-kernel/RELEASE
XDMA/linux-kernel/RELEASE
+22
-0
XDMA/linux-kernel/tools/dma_from_device.c
XDMA/linux-kernel/tools/dma_from_device.c
+47
-14
XDMA/linux-kernel/tools/dma_to_device.c
XDMA/linux-kernel/tools/dma_to_device.c
+18
-6
XDMA/linux-kernel/tools/dma_utils.c
XDMA/linux-kernel/tools/dma_utils.c
+15
-12
XDMA/linux-kernel/xdma/cdev_sgdma.c
XDMA/linux-kernel/xdma/cdev_sgdma.c
+2
-1
XDMA/linux-kernel/xdma/libxdma.c
XDMA/linux-kernel/xdma/libxdma.c
+113
-74
XDMA/linux-kernel/xdma/libxdma.h
XDMA/linux-kernel/xdma/libxdma.h
+15
-11
XDMA/linux-kernel/xdma/version.h
XDMA/linux-kernel/xdma/version.h
+1
-1
XDMA/linux-kernel/xdma/xdma_cdev.c
XDMA/linux-kernel/xdma/xdma_cdev.c
+0
-4
XDMA/linux-kernel/xdma/xdma_thread.c
XDMA/linux-kernel/xdma/xdma_thread.c
+9
-14
No files found.
XDMA/linux-kernel/RELEASE
View file @
2c01de22
v2020.1.08
===============
- replaced module parameter "sgdma_timeout" to "h2c_timeout" and "c2h_timeout"
for H2C and C2H channels.
value of 0 means no timeout: wait forever for the dma completion.
- added new "-e" option to dma_from_device
this is for streaming mode only, when -e is set, the driver will end the dma
and return the data when an EOP (end-of-packet) is received or the
specified bytes of data is received.
without "-e" option, the driver will end the dma when the specified bytes of
data is received.
- added gen4 device ids
- fixed next adjacent descriptors when dma_alloc_coherent doesn't return a
page-aligned address
v2020.1.06
===============
- added memory aperture support (-k) option in dma_from_device and dma_to_device.
- fixed holding spinlock while doing wait_event_interruptible_xxx
- kernel 5.0 support
- fixed next adjacent descriptors crossing the 4K boundary
Release: 2019.2
===============
...
...
XDMA/linux-kernel/tools/dma_from_device.c
View file @
2c01de22
...
...
@@ -40,6 +40,7 @@ static struct option const long_opts[] = {
{
"offset"
,
required_argument
,
NULL
,
'o'
},
{
"count"
,
required_argument
,
NULL
,
'c'
},
{
"file"
,
required_argument
,
NULL
,
'f'
},
{
"eop_flush"
,
no_argument
,
NULL
,
'e'
},
{
"help"
,
no_argument
,
NULL
,
'h'
},
{
"verbose"
,
no_argument
,
NULL
,
'v'
},
{
0
,
0
,
0
,
0
}
...
...
@@ -48,7 +49,7 @@ static struct option const long_opts[] = {
static
int
test_dma
(
char
*
devname
,
uint64_t
addr
,
uint64_t
aperture
,
uint64_t
size
,
uint64_t
offset
,
uint64_t
count
,
char
*
ofname
);
static
int
no_write
=
0
;
static
int
eop_flush
=
0
;
static
void
usage
(
const
char
*
name
)
{
...
...
@@ -80,12 +81,25 @@ static void usage(const char *name)
" -%c (--%s) file to write the data of the transfers
\n
"
,
long_opts
[
i
].
val
,
long_opts
[
i
].
name
);
i
++
;
fprintf
(
stdout
,
" -%c (--%s) end dma when ST end-of-packet(eop) is rcved
\n
"
,
long_opts
[
i
].
val
,
long_opts
[
i
].
name
);
fprintf
(
stdout
,
"
\t\t
* streaming only, ignored for memory-mapped channels
\n
"
);
fprintf
(
stdout
,
"
\t\t
* acutal # of bytes dma'ed could be smaller than specified
\n
"
);
i
++
;
fprintf
(
stdout
,
" -%c (--%s) print usage help and exit
\n
"
,
long_opts
[
i
].
val
,
long_opts
[
i
].
name
);
i
++
;
fprintf
(
stdout
,
" -%c (--%s) verbose output
\n
"
,
long_opts
[
i
].
val
,
long_opts
[
i
].
name
);
i
++
;
fprintf
(
stdout
,
"
\n
Return code:
\n
"
);
fprintf
(
stdout
,
" 0: all bytes were dma'ed successfully
\n
"
);
fprintf
(
stdout
,
" * with -e set, the bytes dma'ed could be smaller
\n
"
);
fprintf
(
stdout
,
" < 0: error
\n\n
"
);
}
int
main
(
int
argc
,
char
*
argv
[])
...
...
@@ -99,7 +113,7 @@ int main(int argc, char *argv[])
uint64_t
count
=
COUNT_DEFAULT
;
char
*
ofname
=
NULL
;
while
((
cmd_opt
=
getopt_long
(
argc
,
argv
,
"vh
x
c:f:d:a:k:s:o:"
,
long_opts
,
while
((
cmd_opt
=
getopt_long
(
argc
,
argv
,
"vh
e
c:f:d:a:k:s:o:"
,
long_opts
,
NULL
))
!=
-
1
)
{
switch
(
cmd_opt
)
{
case
0
:
...
...
@@ -133,12 +147,12 @@ int main(int argc, char *argv[])
ofname
=
strdup
(
optarg
);
break
;
/* print usage help and exit */
case
'x'
:
no_write
++
;
break
;
case
'v'
:
verbose
=
1
;
break
;
case
'e'
:
eop_flush
=
1
;
break
;
case
'h'
:
default:
usage
(
argv
[
0
]);
...
...
@@ -159,19 +173,30 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
uint64_t
size
,
uint64_t
offset
,
uint64_t
count
,
char
*
ofname
)
{
ssize_t
rc
;
ssize_t
rc
=
0
;
size_t
out_offset
=
0
;
size_t
bytes_done
=
0
;
uint64_t
i
;
uint64_t
apt_loop
=
aperture
?
(
size
+
aperture
-
1
)
/
aperture
:
0
;
char
*
buffer
=
NULL
;
char
*
allocated
=
NULL
;
struct
timespec
ts_start
,
ts_end
;
int
out_fd
=
-
1
;
int
fpga_fd
=
open
(
devname
,
O_RDWR
|
O_NONBLOCK
)
;
int
fpga_fd
;
long
total_time
=
0
;
float
result
;
float
avg_time
=
0
;
int
underflow
=
0
;
/*
* use O_TRUNC to indicate to the driver to flush the data up based on
* EOP (end-of-packet), streaming mode only
*/
if
(
eop_flush
)
fpga_fd
=
open
(
devname
,
O_RDWR
|
O_TRUNC
);
else
fpga_fd
=
open
(
devname
,
O_RDWR
);
if
(
fpga_fd
<
0
)
{
fprintf
(
stderr
,
"unable to open device %s, %d.
\n
"
,
devname
,
fpga_fd
);
...
...
@@ -210,6 +235,7 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
uint64_t
len
=
size
;
char
*
buf
=
buffer
;
bytes_done
=
0
;
for
(
j
=
0
;
j
<
apt_loop
;
j
++
,
len
-=
aperture
,
buf
+=
aperture
)
{
uint64_t
bytes
=
(
len
>
aperture
)
?
aperture
:
len
,
rc
=
read_to_buffer
(
devname
,
fpga_fd
,
buf
,
...
...
@@ -219,13 +245,15 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
if
(
!
underflow
&&
rc
<
bytes
)
underflow
=
1
;
bytes_done
+=
rc
;
}
}
else
{
rc
=
read_to_buffer
(
devname
,
fpga_fd
,
buffer
,
size
,
addr
);
if
(
rc
<
0
)
goto
out
;
bytes_done
=
rc
;
if
(
!
underflow
&&
rc
<
size
)
if
(
!
underflow
&&
bytes_done
<
size
)
underflow
=
1
;
}
clock_gettime
(
CLOCK_MONOTONIC
,
&
ts_end
);
...
...
@@ -238,14 +266,15 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
if
(
verbose
)
fprintf
(
stdout
,
"#%lu: CLOCK_MONOTONIC %ld.%09ld sec. read %ld/%ld bytes
\n
"
,
i
,
ts_end
.
tv_sec
,
ts_end
.
tv_nsec
,
rc
,
size
);
i
,
ts_end
.
tv_sec
,
ts_end
.
tv_nsec
,
bytes_done
,
size
);
/* file argument given? */
if
(
(
out_fd
>=
0
)
&
(
no_write
==
0
)
)
{
if
(
out_fd
>=
0
)
{
rc
=
write_from_buffer
(
ofname
,
out_fd
,
buffer
,
size
,
i
*
size
);
if
(
rc
<
0
)
bytes_done
,
out_offset
);
if
(
rc
<
0
||
rc
<
bytes_done
)
goto
out
;
out_offset
+=
bytes_done
;
}
}
...
...
@@ -256,9 +285,13 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
printf
(
"** Avg time device %s, total time %ld nsec, avg_time = %f, size = %lu, BW = %f
\n
"
,
devname
,
total_time
,
avg_time
,
size
,
result
);
printf
(
"%s ** Average BW = %lu, %f
\n
"
,
devname
,
size
,
result
);
}
rc
=
0
;
}
else
if
(
eop_flush
)
{
/* allow underflow with -e option */
rc
=
0
;
}
else
rc
=
-
EIO
;
rc
=
0
;
out:
close
(
fpga_fd
);
if
(
out_fd
>=
0
)
...
...
XDMA/linux-kernel/tools/dma_to_device.c
View file @
2c01de22
...
...
@@ -93,6 +93,10 @@ static void usage(const char *name)
fprintf
(
stdout
,
" -%c (--%s) verbose output
\n
"
,
long_opts
[
i
].
val
,
long_opts
[
i
].
name
);
i
++
;
fprintf
(
stdout
,
"
\n
Return code:
\n
"
);
fprintf
(
stdout
,
" 0: all bytes were dma'ed successfully
\n
"
);
fprintf
(
stdout
,
" < 0: error
\n\n
"
);
}
int
main
(
int
argc
,
char
*
argv
[])
...
...
@@ -173,6 +177,8 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
{
uint64_t
i
;
ssize_t
rc
;
size_t
bytes_done
=
0
;
size_t
out_offset
=
0
;
uint64_t
apt_loop
=
aperture
?
(
size
+
aperture
-
1
)
/
aperture
:
0
;
char
*
buffer
=
NULL
;
char
*
allocated
=
NULL
;
...
...
@@ -229,7 +235,7 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
if
(
infile_fd
>=
0
)
{
rc
=
read_to_buffer
(
infname
,
infile_fd
,
buffer
,
size
,
0
);
if
(
rc
<
0
)
if
(
rc
<
0
||
rc
<
size
)
goto
out
;
}
...
...
@@ -242,6 +248,7 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
uint64_t
len
=
size
;
char
*
buf
=
buffer
;
bytes_done
=
0
;
for
(
j
=
0
;
j
<
apt_loop
;
j
++
,
len
-=
aperture
,
buf
+=
aperture
)
{
uint64_t
bytes
=
(
len
>
aperture
)
?
aperture
:
len
,
...
...
@@ -250,6 +257,7 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
if
(
rc
<
0
)
goto
out
;
bytes_done
+=
rc
;
if
(
!
underflow
&&
rc
<
bytes
)
underflow
=
1
;
}
...
...
@@ -259,7 +267,8 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
if
(
rc
<
0
)
goto
out
;
if
(
!
underflow
&&
rc
<
size
)
bytes_done
=
rc
;
if
(
!
underflow
&&
bytes_done
<
size
)
underflow
=
1
;
}
...
...
@@ -275,9 +284,10 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
if
(
outfile_fd
>=
0
)
{
rc
=
write_from_buffer
(
ofname
,
outfile_fd
,
buffer
,
size
,
i
*
size
);
if
(
rc
<
0
)
bytes_done
,
out_offset
);
if
(
rc
<
0
||
rc
<
bytes_done
)
goto
out
;
out_offset
+=
bytes_done
;
}
}
...
...
@@ -289,7 +299,6 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
devname
,
total_time
,
avg_time
,
size
,
result
);
printf
(
"%s ** Average BW = %lu, %f
\n
"
,
devname
,
size
,
result
);
}
rc
=
0
;
out:
close
(
fpga_fd
);
...
...
@@ -299,5 +308,8 @@ out:
close
(
outfile_fd
);
free
(
allocated
);
return
rc
;
if
(
rc
<
0
)
return
rc
;
/* treat underflow as error */
return
underflow
?
-
EIO
:
0
;
}
XDMA/linux-kernel/tools/dma_utils.c
View file @
2c01de22
...
...
@@ -47,6 +47,7 @@ ssize_t read_to_buffer(char *fname, int fd, char *buffer, uint64_t size,
uint64_t
count
=
0
;
char
*
buf
=
buffer
;
off_t
offset
=
base
;
int
loop
=
0
;
while
(
count
<
size
)
{
uint64_t
bytes
=
size
-
count
;
...
...
@@ -67,7 +68,7 @@ ssize_t read_to_buffer(char *fname, int fd, char *buffer, uint64_t size,
/* read data from file into memory buffer */
rc
=
read
(
fd
,
buf
,
bytes
);
if
(
rc
<
0
)
{
fprintf
(
stderr
,
"%s, read 0x%lx @ 0x%lx failed %d.
\n
"
,
fprintf
(
stderr
,
"%s, read 0x%lx @ 0x%lx failed %
l
d.
\n
"
,
fname
,
bytes
,
offset
,
rc
);
perror
(
"read file"
);
return
-
EIO
;
...
...
@@ -75,19 +76,19 @@ ssize_t read_to_buffer(char *fname, int fd, char *buffer, uint64_t size,
count
+=
rc
;
if
(
rc
!=
bytes
)
{
fprintf
(
stderr
,
"%s, read underflow 0x%lx/0x%lx
, off
0x%lx.
\n
"
,
fprintf
(
stderr
,
"%s, read underflow 0x%lx/0x%lx
@
0x%lx.
\n
"
,
fname
,
rc
,
bytes
,
offset
);
break
;
}
buf
+=
bytes
;
offset
+=
bytes
;
}
loop
++
;
}
if
(
count
!=
size
)
fprintf
(
stderr
,
"%s, read underflow 0x%lx
!=
0x%lx.
\n
"
,
if
(
count
!=
size
&&
loop
)
fprintf
(
stderr
,
"%s, read underflow 0x%lx
/
0x%lx.
\n
"
,
fname
,
count
,
size
);
return
count
;
}
...
...
@@ -98,6 +99,7 @@ ssize_t write_from_buffer(char *fname, int fd, char *buffer, uint64_t size,
uint64_t
count
=
0
;
char
*
buf
=
buffer
;
off_t
offset
=
base
;
int
loop
=
0
;
while
(
count
<
size
)
{
uint64_t
bytes
=
size
-
count
;
...
...
@@ -118,7 +120,7 @@ ssize_t write_from_buffer(char *fname, int fd, char *buffer, uint64_t size,
/* write data to file from memory buffer */
rc
=
write
(
fd
,
buf
,
bytes
);
if
(
rc
<
0
)
{
fprintf
(
stderr
,
"%s, write 0x%lx @ 0x%lx failed %d.
\n
"
,
fprintf
(
stderr
,
"%s, write 0x%lx @ 0x%lx failed %
l
d.
\n
"
,
fname
,
bytes
,
offset
,
rc
);
perror
(
"write file"
);
return
-
EIO
;
...
...
@@ -126,16 +128,18 @@ ssize_t write_from_buffer(char *fname, int fd, char *buffer, uint64_t size,
count
+=
rc
;
if
(
rc
!=
bytes
)
{
fprintf
(
stderr
,
"%s, write underflow 0x%lx/0x%lx
, off
0x%lx.
\n
"
,
fprintf
(
stderr
,
"%s, write underflow 0x%lx/0x%lx
@
0x%lx.
\n
"
,
fname
,
rc
,
bytes
,
offset
);
break
;
}
buf
+=
bytes
;
offset
+=
bytes
;
}
if
(
count
!=
size
)
fprintf
(
stderr
,
"%s, write underflow 0x%lx != 0x%lx.
\n
"
,
loop
++
;
}
if
(
count
!=
size
&&
loop
)
fprintf
(
stderr
,
"%s, write underflow 0x%lx/0x%lx.
\n
"
,
fname
,
count
,
size
);
return
count
;
...
...
@@ -177,4 +181,3 @@ void timespec_sub(struct timespec *t1, struct timespec *t2)
t1
->
tv_nsec
+=
1000000000
;
}
}
XDMA/linux-kernel/xdma/cdev_sgdma.c
View file @
2c01de22
...
...
@@ -485,7 +485,6 @@ static ssize_t cdev_aio_write(struct kiocb *iocb, const struct iovec *io,
return
-
EIOCBQUEUED
;
}
static
ssize_t
cdev_aio_read
(
struct
kiocb
*
iocb
,
const
struct
iovec
*
io
,
unsigned
long
count
,
loff_t
pos
)
{
...
...
@@ -790,6 +789,8 @@ static int char_sgdma_open(struct inode *inode, struct file *file)
if
(
engine
->
device_open
==
1
)
return
-
EBUSY
;
engine
->
device_open
=
1
;
engine
->
eop_flush
=
(
file
->
f_flags
&
O_TRUNC
)
?
1
:
0
;
}
return
0
;
...
...
XDMA/linux-kernel/xdma/libxdma.c
View file @
2c01de22
...
...
@@ -95,12 +95,20 @@ static DEFINE_SPINLOCK(xdev_rcu_lock);
#define list_last_entry(ptr, type, member) list_entry((ptr)->prev, type, member)
#endif
static
inline
void
xdev_list_add
(
struct
xdma_dev
*
xdev
)
static
inline
int
xdev_list_add
(
struct
xdma_dev
*
xdev
)
{
mutex_lock
(
&
xdev_mutex
);
if
(
list_empty
(
&
xdev_list
))
if
(
list_empty
(
&
xdev_list
))
{
xdev
->
idx
=
0
;
else
{
if
(
poll_mode
)
{
int
rv
=
xdma_threads_create
(
xdev
->
h2c_channel_max
+
xdev
->
c2h_channel_max
);
if
(
rv
<
0
)
{
mutex_unlock
(
&
xdev_mutex
);
return
rv
;
}
}
}
else
{
struct
xdma_dev
*
last
;
last
=
list_last_entry
(
&
xdev_list
,
struct
xdma_dev
,
list_head
);
...
...
@@ -115,6 +123,8 @@ static inline void xdev_list_add(struct xdma_dev *xdev)
spin_lock
(
&
xdev_rcu_lock
);
list_add_tail_rcu
(
&
xdev
->
rcu_node
,
&
xdev_rcu_list
);
spin_unlock
(
&
xdev_rcu_lock
);
return
0
;
}
#undef list_last_entry
...
...
@@ -123,6 +133,8 @@ static inline void xdev_list_remove(struct xdma_dev *xdev)
{
mutex_lock
(
&
xdev_mutex
);
list_del
(
&
xdev
->
list_head
);
if
(
poll_mode
&&
list_empty
(
&
xdev_list
))
xdma_threads_destroy
();
mutex_unlock
(
&
xdev_mutex
);
spin_lock
(
&
xdev_rcu_lock
);
...
...
@@ -526,6 +538,10 @@ static int xdma_engine_stop(struct xdma_engine *engine)
}
dbg_tfr
(
"%s(engine=%p)
\n
"
,
__func__
,
engine
);
if
(
enable_credit_mp
&&
engine
->
streaming
&&
engine
->
dir
==
DMA_FROM_DEVICE
)
write_register
(
0
,
&
engine
->
sgdma_regs
->
credits
,
0
);
w
=
0
;
w
|=
(
u32
)
XDMA_CTRL_IE_DESC_ALIGN_MISMATCH
;
w
|=
(
u32
)
XDMA_CTRL_IE_MAGIC_STOPPED
;
...
...
@@ -871,8 +887,9 @@ static int engine_err_handle(struct xdma_engine *engine,
if
(
engine
->
status
&
XDMA_STAT_BUSY
)
{
value
=
read_register
(
&
engine
->
regs
->
status
);
if
((
value
&
XDMA_STAT_BUSY
))
printk_ratelimited
(
KERN_INFO
"%s has errors but is still BUSY
\n
"
,
engine
->
name
);
printk_ratelimited
(
KERN_INFO
"%s has errors but is still BUSY
\n
"
,
engine
->
name
);
}
printk_ratelimited
(
KERN_INFO
"%s, s 0x%x, aborted xfer 0x%p, cmpl %d/%d
\n
"
,
...
...
@@ -908,6 +925,7 @@ engine_service_final_transfer(struct xdma_engine *engine,
*
pdesc_completed
);
return
NULL
;
}
if
(((
engine
->
dir
==
DMA_FROM_DEVICE
)
&&
(
engine
->
status
&
XDMA_STAT_C2H_ERR_MASK
))
||
((
engine
->
dir
==
DMA_TO_DEVICE
)
&&
...
...
@@ -925,10 +943,42 @@ engine_service_final_transfer(struct xdma_engine *engine,
/* the engine stopped on current transfer? */
if
(
*
pdesc_completed
<
transfer
->
desc_num
)
{
transfer
->
state
=
TRANSFER_STATE_FAILED
;
pr_info
(
"%s, xfer 0x%p, stopped half-way, %d/%d.
\n
"
,
engine
->
name
,
transfer
,
*
pdesc_completed
,
transfer
->
desc_num
);
if
(
engine
->
eop_flush
)
{
/* check if eop received */
struct
xdma_result
*
result
=
transfer
->
res_virt
;
int
i
;
int
max
=
*
pdesc_completed
;
for
(
i
=
0
;
i
<
max
;
i
++
)
{
if
((
result
[
i
].
status
&
RX_STATUS_EOP
)
!=
0
)
{
transfer
->
flags
|=
XFER_FLAG_ST_C2H_EOP_RCVED
;
break
;
}
}
transfer
->
desc_cmpl
+=
*
pdesc_completed
;
if
(
!
(
transfer
->
flags
&
XFER_FLAG_ST_C2H_EOP_RCVED
))
{
return
NULL
;
}
/* mark transfer as successfully completed */
engine_service_shutdown
(
engine
);
transfer
->
state
=
TRANSFER_STATE_COMPLETED
;
engine
->
desc_dequeued
+=
transfer
->
desc_cmpl
;
}
else
{
transfer
->
state
=
TRANSFER_STATE_FAILED
;
pr_info
(
"%s, xfer 0x%p, stopped half-way, %d/%d.
\n
"
,
engine
->
name
,
transfer
,
*
pdesc_completed
,
transfer
->
desc_num
);
/* add dequeued number of descriptors during this run */
engine
->
desc_dequeued
+=
transfer
->
desc_num
;
transfer
->
desc_cmpl
=
*
pdesc_completed
;
}
}
else
{
dbg_tfr
(
"engine %s completed transfer
\n
"
,
engine
->
name
);
dbg_tfr
(
"Completed transfer ID = 0x%p
\n
"
,
transfer
);
...
...
@@ -944,13 +994,14 @@ engine_service_final_transfer(struct xdma_engine *engine,
}
/* mark transfer as successfully completed */
transfer
->
state
=
TRANSFER_STATE_COMPLETED
;
transfer
->
desc_cmpl
=
transfer
->
desc_num
;
/* add dequeued number of descriptors during this run */
engine
->
desc_dequeued
+=
transfer
->
desc_num
;
}
transfer_del:
/* remove completed transfer from list */
list_del
(
engine
->
transfer_list
.
next
);
/* add to dequeued number of descriptors during this run */
engine
->
desc_dequeued
+=
transfer
->
desc_num
;
/*
* Complete transfer - sets transfer to NULL if an asynchronous
...
...
@@ -1021,13 +1072,8 @@ static int engine_service_resume(struct xdma_engine *engine)
dbg_tfr
(
"no pending transfers, %s engine stays idle.
\n
"
,
engine
->
name
);
}
}
else
{
/* engine is still running? */
if
(
list_empty
(
&
engine
->
transfer_list
))
{
pr_warn
(
"no queued transfers but %s engine running!
\n
"
,
engine
->
name
);
WARN_ON
(
1
);
}
}
else
if
(
list_empty
(
&
engine
->
transfer_list
))
{
engine_service_shutdown
(
engine
);
}
return
0
;
}
...
...
@@ -1046,23 +1092,18 @@ static int engine_service(struct xdma_engine *engine, int desc_writeback)
u32
desc_count
=
desc_writeback
&
WB_COUNT_MASK
;
u32
err_flag
=
desc_writeback
&
WB_ERR_MASK
;
int
rv
=
0
;
struct
xdma_poll_wb
*
wb_data
;
if
(
!
engine
)
{
pr_err
(
"dma engine NULL
\n
"
);
return
-
EINVAL
;
}
/* If polling detected an error, signal to the caller */
if
(
err_flag
)
rv
=
-
1
;
/* Service the engine */
if
(
!
engine
->
running
)
{
dbg_tfr
(
"Engine was not running!!! Clearing status
\n
"
);
rv
=
engine_status_read
(
engine
,
1
,
0
);
if
(
rv
<
0
)
{
pr_err
(
"
Failed to read engine status
\n
"
);
pr_err
(
"
%s failed to read status
\n
"
,
engine
->
name
);
return
rv
;
}
return
0
;
...
...
@@ -1086,13 +1127,14 @@ static int engine_service(struct xdma_engine *engine, int desc_writeback)
* shut down
*/
if
((
engine
->
running
&&
!
(
engine
->
status
&
XDMA_STAT_BUSY
))
||
(
desc_count
!=
0
))
{
(
!
engine
->
eop_flush
&&
desc_count
!=
0
))
{
rv
=
engine_service_shutdown
(
engine
);
if
(
rv
<
0
)
{
pr_err
(
"Failed to shutdown engine
\n
"
);
return
rv
;
}
}
/*
* If called from the ISR, or if an error occurred, the descriptor
* count will be zero. In this scenario, read the descriptor count
...
...
@@ -1101,7 +1143,12 @@ static int engine_service(struct xdma_engine *engine, int desc_writeback)
*/
if
(
!
desc_count
)
desc_count
=
read_register
(
&
engine
->
regs
->
completed_desc_count
);
dbg_tfr
(
"desc_count = %d
\n
"
,
desc_count
);
dbg_tfr
(
"%s wb 0x%x, desc_count %u, err %u, dequeued %u.
\n
"
,
engine
->
name
,
desc_writeback
,
desc_count
,
err_flag
,
engine
->
desc_dequeued
);
if
(
!
desc_count
)
goto
done
;
/* transfers on queue? */
if
(
!
list_empty
(
&
engine
->
transfer_list
))
{
...
...
@@ -1135,18 +1182,16 @@ static int engine_service(struct xdma_engine *engine, int desc_writeback)
*/
transfer
=
engine_service_final_transfer
(
engine
,
transfer
,
&
desc_count
);
/* Before starting engine again, clear the writeback data */
if
(
poll_mode
)
{
wb_data
=
(
struct
xdma_poll_wb
*
)
engine
->
poll_mode_addr_virt
;
wb_data
->
completed_desc_count
=
0
;
}
/* Restart the engine following the servicing */
rv
=
engine_service_resume
(
engine
);
if
(
rv
<
0
)
pr_err
(
"Failed to resume engine
\n
"
);
if
(
!
engine
->
eop_flush
)
{
rv
=
engine_service_resume
(
engine
);
if
(
rv
<
0
)
pr_err
(
"Failed to resume engine
\n
"
);
}
return
rv
;
done:
/* If polling detected an error, signal to the caller */
return
err_flag
?
-
1
:
0
;
}
/* engine_service_work */
...
...
@@ -1214,6 +1259,9 @@ static u32 engine_service_wb_monitor(struct xdma_engine *engine,
while
(
expected_wb
!=
0
)
{
desc_wb
=
wb_data
->
completed_desc_count
;
if
(
desc_wb
)
wb_data
->
completed_desc_count
=
0
;
if
(
desc_wb
&
WB_ERR_MASK
)
break
;
else
if
(
desc_wb
>=
expected_wb
)
...
...
@@ -1248,7 +1296,6 @@ static u32 engine_service_wb_monitor(struct xdma_engine *engine,
int
engine_service_poll
(
struct
xdma_engine
*
engine
,
u32
expected_desc_count
)
{
struct
xdma_poll_wb
*
writeback_data
;
u32
desc_wb
=
0
;
unsigned
long
flags
;
int
rv
=
0
;
...
...
@@ -1264,13 +1311,6 @@ int engine_service_poll(struct xdma_engine *engine,
return
-
EINVAL
;
}
writeback_data
=
(
struct
xdma_poll_wb
*
)
engine
->
poll_mode_addr_virt
;
if
((
expected_desc_count
&
WB_COUNT_MASK
)
!=
expected_desc_count
)
{
dbg_tfr
(
"Queued descriptor count is larger than supported
\n
"
);
return
-
1
;
}
/*
* Poll the writeback location for the expected number of
* descriptors / error events This loop is skipped for cyclic mode,
...
...
@@ -1279,6 +1319,8 @@ int engine_service_poll(struct xdma_engine *engine,
*/
desc_wb
=
engine_service_wb_monitor
(
engine
,
expected_desc_count
);
if
(
!
desc_wb
)
return
0
;
spin_lock_irqsave
(
&
engine
->
lock
,
flags
);
dbg_tfr
(
"%s service.
\n
"
,
engine
->
name
);
...
...
@@ -2957,6 +2999,14 @@ static int transfer_init(struct xdma_engine *engine,
control
|=
XDMA_DESC_COMPLETED
;
xdma_desc_control_set
(
xfer
->
desc_virt
+
last
,
control
);
if
(
engine
->
eop_flush
)
{
for
(
i
=
0
;
i
<
last
;
i
++
)
xdma_desc_control_set
(
xfer
->
desc_virt
+
i
,
XDMA_DESC_COMPLETED
);
xfer
->
desc_cmpl_th
=
1
;
}
else
xfer
->
desc_cmpl_th
=
desc_max
;
xfer
->
desc_num
=
desc_max
;
engine
->
desc_idx
=
(
engine
->
desc_idx
+
desc_max
)
%
XDMA_TRANSFER_MAX_DESC
;
...
...
@@ -3101,7 +3151,6 @@ ssize_t xdma_xfer_submit(void *dev_hndl, int channel, bool write, u64 ep_addr,
int
nents
;
enum
dma_data_direction
dir
=
write
?
DMA_TO_DEVICE
:
DMA_FROM_DEVICE
;
struct
xdma_request_cb
*
req
=
NULL
;
struct
xdma_result
*
result
;
if
(
!
dev_hndl
)
return
-
EINVAL
;
...
...
@@ -3213,34 +3262,16 @@ ssize_t xdma_xfer_submit(void *dev_hndl, int channel, bool write, u64 ep_addr,
goto
unmap_sgl
;
}
/*
* When polling, determine how many descriptors have been queued
* on the engine to determine the writeback value expected
*/
if
(
poll_mode
)
{
unsigned
int
desc_count
;
spin_lock_irqsave
(
&
engine
->
lock
,
flags
);
desc_count
=
xfer
->
desc_num
;
spin_unlock_irqrestore
(
&
engine
->
lock
,
flags
);
dbg_tfr
(
"%s poll desc_count=%d
\n
"
,
engine
->
name
,
desc_count
);
rv
=
engine_service_poll
(
engine
,
desc_count
);
if
(
rv
<
0
)
{
mutex_unlock
(
&
engine
->
desc_lock
);
pr_err
(
"Failed to service polling
\n
"
);
goto
unmap_sgl
;
}
if
(
engine
->
cmplthp
)
xdma_kthread_wakeup
(
engine
->
cmplthp
);
}
else
{
if
(
timeout_ms
>
0
)
xlx_wait_event_interruptible_timeout
(
xfer
->
wq
,
if
(
timeout_ms
>
0
)
xlx_wait_event_interruptible_timeout
(
xfer
->
wq
,
(
xfer
->
state
!=
TRANSFER_STATE_SUBMITTED
),
msecs_to_jiffies
(
timeout_ms
));
else
xlx_wait_event_interruptible
(
xfer
->
wq
,
else
xlx_wait_event_interruptible
(
xfer
->
wq
,
(
xfer
->
state
!=
TRANSFER_STATE_SUBMITTED
));
}
spin_lock_irqsave
(
&
engine
->
lock
,
flags
);
...
...
@@ -3248,8 +3279,7 @@ ssize_t xdma_xfer_submit(void *dev_hndl, int channel, bool write, u64 ep_addr,
case
TRANSFER_STATE_COMPLETED
:
spin_unlock_irqrestore
(
&
engine
->
lock
,
flags
);
result
=
xfer
->
res_virt
;
rv
=
0
;
dbg_tfr
(
"transfer %p, %u, ep 0x%llx compl, +%lu.
\n
"
,
xfer
,
xfer
->
len
,
req
->
ep_addr
-
xfer
->
len
,
done
);
...
...
@@ -3257,12 +3287,17 @@ ssize_t xdma_xfer_submit(void *dev_hndl, int channel, bool write, u64 ep_addr,
/* For C2H streaming use writeback results */
if
(
engine
->
streaming
&&
engine
->
dir
==
DMA_FROM_DEVICE
)
{
for
(
i
=
0
;
i
<
xfer
->
desc_num
;
i
++
)
struct
xdma_result
*
result
=
xfer
->
res_virt
;
for
(
i
=
0
;
i
<
xfer
->
desc_cmpl
;
i
++
)
done
+=
result
[
i
].
length
;
/* finish the whole request */
if
(
engine
->
eop_flush
)
nents
=
0
;
}
else
done
+=
xfer
->
len
;
rv
=
0
;
break
;
case
TRANSFER_STATE_FAILED
:
pr_info
(
"xfer 0x%p,%u, failed, ep 0x%llx.
\n
"
,
xfer
,
...
...
@@ -4053,7 +4088,6 @@ void *xdma_device_open(const char *mname, struct pci_dev *pdev, int *user_max,
xdev
->
c2h_channel_max
=
*
c2h_channel_max
;
xdma_device_flag_set
(
xdev
,
XDEV_FLAG_OFFLINE
);
xdev_list_add
(
xdev
);
if
(
xdev
->
user_max
==
0
||
xdev
->
user_max
>
MAX_USER_IRQ
)
xdev
->
user_max
=
MAX_USER_IRQ
;
...
...
@@ -4064,6 +4098,10 @@ void *xdma_device_open(const char *mname, struct pci_dev *pdev, int *user_max,
xdev
->
c2h_channel_max
>
XDMA_CHANNEL_NUM_MAX
)
xdev
->
c2h_channel_max
=
XDMA_CHANNEL_NUM_MAX
;
rv
=
xdev_list_add
(
xdev
);
if
(
rv
<
0
)
goto
free_xdev
;
rv
=
pci_enable_device
(
pdev
);
if
(
rv
)
{
dbg_init
(
"pci_enable_device() failed, %d.
\n
"
,
rv
);
...
...
@@ -4145,6 +4183,7 @@ err_regions:
pci_disable_device
(
pdev
);
err_enable:
xdev_list_remove
(
xdev
);
free_xdev:
kfree
(
xdev
);
return
NULL
;
}
...
...
XDMA/linux-kernel/xdma/libxdma.h
View file @
2c01de22
...
...
@@ -431,6 +431,8 @@ struct sw_desc {
};
/* Describes a (SG DMA) single transfer for the engine */
#define XFER_FLAG_NEED_UNMAP 0x1
#define XFER_FLAG_ST_C2H_EOP_RCVED 0x2
/* ST c2h only */
struct
xdma_transfer
{
struct
list_head
entry
;
/* queue of non-completed transfers */
struct
xdma_desc
*
desc_virt
;
/* virt addr of the 1st descriptor */
...
...
@@ -440,6 +442,8 @@ struct xdma_transfer {
int
desc_adjacent
;
/* adjacent descriptors at desc_bus */
int
desc_num
;
/* number of descriptors in transfer */
int
desc_index
;
/* index for 1st desc. in transfer */
int
desc_cmpl
;
/* completed descriptors */
int
desc_cmpl_th
;
/* completed descriptor threshold */
enum
dma_data_direction
dir
;
#if HAS_SWAKE_UP
struct
swait_queue_head
wq
;
...
...
@@ -449,7 +453,6 @@ struct xdma_transfer {
enum
transfer_state
state
;
/* state of the transfer */
unsigned
int
flags
;
#define XFER_FLAG_NEED_UNMAP 0x1
int
cyclic
;
/* flag if transfer is cyclic */
int
last_in_request
;
/* flag if last within request */
unsigned
int
len
;
...
...
@@ -477,8 +480,6 @@ struct xdma_engine {
struct
xdma_dev
*
xdev
;
/* parent device */
char
name
[
16
];
/* name of this engine */
int
version
;
/* version of this engine */
//dev_t cdevno; /* character device major:minor */
//struct cdev cdev; /* character device (embedded struct) */
/* HW register address offsets */
struct
engine_regs
*
regs
;
/* Control reg BAR offset */
...
...
@@ -488,14 +489,17 @@ struct xdma_engine {
/* Engine state, configuration and flags */
enum
shutdown_state
shutdown
;
/* engine shutdown mode */
enum
dma_data_direction
dir
;
int
device_open
;
/* flag if engine node open, ST mode only */
int
running
;
/* flag if the driver started engine */
int
non_incr_addr
;
/* flag if non-incremental addressing used */
int
streaming
;
int
addr_align
;
/* source/dest alignment in bytes */
int
len_granularity
;
/* transfer length multiple */
int
addr_bits
;
/* HW datapath address width */
int
channel
;
/* engine indices */
u8
addr_align
;
/* source/dest alignment in bytes */
u8
len_granularity
;
/* transfer length multiple */
u8
addr_bits
;
/* HW datapath address width */
u8
channel
:
2
;
/* engine indices */
u8
streaming
:
1
;
u8
device_open
:
1
;
/* flag if engine node open, ST mode only */
u8
running
:
1
;
/* flag if the driver started engine */
u8
non_incr_addr
:
1
;
/* flag if non-incremental addressing used */
u8
eop_flush
:
1
;
/* st c2h only, flush up the data with eop */
u8
filler
:
1
;
int
max_extra_adj
;
/* descriptor prefetch capability */
int
desc_dequeued
;
/* num descriptors of completed transfers */
u32
status
;
/* last known status of device */
...
...
XDMA/linux-kernel/xdma/version.h
View file @
2c01de22
...
...
@@ -22,7 +22,7 @@
#define DRV_MOD_MAJOR 2020
#define DRV_MOD_MINOR 1
#define DRV_MOD_PATCHLEVEL 0
7
#define DRV_MOD_PATCHLEVEL 0
8
#define DRV_MODULE_VERSION \
__stringify(DRV_MOD_MAJOR) "." \
...
...
XDMA/linux-kernel/xdma/xdma_cdev.c
View file @
2c01de22
...
...
@@ -619,8 +619,6 @@ int xdma_cdev_init(void)
return
-
ENOMEM
;
}
xdma_threads_create
(
num_online_cpus
());
return
0
;
}
...
...
@@ -631,6 +629,4 @@ void xdma_cdev_cleanup(void)
if
(
g_xdma_class
)
class_destroy
(
g_xdma_class
);
xdma_threads_destroy
();
}
XDMA/linux-kernel/xdma/xdma_thread.c
View file @
2c01de22
...
...
@@ -39,7 +39,7 @@ static int xdma_thread_cmpl_status_pend(struct list_head *work_item)
unsigned
long
flags
;
spin_lock_irqsave
(
&
engine
->
lock
,
flags
);
pend
=
!
list_empty
(
&
engine
->
transfer_list
);
pend
=
!
list_empty
(
&
engine
->
transfer_list
);
spin_unlock_irqrestore
(
&
engine
->
lock
,
flags
);
return
pend
;
...
...
@@ -53,12 +53,11 @@ static int xdma_thread_cmpl_status_proc(struct list_head *work_item)
engine
=
list_entry
(
work_item
,
struct
xdma_engine
,
cmplthp_list
);
transfer
=
list_entry
(
engine
->
transfer_list
.
next
,
struct
xdma_transfer
,
entry
);
engine_service_poll
(
engine
,
transfer
->
desc_num
);
if
(
transfer
)
engine_service_poll
(
engine
,
transfer
->
desc_cmpl_th
);
return
0
;
}
static
inline
int
xthread_work_pending
(
struct
xdma_kthread
*
thp
)
{
struct
list_head
*
work_item
,
*
next
;
...
...
@@ -67,7 +66,6 @@ static inline int xthread_work_pending(struct xdma_kthread *thp)
if
(
list_empty
(
&
thp
->
work_list
))
return
0
;
/* any work item has pending work to do? */
list_for_each_safe
(
work_item
,
next
,
&
thp
->
work_list
)
{
if
(
thp
->
fpending
&&
thp
->
fpending
(
work_item
))
...
...
@@ -101,7 +99,6 @@ static int xthread_main(void *data)
if
(
thp
->
finit
)
thp
->
finit
(
thp
);
while
(
!
kthread_should_stop
())
{
struct
list_head
*
work_item
,
*
next
;
...
...
@@ -150,8 +147,10 @@ int xdma_kthread_start(struct xdma_kthread *thp, char *name, int id)
}
len
=
snprintf
(
thp
->
name
,
sizeof
(
thp
->
name
),
"%s%d"
,
name
,
id
);
if
(
len
<
0
)
if
(
len
<
0
)
{
pr_err
(
"thread %d, error in snprintf name %s.
\n
"
,
id
,
name
);
return
-
EINVAL
;
}
thp
->
id
=
id
;
...
...
@@ -180,7 +179,6 @@ int xdma_kthread_start(struct xdma_kthread *thp, char *name, int id)
return
0
;
}
int
xdma_kthread_stop
(
struct
xdma_kthread
*
thp
)
{
int
rv
;
...
...
@@ -234,8 +232,6 @@ void xdma_thread_remove_work(struct xdma_engine *engine)
cmpl_thread
->
work_cnt
--
;
unlock_thread
(
cmpl_thread
);
}
}
void
xdma_thread_add_work
(
struct
xdma_engine
*
engine
)
...
...
@@ -275,7 +271,6 @@ void xdma_thread_add_work(struct xdma_engine *engine)
spin_lock_irqsave
(
&
engine
->
lock
,
flags
);
engine
->
cmplthp
=
thp
;
spin_unlock_irqrestore
(
&
engine
->
lock
,
flags
);
}
int
xdma_threads_create
(
unsigned
int
num_threads
)
...
...
@@ -289,12 +284,12 @@ int xdma_threads_create(unsigned int num_threads)
return
0
;
}
pr_info
(
"xdma_threads_create
\n
"
);
cs_threads
=
kzalloc
(
num_threads
*
sizeof
(
struct
xdma_kthread
),
GFP_KERNEL
);
if
(
!
cs_threads
)
if
(
!
cs_threads
)
{
pr_err
(
"OOM, # threads %u.
\n
"
,
num_threads
);
return
-
ENOMEM
;
}
/* N dma writeback monitoring threads */
thp
=
cs_threads
;
...
...
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