diff options
author | root <root@iss-tomyspiel-1> | 2011-10-21 02:37:19 +0200 |
---|---|---|
committer | root <root@iss-tomyspiel-1> | 2011-10-21 02:37:19 +0200 |
commit | 33fb2003ef2e359f472dc153a7c2e700cdff2922 (patch) | |
tree | 102b48849f6b3a1486ac5ec5bbb305a8c8d274a1 | |
parent | 64e0f2948b71d37e8cdb99693a00b3f440565953 (diff) | |
download | pcitool-33fb2003ef2e359f472dc153a7c2e700cdff2922.tar.gz pcitool-33fb2003ef2e359f472dc153a7c2e700cdff2922.tar.bz2 pcitool-33fb2003ef2e359f472dc153a7c2e700cdff2922.tar.xz pcitool-33fb2003ef2e359f472dc153a7c2e700cdff2922.zip |
Support exporting data from kernel buffers
-rw-r--r-- | cli.c | 77 | ||||
-rw-r--r-- | driver/common.h | 1 | ||||
-rw-r--r-- | driver/kmem.c | 36 | ||||
-rw-r--r-- | driver/pciDriver.h | 1 | ||||
-rw-r--r-- | driver/sysfs.c | 5 | ||||
-rw-r--r-- | kmem.c | 9 | ||||
-rw-r--r-- | kmem.h | 3 |
7 files changed, 106 insertions, 26 deletions
@@ -60,6 +60,7 @@ typedef enum { MODE_STOP_DMA, MODE_WAIT_IRQ, MODE_LIST_KMEM, + MODE_READ_KMEM, MODE_FREE_KMEM } MODE; @@ -79,8 +80,8 @@ typedef enum { OPT_OUTPUT = 'o', OPT_TIMEOUT = 't', OPT_INFO = 'i', - OPT_BENCHMARK = 'p', OPT_LIST = 'l', + OPT_BENCHMARK = 'p', OPT_READ = 'r', OPT_WRITE = 'w', OPT_GRAB = 'g', @@ -92,6 +93,7 @@ typedef enum { OPT_ITERATIONS, OPT_LIST_KMEM, OPT_FREE_KMEM, + OPT_READ_KMEM, OPT_FORCE, OPT_HELP = 'h', } OPTIONS; @@ -117,6 +119,7 @@ static struct option long_options[] = { {"stop-dma", optional_argument, 0, OPT_STOP_DMA }, {"wait-irq", optional_argument, 0, OPT_WAIT_IRQ }, {"list-kernel-memory", no_argument, 0, OPT_LIST_KMEM }, + {"read-kernel-memory", required_argument, 0, OPT_READ_KMEM }, {"free-kernel-memory", required_argument, 0, OPT_FREE_KMEM }, {"quiete", no_argument, 0, OPT_QUIETE }, {"force", no_argument, 0, OPT_FORCE }, @@ -159,6 +162,8 @@ void Usage(int argc, char *argv[], const char *format, ...) { "\n" " Kernel Modes:\n" " --list-kernel-memory - List kernel buffers\n" +" --read-kernel-memory <blk> - Read the specified block of the kernel memory,\n" +" block is specified as: use:block_number\n" " --free-kernel-memory <use> - Cleans lost kernel space buffers (DANGEROUS)\n" " dma - Remove all buffers allocated by DMA subsystem\n" " #number - Remove all buffers with the specified use id\n" @@ -1085,7 +1090,7 @@ int ListKMEM(pcilib_t *handle, const char *device) { return 0; } - printf("Use Type Count Total Size REF Mode \n"); + printf("Use Type Count Total Size REF Mode \n"); printf("--------------------------------------------------------------------------------\n"); for (useid = 0; useid < n_uses; useid++) { if (useid + 1 == n_uses) { @@ -1093,20 +1098,21 @@ int ListKMEM(pcilib_t *handle, const char *device) { i = 0; } else i = useid + 1; - if (!i) printf("0x%08lx Others", 0); - else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_RING) printf("DMA%u %s Ring ", uses[i].use&0x7F, ((uses[i].use&0x80)?"C2S":"S2C")); - else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_PAGES) printf("DMA%u %s Pages ", uses[i].use&0x7F, ((uses[i].use&0x80)?"C2S":"S2C")); - else printf("0x%08lx ", uses[i].use); - printf(" "); - printf("% 9lu", uses[i].count); + printf("%08lx ", uses[i].use); + if (!i) printf("All Others "); + else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_RING) printf("DMA%u %s Ring ", uses[i].use&0x7F, ((uses[i].use&0x80)?"S2C":"C2S")); + else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_PAGES) printf("DMA%u %s Pages ", uses[i].use&0x7F, ((uses[i].use&0x80)?"S2C":"C2S")); + else printf (" ", uses[i].use); + printf(" "); + printf("% 6lu", uses[i].count); printf(" "); - printf("% 12s", PrintSize(stmp, uses[i].size)); - printf(" "); + printf("% 10s", PrintSize(stmp, uses[i].size)); + printf(" "); if (uses[i].referenced&&uses[i].hw_lock) printf("HW+SW"); else if (uses[i].referenced) printf(" SW"); else if (uses[i].hw_lock) printf("HW "); else printf(" - "); - printf(" "); + printf(" "); if (uses[i].persistent) printf("Persistent"); else if (uses[i].open) printf("Open "); else if (uses[i].reusable) printf("Reusable "); @@ -1120,6 +1126,28 @@ int ListKMEM(pcilib_t *handle, const char *device) { return 0; } +int ReadKMEM(pcilib_t *handle, const char *device, pcilib_kmem_use_t use, size_t block, FILE *o) { + void *data; + size_t size; + pcilib_kmem_handle_t *kbuf; + + kbuf = pcilib_alloc_kernel_memory(handle, 0, block + 1, 0, 0, use, PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_TRY); + if (!kbuf) { + printf("The specified kernel buffer is not allocated\n"); + return 0; + } + + data = pcilib_kmem_get_block_ua(handle, kbuf, block); + if (data) { + size = pcilib_kmem_get_block_size(handle, kbuf, block); + fwrite(data, 1, size, o?o:stdout); + } else { + printf("The specified block is not existing\n"); + } + + pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE); +} + int FreeKMEM(pcilib_t *handle, const char *device, const char *use, int force) { int err; int i; @@ -1172,6 +1200,7 @@ int WaitIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq int main(int argc, char **argv) { int i; long itmp; + unsigned long utmp; unsigned char c; const char *num_offset; @@ -1194,6 +1223,8 @@ int main(int argc, char **argv) { const char *event = NULL; const char *dma_channel = NULL; const char *use = NULL; + pcilib_kmem_use_t use_id; + size_t block = 0; pcilib_irq_hw_source_t irq_source; pcilib_dma_direction_t dma_direction = PCILIB_DMA_BIDIRECTIONAL; @@ -1294,6 +1325,27 @@ int main(int argc, char **argv) { if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); mode = MODE_LIST_KMEM; break; + case OPT_READ_KMEM: + if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); + mode = MODE_READ_KMEM; + + num_offset = strchr(optarg, ':'); + + if (num_offset) { + if (sscanf(num_offset + 1, "%zu", &block) != 1) + Usage(argc, argv, "Invalid block number is specified (%s)", num_offset + 1); + + *(char*)num_offset = 0; + } + + if (sscanf(optarg, "%lx", &utmp) != 1) + Usage(argc, argv, "Invalid USE number is specified (%s)", optarg); + + if (!utmp) + Usage(argc, argv, "Can't read buffer with the unspecific use (use number is 0)"); + + use_id = utmp; + break; case OPT_FREE_KMEM: if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); mode = MODE_FREE_KMEM; @@ -1570,6 +1622,9 @@ int main(int argc, char **argv) { case MODE_LIST_KMEM: ListKMEM(handle, fpga_device); break; + case MODE_READ_KMEM: + ReadKMEM(handle, fpga_device, use_id, block, ofile); + break; case MODE_FREE_KMEM: FreeKMEM(handle, fpga_device, use, force); break; diff --git a/driver/common.h b/driver/common.h index 5de501c..e6dea5f 100644 --- a/driver/common.h +++ b/driver/common.h @@ -16,6 +16,7 @@ typedef struct { unsigned long cpua; unsigned long size; unsigned long type; + unsigned long align; unsigned long use; unsigned long item; diff --git a/driver/kmem.c b/driver/kmem.c index 274ab9f..afe3889 100644 --- a/driver/kmem.c +++ b/driver/kmem.c @@ -40,28 +40,41 @@ int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han if (kmem_entry) { unsigned long flags = kmem_handle->flags; - if (kmem_handle->type != kmem_entry->type) { - mod_info("Invalid type of reusable kmem_entry\n"); + if (flags&KMEM_FLAG_TRY) { + kmem_handle->type = kmem_entry->type; + kmem_handle->size = kmem_entry->size; + kmem_handle->align = kmem_entry->align; + } else { + if (kmem_handle->type != kmem_entry->type) { + mod_info("Invalid type of reusable kmem_entry\n"); return -EINVAL; - } + } - if (kmem_handle->type == PCILIB_KMEM_TYPE_PAGE) { - kmem_handle->size = kmem_entry->size; - } else if (kmem_handle->size != kmem_entry->size) { + if (kmem_handle->type == PCILIB_KMEM_TYPE_PAGE) { + kmem_handle->size = kmem_entry->size; + } else if (kmem_handle->size != kmem_entry->size) { mod_info("Invalid size of reusable kmem_entry\n"); return -EINVAL; - } - - if (((kmem_entry->mode&KMEM_MODE_EXCLUSIVE)?1:0) != ((flags&KMEM_FLAG_EXCLUSIVE)?1:0)) { + } + + if (kmem_handle->align != kmem_entry->align) { + mod_info("Invalid alignment of reusable kmem_entry\n"); + return -EINVAL; + } + + if (((kmem_entry->mode&KMEM_MODE_EXCLUSIVE)?1:0) != ((flags&KMEM_FLAG_EXCLUSIVE)?1:0)) { mod_info("Invalid mode of reusable kmem_entry\n"); return -EINVAL; + } } + if ((kmem_entry->mode&KMEM_MODE_COUNT)==KMEM_MODE_COUNT) { mod_info("Reuse counter of kmem_entry is overflown"); return -EBUSY; } + kmem_handle->handle_id = kmem_entry->id; kmem_handle->pa = (unsigned long)(kmem_entry->dma_handle); @@ -79,9 +92,11 @@ int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han if (flags&KMEM_FLAG_PERSISTENT) kmem_entry->mode |= KMEM_MODE_PERSISTENT; privdata->kmem_cur_id = kmem_entry->id; - + return 0; } + + if (kmem_handle->flags&KMEM_FLAG_TRY) return -ENOENT; } /* First, allocate zeroed memory for the kmem_entry */ @@ -96,6 +111,7 @@ int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han kmem_entry->use = kmem_handle->use; kmem_entry->item = kmem_handle->item; kmem_entry->type = kmem_handle->type; + kmem_entry->align = kmem_handle->align; /* Initialize sysfs if possible */ if (pcidriver_sysfs_initialize_kmem(privdata, kmem_entry->id, &(kmem_entry->sysfs_attr)) != 0) diff --git a/driver/pciDriver.h b/driver/pciDriver.h index fc92b11..3ffe8b7 100644 --- a/driver/pciDriver.h +++ b/driver/pciDriver.h @@ -106,6 +106,7 @@ #define KMEM_FLAG_HW 8 /**< The buffer may be accessed by hardware, the hardware access will not occur any more if passed to _free function */ #define KMEM_FLAG_FORCE 16 /**< Force memory cleanup even if references are present */ #define KMEM_FLAG_MASS 32 /**< Apply to all buffers of selected use */ +#define KMEM_FLAG_TRY 64 /**< Do not allocate buffers, try to reuse and fail if not possible */ #define KMEM_FLAG_REUSED 1 /**< Indicates if buffer with specified use & item was already allocated and reused */ #define KMEM_FLAG_REUSED_PERSISTENT 4 /**< Indicates that reused buffer was persistent before the call */ diff --git a/driver/sysfs.c b/driver/sysfs.c index 47e4395..b10157b 100644 --- a/driver/sysfs.c +++ b/driver/sysfs.c @@ -101,7 +101,10 @@ static SYSFS_GET_FUNCTION(pcidriver_show_kmem_entry) int id = simple_strtol(attr->attr.name + strlen("kbuf"), NULL, 10); pcidriver_kmem_entry_t *entry = pcidriver_kmem_find_entry_id(privdata, id); if (entry) - return snprintf(buf, PAGE_SIZE, "buffer: %d\ntype: %lu\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\n", id, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode); + if (entry->size >= 16) + return snprintf(buf, PAGE_SIZE, "buffer: %d\ntype: %lu\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\n data: %8x %8x %8x %8x\n", id, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode, *(u32*)(entry->cpua), *(u32*)(entry->cpua + 4), *(u32*)(entry->cpua + 8), *(u32*)(entry->cpua + 12)); + else + return snprintf(buf, PAGE_SIZE, "buffer: %d\ntype: %lu\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\n", id, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode); else return snprintf(buf, PAGE_SIZE, "I am in the kmem_entry show function for buffer %d\n", id); #else @@ -144,9 +144,9 @@ pcilib_kmem_handle_t *pcilib_alloc_kernel_memory(pcilib_t *ctx, pcilib_kmem_type break; } - if ((alignment)&&(type != PCILIB_KMEM_TYPE_PAGE)) { - if (kh.pa % alignment) kbuf->buf.blocks[i].alignment_offset = alignment - kh.pa % alignment; - kbuf->buf.blocks[i].size -= alignment; + if ((kh.align)&&(type != PCILIB_KMEM_TYPE_PAGE)) { + if (kh.pa % kh.align) kbuf->buf.blocks[i].alignment_offset = kh.align - kh.pa % kh.align; + kbuf->buf.blocks[i].size -= kh.align; } addr = mmap( 0, kbuf->buf.blocks[i].size + kbuf->buf.blocks[i].alignment_offset, PROT_WRITE | PROT_READ, MAP_SHARED, ctx->handle, 0 ); @@ -157,6 +157,9 @@ pcilib_kmem_handle_t *pcilib_alloc_kernel_memory(pcilib_t *ctx, pcilib_kmem_type } kbuf->buf.blocks[i].ua = addr; +// if (use == PCILIB_KMEM_USE_DMA_PAGES) { +// memset(addr, 10, kbuf->buf.blocks[i].size + kbuf->buf.blocks[i].alignment_offset); +// } kbuf->buf.blocks[i].mmap_offset = kh.pa & ctx->page_mask; } @@ -9,7 +9,8 @@ typedef enum { PCILIB_KMEM_FLAG_EXCLUSIVE = KMEM_FLAG_EXCLUSIVE, PCILIB_KMEM_FLAG_PERSISTENT = KMEM_FLAG_PERSISTENT, PCILIB_KMEM_FLAG_HARDWARE = KMEM_FLAG_HW, - PCILIB_KMEM_FLAG_FORCE = KMEM_FLAG_FORCE + PCILIB_KMEM_FLAG_FORCE = KMEM_FLAG_FORCE, + PCILIB_KMEM_FLAG_TRY = KMEM_FLAG_TRY } pcilib_kmem_flags_t; |