Commit 2c01de22 authored by Karen Xie's avatar Karen Xie

XDMA v2020.1.08: allow ST c2h to end a dma transfer when EOP is received

parent 7642657b
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 Release: 2019.2
=============== ===============
......
...@@ -40,6 +40,7 @@ static struct option const long_opts[] = { ...@@ -40,6 +40,7 @@ static struct option const long_opts[] = {
{"offset", required_argument, NULL, 'o'}, {"offset", required_argument, NULL, 'o'},
{"count", required_argument, NULL, 'c'}, {"count", required_argument, NULL, 'c'},
{"file", required_argument, NULL, 'f'}, {"file", required_argument, NULL, 'f'},
{"eop_flush", no_argument, NULL, 'e'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{"verbose", no_argument, NULL, 'v'}, {"verbose", no_argument, NULL, 'v'},
{0, 0, 0, 0} {0, 0, 0, 0}
...@@ -48,7 +49,7 @@ static struct option const long_opts[] = { ...@@ -48,7 +49,7 @@ static struct option const long_opts[] = {
static int test_dma(char *devname, uint64_t addr, uint64_t aperture, static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
uint64_t size, uint64_t offset, uint64_t count, uint64_t size, uint64_t offset, uint64_t count,
char *ofname); char *ofname);
static int no_write = 0; static int eop_flush = 0;
static void usage(const char *name) static void usage(const char *name)
{ {
...@@ -80,12 +81,25 @@ 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", " -%c (--%s) file to write the data of the transfers\n",
long_opts[i].val, long_opts[i].name); long_opts[i].val, long_opts[i].name);
i++; 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", fprintf(stdout, " -%c (--%s) print usage help and exit\n",
long_opts[i].val, long_opts[i].name); long_opts[i].val, long_opts[i].name);
i++; i++;
fprintf(stdout, " -%c (--%s) verbose output\n", fprintf(stdout, " -%c (--%s) verbose output\n",
long_opts[i].val, long_opts[i].name); long_opts[i].val, long_opts[i].name);
i++; i++;
fprintf(stdout, "\nReturn 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[]) int main(int argc, char *argv[])
...@@ -99,7 +113,7 @@ int main(int argc, char *argv[]) ...@@ -99,7 +113,7 @@ int main(int argc, char *argv[])
uint64_t count = COUNT_DEFAULT; uint64_t count = COUNT_DEFAULT;
char *ofname = NULL; char *ofname = NULL;
while ((cmd_opt = getopt_long(argc, argv, "vhxc:f:d:a:k:s:o:", long_opts, while ((cmd_opt = getopt_long(argc, argv, "vhec:f:d:a:k:s:o:", long_opts,
NULL)) != -1) { NULL)) != -1) {
switch (cmd_opt) { switch (cmd_opt) {
case 0: case 0:
...@@ -133,12 +147,12 @@ int main(int argc, char *argv[]) ...@@ -133,12 +147,12 @@ int main(int argc, char *argv[])
ofname = strdup(optarg); ofname = strdup(optarg);
break; break;
/* print usage help and exit */ /* print usage help and exit */
case 'x':
no_write++;
break;
case 'v': case 'v':
verbose = 1; verbose = 1;
break; break;
case 'e':
eop_flush = 1;
break;
case 'h': case 'h':
default: default:
usage(argv[0]); usage(argv[0]);
...@@ -159,19 +173,30 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture, ...@@ -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, uint64_t size, uint64_t offset, uint64_t count,
char *ofname) char *ofname)
{ {
ssize_t rc; ssize_t rc = 0;
size_t out_offset = 0;
size_t bytes_done = 0;
uint64_t i; uint64_t i;
uint64_t apt_loop = aperture ? (size + aperture - 1) / aperture : 0; uint64_t apt_loop = aperture ? (size + aperture - 1) / aperture : 0;
char *buffer = NULL; char *buffer = NULL;
char *allocated = NULL; char *allocated = NULL;
struct timespec ts_start, ts_end; struct timespec ts_start, ts_end;
int out_fd = -1; int out_fd = -1;
int fpga_fd = open(devname, O_RDWR | O_NONBLOCK); int fpga_fd;
long total_time = 0; long total_time = 0;
float result; float result;
float avg_time = 0; float avg_time = 0;
int underflow = 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) { if (fpga_fd < 0) {
fprintf(stderr, "unable to open device %s, %d.\n", fprintf(stderr, "unable to open device %s, %d.\n",
devname, fpga_fd); devname, fpga_fd);
...@@ -210,6 +235,7 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture, ...@@ -210,6 +235,7 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
uint64_t len = size; uint64_t len = size;
char *buf = buffer; char *buf = buffer;
bytes_done = 0;
for (j = 0; j < apt_loop; j++, len -= aperture, buf += aperture) { for (j = 0; j < apt_loop; j++, len -= aperture, buf += aperture) {
uint64_t bytes = (len > aperture) ? aperture : len, uint64_t bytes = (len > aperture) ? aperture : len,
rc = read_to_buffer(devname, fpga_fd, buf, rc = read_to_buffer(devname, fpga_fd, buf,
...@@ -219,13 +245,15 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture, ...@@ -219,13 +245,15 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
if (!underflow && rc < bytes) if (!underflow && rc < bytes)
underflow = 1; underflow = 1;
bytes_done += rc;
} }
} else { } else {
rc = read_to_buffer(devname, fpga_fd, buffer, size, addr); rc = read_to_buffer(devname, fpga_fd, buffer, size, addr);
if (rc < 0) if (rc < 0)
goto out; goto out;
bytes_done = rc;
if (!underflow && rc < size) if (!underflow && bytes_done < size)
underflow = 1; underflow = 1;
} }
clock_gettime(CLOCK_MONOTONIC, &ts_end); clock_gettime(CLOCK_MONOTONIC, &ts_end);
...@@ -238,14 +266,15 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture, ...@@ -238,14 +266,15 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
if (verbose) if (verbose)
fprintf(stdout, fprintf(stdout,
"#%lu: CLOCK_MONOTONIC %ld.%09ld sec. read %ld/%ld bytes\n", "#%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? */ /* file argument given? */
if ((out_fd >= 0) & (no_write == 0)) { if (out_fd >= 0) {
rc = write_from_buffer(ofname, out_fd, buffer, rc = write_from_buffer(ofname, out_fd, buffer,
size, i*size); bytes_done, out_offset);
if (rc < 0) if (rc < 0 || rc < bytes_done)
goto out; goto out;
out_offset += bytes_done;
} }
} }
...@@ -256,9 +285,13 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture, ...@@ -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", printf("** Avg time device %s, total time %ld nsec, avg_time = %f, size = %lu, BW = %f \n",
devname, total_time, avg_time, size, result); devname, total_time, avg_time, size, result);
printf("%s ** Average BW = %lu, %f\n", devname, 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: out:
close(fpga_fd); close(fpga_fd);
if (out_fd >= 0) if (out_fd >= 0)
......
...@@ -93,6 +93,10 @@ static void usage(const char *name) ...@@ -93,6 +93,10 @@ static void usage(const char *name)
fprintf(stdout, " -%c (--%s) verbose output\n", fprintf(stdout, " -%c (--%s) verbose output\n",
long_opts[i].val, long_opts[i].name); long_opts[i].val, long_opts[i].name);
i++; i++;
fprintf(stdout, "\nReturn code:\n");
fprintf(stdout, " 0: all bytes were dma'ed successfully\n");
fprintf(stdout, " < 0: error\n\n");
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
...@@ -173,6 +177,8 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture, ...@@ -173,6 +177,8 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
{ {
uint64_t i; uint64_t i;
ssize_t rc; ssize_t rc;
size_t bytes_done = 0;
size_t out_offset = 0;
uint64_t apt_loop = aperture ? (size + aperture - 1) / aperture : 0; uint64_t apt_loop = aperture ? (size + aperture - 1) / aperture : 0;
char *buffer = NULL; char *buffer = NULL;
char *allocated = NULL; char *allocated = NULL;
...@@ -229,7 +235,7 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture, ...@@ -229,7 +235,7 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
if (infile_fd >= 0) { if (infile_fd >= 0) {
rc = read_to_buffer(infname, infile_fd, buffer, size, 0); rc = read_to_buffer(infname, infile_fd, buffer, size, 0);
if (rc < 0) if (rc < 0 || rc < size)
goto out; goto out;
} }
...@@ -242,6 +248,7 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture, ...@@ -242,6 +248,7 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
uint64_t len = size; uint64_t len = size;
char *buf = buffer; char *buf = buffer;
bytes_done = 0;
for (j = 0; j < apt_loop; j++, len -= aperture, for (j = 0; j < apt_loop; j++, len -= aperture,
buf += aperture) { buf += aperture) {
uint64_t bytes = (len > aperture) ? aperture : len, uint64_t bytes = (len > aperture) ? aperture : len,
...@@ -250,6 +257,7 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture, ...@@ -250,6 +257,7 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
if (rc < 0) if (rc < 0)
goto out; goto out;
bytes_done += rc;
if (!underflow && rc < bytes) if (!underflow && rc < bytes)
underflow = 1; underflow = 1;
} }
...@@ -259,7 +267,8 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture, ...@@ -259,7 +267,8 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
if (rc < 0) if (rc < 0)
goto out; goto out;
if (!underflow && rc < size) bytes_done = rc;
if (!underflow && bytes_done < size)
underflow = 1; underflow = 1;
} }
...@@ -275,9 +284,10 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture, ...@@ -275,9 +284,10 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
if (outfile_fd >= 0) { if (outfile_fd >= 0) {
rc = write_from_buffer(ofname, outfile_fd, buffer, rc = write_from_buffer(ofname, outfile_fd, buffer,
size, i * size); bytes_done, out_offset);
if (rc < 0) if (rc < 0 || rc < bytes_done)
goto out; goto out;
out_offset += bytes_done;
} }
} }
...@@ -289,7 +299,6 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture, ...@@ -289,7 +299,6 @@ static int test_dma(char *devname, uint64_t addr, uint64_t aperture,
devname, total_time, avg_time, size, result); devname, total_time, avg_time, size, result);
printf("%s ** Average BW = %lu, %f\n", devname, size, result); printf("%s ** Average BW = %lu, %f\n", devname, size, result);
} }
rc = 0;
out: out:
close(fpga_fd); close(fpga_fd);
...@@ -299,5 +308,8 @@ out: ...@@ -299,5 +308,8 @@ out:
close(outfile_fd); close(outfile_fd);
free(allocated); free(allocated);
return rc; if (rc < 0)
return rc;
/* treat underflow as error */
return underflow ? -EIO : 0;
} }
...@@ -47,6 +47,7 @@ ssize_t read_to_buffer(char *fname, int fd, char *buffer, uint64_t size, ...@@ -47,6 +47,7 @@ ssize_t read_to_buffer(char *fname, int fd, char *buffer, uint64_t size,
uint64_t count = 0; uint64_t count = 0;
char *buf = buffer; char *buf = buffer;
off_t offset = base; off_t offset = base;
int loop = 0;
while (count < size) { while (count < size) {
uint64_t bytes = size - count; uint64_t bytes = size - count;
...@@ -67,7 +68,7 @@ ssize_t read_to_buffer(char *fname, int fd, char *buffer, uint64_t size, ...@@ -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 */ /* read data from file into memory buffer */
rc = read(fd, buf, bytes); rc = read(fd, buf, bytes);
if (rc < 0) { if (rc < 0) {
fprintf(stderr, "%s, read 0x%lx @ 0x%lx failed %d.\n", fprintf(stderr, "%s, read 0x%lx @ 0x%lx failed %ld.\n",
fname, bytes, offset, rc); fname, bytes, offset, rc);
perror("read file"); perror("read file");
return -EIO; return -EIO;
...@@ -75,19 +76,19 @@ ssize_t read_to_buffer(char *fname, int fd, char *buffer, uint64_t size, ...@@ -75,19 +76,19 @@ ssize_t read_to_buffer(char *fname, int fd, char *buffer, uint64_t size,
count += rc; count += rc;
if (rc != bytes) { 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); fname, rc, bytes, offset);
break; break;
} }
buf += bytes; buf += bytes;
offset += bytes; offset += bytes;
} loop++;
}
if (count != size) if (count != size && loop)
fprintf(stderr, "%s, read underflow 0x%lx != 0x%lx.\n", fprintf(stderr, "%s, read underflow 0x%lx/0x%lx.\n",
fname, count, size); fname, count, size);
return count; return count;
} }
...@@ -98,6 +99,7 @@ ssize_t write_from_buffer(char *fname, int fd, char *buffer, uint64_t size, ...@@ -98,6 +99,7 @@ ssize_t write_from_buffer(char *fname, int fd, char *buffer, uint64_t size,
uint64_t count = 0; uint64_t count = 0;
char *buf = buffer; char *buf = buffer;
off_t offset = base; off_t offset = base;
int loop = 0;
while (count < size) { while (count < size) {
uint64_t bytes = size - count; uint64_t bytes = size - count;
...@@ -118,7 +120,7 @@ ssize_t write_from_buffer(char *fname, int fd, char *buffer, uint64_t size, ...@@ -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 */ /* write data to file from memory buffer */
rc = write(fd, buf, bytes); rc = write(fd, buf, bytes);
if (rc < 0) { if (rc < 0) {
fprintf(stderr, "%s, write 0x%lx @ 0x%lx failed %d.\n", fprintf(stderr, "%s, write 0x%lx @ 0x%lx failed %ld.\n",
fname, bytes, offset, rc); fname, bytes, offset, rc);
perror("write file"); perror("write file");
return -EIO; return -EIO;
...@@ -126,16 +128,18 @@ ssize_t write_from_buffer(char *fname, int fd, char *buffer, uint64_t size, ...@@ -126,16 +128,18 @@ ssize_t write_from_buffer(char *fname, int fd, char *buffer, uint64_t size,
count += rc; count += rc;
if (rc != bytes) { 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); fname, rc, bytes, offset);
break; break;
} }
buf += bytes; buf += bytes;
offset += bytes; offset += bytes;
}
if (count != size) loop++;
fprintf(stderr, "%s, write underflow 0x%lx != 0x%lx.\n", }
if (count != size && loop)
fprintf(stderr, "%s, write underflow 0x%lx/0x%lx.\n",
fname, count, size); fname, count, size);
return count; return count;
...@@ -177,4 +181,3 @@ void timespec_sub(struct timespec *t1, struct timespec *t2) ...@@ -177,4 +181,3 @@ void timespec_sub(struct timespec *t1, struct timespec *t2)
t1->tv_nsec += 1000000000; t1->tv_nsec += 1000000000;
} }
} }
...@@ -485,7 +485,6 @@ static ssize_t cdev_aio_write(struct kiocb *iocb, const struct iovec *io, ...@@ -485,7 +485,6 @@ static ssize_t cdev_aio_write(struct kiocb *iocb, const struct iovec *io,
return -EIOCBQUEUED; return -EIOCBQUEUED;
} }
static ssize_t cdev_aio_read(struct kiocb *iocb, const struct iovec *io, static ssize_t cdev_aio_read(struct kiocb *iocb, const struct iovec *io,
unsigned long count, loff_t pos) unsigned long count, loff_t pos)
{ {
...@@ -790,6 +789,8 @@ static int char_sgdma_open(struct inode *inode, struct file *file) ...@@ -790,6 +789,8 @@ static int char_sgdma_open(struct inode *inode, struct file *file)
if (engine->device_open == 1) if (engine->device_open == 1)
return -EBUSY; return -EBUSY;
engine->device_open = 1; engine->device_open = 1;
engine->eop_flush = (file->f_flags & O_TRUNC) ? 1 : 0;
} }
return 0; return 0;
......
This diff is collapsed.
...@@ -431,6 +431,8 @@ struct sw_desc { ...@@ -431,6 +431,8 @@ struct sw_desc {
}; };
/* Describes a (SG DMA) single transfer for the engine */ /* 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 xdma_transfer {
struct list_head entry; /* queue of non-completed transfers */ struct list_head entry; /* queue of non-completed transfers */
struct xdma_desc *desc_virt; /* virt addr of the 1st descriptor */ struct xdma_desc *desc_virt; /* virt addr of the 1st descriptor */
...@@ -440,6 +442,8 @@ struct xdma_transfer { ...@@ -440,6 +442,8 @@ struct xdma_transfer {
int desc_adjacent; /* adjacent descriptors at desc_bus */ int desc_adjacent; /* adjacent descriptors at desc_bus */
int desc_num; /* number of descriptors in transfer */ int desc_num; /* number of descriptors in transfer */
int desc_index; /* index for 1st desc. 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; enum dma_data_direction dir;
#if HAS_SWAKE_UP #if HAS_SWAKE_UP
struct swait_queue_head wq; struct swait_queue_head wq;
...@@ -449,7 +453,6 @@ struct xdma_transfer { ...@@ -449,7 +453,6 @@ struct xdma_transfer {
enum transfer_state state; /* state of the transfer */ enum transfer_state state; /* state of the transfer */
unsigned int flags; unsigned int flags;
#define XFER_FLAG_NEED_UNMAP 0x1
int cyclic; /* flag if transfer is cyclic */ int cyclic; /* flag if transfer is cyclic */
int last_in_request; /* flag if last within request */ int last_in_request; /* flag if last within request */
unsigned int len; unsigned int len;
...@@ -477,8 +480,6 @@ struct xdma_engine { ...@@ -477,8 +480,6 @@ struct xdma_engine {
struct xdma_dev *xdev; /* parent device */ struct xdma_dev *xdev; /* parent device */
char name[16]; /* name of this engine */ char name[16]; /* name of this engine */
int version; /* version 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 */ /* HW register address offsets */
struct engine_regs *regs; /* Control reg BAR offset */ struct engine_regs *regs; /* Control reg BAR offset */
...@@ -488,14 +489,17 @@ struct xdma_engine { ...@@ -488,14 +489,17 @@ struct xdma_engine {
/* Engine state, configuration and flags */ /* Engine state, configuration and flags */
enum shutdown_state shutdown; /* engine shutdown mode */ enum shutdown_state shutdown; /* engine shutdown mode */
enum dma_data_direction dir; enum dma_data_direction dir;
int device_open; /* flag if engine node open, ST mode only */ u8 addr_align; /* source/dest alignment in bytes */
int running; /* flag if the driver started engine */ u8 len_granularity; /* transfer length multiple */
int non_incr_addr; /* flag if non-incremental addressing used */ u8 addr_bits; /* HW datapath address width */
int streaming; u8 channel:2; /* engine indices */
int addr_align; /* source/dest alignment in bytes */ u8 streaming:1;
int len_granularity; /* transfer length multiple */ u8 device_open:1; /* flag if engine node open, ST mode only */
int addr_bits; /* HW datapath address width */ u8 running:1; /* flag if the driver started engine */
int channel; /* engine indices */ 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 max_extra_adj; /* descriptor prefetch capability */
int desc_dequeued; /* num descriptors of completed transfers */ int desc_dequeued; /* num descriptors of completed transfers */
u32 status; /* last known status of device */ u32 status; /* last known status of device */
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#define DRV_MOD_MAJOR 2020 #define DRV_MOD_MAJOR 2020
#define DRV_MOD_MINOR 1 #define DRV_MOD_MINOR 1
#define DRV_MOD_PATCHLEVEL 07 #define DRV_MOD_PATCHLEVEL 08
#define DRV_MODULE_VERSION \ #define DRV_MODULE_VERSION \
__stringify(DRV_MOD_MAJOR) "." \ __stringify(DRV_MOD_MAJOR) "." \
......
...@@ -619,8 +619,6 @@ int xdma_cdev_init(void) ...@@ -619,8 +619,6 @@ int xdma_cdev_init(void)
return -ENOMEM; return -ENOMEM;
} }
xdma_threads_create(num_online_cpus());
return 0; return 0;
} }
...@@ -631,6 +629,4 @@ void xdma_cdev_cleanup(void) ...@@ -631,6 +629,4 @@ void xdma_cdev_cleanup(void)
if (g_xdma_class) if (g_xdma_class)
class_destroy(g_xdma_class); class_destroy(g_xdma_class);
xdma_threads_destroy();
} }
...@@ -39,7 +39,7 @@ static int xdma_thread_cmpl_status_pend(struct list_head *work_item) ...@@ -39,7 +39,7 @@ static int xdma_thread_cmpl_status_pend(struct list_head *work_item)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&engine->lock, 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); spin_unlock_irqrestore(&engine->lock, flags);
return pend; return pend;
...@@ -53,12 +53,11 @@ static int xdma_thread_cmpl_status_proc(struct list_head *work_item) ...@@ -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); engine = list_entry(work_item, struct xdma_engine, cmplthp_list);
transfer = list_entry(engine->transfer_list.next, struct xdma_transfer, transfer = list_entry(engine->transfer_list.next, struct xdma_transfer,
entry); entry);
engine_service_poll(engine, transfer->desc_num); if (transfer)
engine_service_poll(engine, transfer->desc_cmpl_th);
return 0; return 0;
} }
static inline int xthread_work_pending(struct xdma_kthread *thp) static inline int xthread_work_pending(struct xdma_kthread *thp)
{ {
struct list_head *work_item, *next; struct list_head *work_item, *next;
...@@ -67,7 +66,6 @@ static inline int xthread_work_pending(struct xdma_kthread *thp) ...@@ -67,7 +66,6 @@ static inline int xthread_work_pending(struct xdma_kthread *thp)
if (list_empty(&thp->work_list)) if (list_empty(&thp->work_list))
return 0; return 0;
/* any work item has pending work to do? */ /* any work item has pending work to do? */
list_for_each_safe(work_item, next, &thp->work_list) { list_for_each_safe(work_item, next, &thp->work_list) {
if (thp->fpending && thp->fpending(work_item)) if (thp->fpending && thp->fpending(work_item))
...@@ -101,7 +99,6 @@ static int xthread_main(void *data) ...@@ -101,7 +99,6 @@ static int xthread_main(void *data)
if (thp->finit) if (thp->finit)
thp->finit(thp); thp->finit(thp);
while (!kthread_should_stop()) { while (!kthread_should_stop()) {
struct list_head *work_item, *next; struct list_head *work_item, *next;
...@@ -150,8 +147,10 @@ int xdma_kthread_start(struct xdma_kthread *thp, char *name, int id) ...@@ -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); 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; return -EINVAL;
}
thp->id = id; thp->id = id;
...@@ -180,7 +179,6 @@ int xdma_kthread_start(struct xdma_kthread *thp, char *name, int id) ...@@ -180,7 +179,6 @@ int xdma_kthread_start(struct xdma_kthread *thp, char *name, int id)
return 0; return 0;
} }
int xdma_kthread_stop(struct xdma_kthread *thp) int xdma_kthread_stop(struct xdma_kthread *thp)
{ {
int rv; int rv;
...@@ -234,8 +232,6 @@ void xdma_thread_remove_work(struct xdma_engine *engine) ...@@ -234,8 +232,6 @@ void xdma_thread_remove_work(struct xdma_engine *engine)
cmpl_thread->work_cnt--; cmpl_thread->work_cnt--;
unlock_thread(cmpl_thread); unlock_thread(cmpl_thread);
} }
} }
void xdma_thread_add_work(struct xdma_engine *engine) void xdma_thread_add_work(struct xdma_engine *engine)
...@@ -275,7 +271,6 @@ 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); spin_lock_irqsave(&engine->lock, flags);
engine->cmplthp = thp; engine->cmplthp = thp;
spin_unlock_irqrestore(&engine->lock, flags); spin_unlock_irqrestore(&engine->lock, flags);
} }
int xdma_threads_create(unsigned int num_threads) int xdma_threads_create(unsigned int num_threads)
...@@ -289,12 +284,12 @@ int xdma_threads_create(unsigned int num_threads) ...@@ -289,12 +284,12 @@ int xdma_threads_create(unsigned int num_threads)
return 0; return 0;
} }
pr_info("xdma_threads_create\n");
cs_threads = kzalloc(num_threads * sizeof(struct xdma_kthread), cs_threads = kzalloc(num_threads * sizeof(struct xdma_kthread),
GFP_KERNEL); GFP_KERNEL);
if (!cs_threads) if (!cs_threads) {
pr_err("OOM, # threads %u.\n", num_threads);
return -ENOMEM; return -ENOMEM;
}
/* N dma writeback monitoring threads */ /* N dma writeback monitoring threads */
thp = cs_threads; thp = cs_threads;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment