diff options
Diffstat (limited to 'pcitool/cli.c')
-rw-r--r-- | pcitool/cli.c | 177 |
1 files changed, 166 insertions, 11 deletions
diff --git a/pcitool/cli.c b/pcitool/cli.c index 9eeb046..5df175d 100644 --- a/pcitool/cli.c +++ b/pcitool/cli.c @@ -1,3 +1,4 @@ +#define _XOPEN_SOURCE 700 #define _POSIX_C_SOURCE 200112L #define _BSD_SOURCE @@ -37,6 +38,7 @@ #include "error.h" #include "debug.h" #include "model.h" +#include "locking.h" /* defines */ #define MAX_KBUF 14 @@ -89,7 +91,11 @@ typedef enum { MODE_ALLOC_KMEM, MODE_LIST_KMEM, MODE_READ_KMEM, - MODE_FREE_KMEM + MODE_FREE_KMEM, + MODE_LIST_LOCKS, + MODE_FREE_LOCKS, + MODE_LOCK, + MODE_UNLOCK } MODE; typedef enum { @@ -160,6 +166,10 @@ typedef enum { OPT_LIST_KMEM, OPT_FREE_KMEM, OPT_READ_KMEM, + OPT_LIST_LOCKS, + OPT_FREE_LOCKS, + OPT_LOCK, + OPT_UNLOCK, OPT_BLOCK_SIZE, OPT_ALIGNMENT, OPT_TYPE, @@ -209,6 +219,10 @@ static struct option long_options[] = { {"read-kernel-memory", required_argument, 0, OPT_READ_KMEM }, {"alloc-kernel-memory", required_argument, 0, OPT_ALLOC_KMEM }, {"free-kernel-memory", required_argument, 0, OPT_FREE_KMEM }, + {"list-locks", no_argument, 0, OPT_LIST_LOCKS }, + {"free-locks", no_argument, 0, OPT_FREE_LOCKS }, + {"lock", required_argument, 0, OPT_LOCK }, + {"unlock", required_argument, 0, OPT_UNLOCK }, {"type", required_argument, 0, OPT_TYPE }, {"block-size", required_argument, 0, OPT_BLOCK_SIZE }, {"alignment", required_argument, 0, OPT_ALIGNMENT }, @@ -275,6 +289,11 @@ void Usage(int argc, char *argv[], const char *format, ...) { " dma - Remove all buffers allocated by DMA subsystem\n" " #number - Remove all buffers with the specified use id\n" "\n" +" --list-locks - List all registered locks\n" +" --free-locks - Destroy all locks (DANGEROUS)\n" +" --lock <lock name> - Obtain persistent lock\n" +" --unlock <lock name> - Release persistent lock\n" +"\n" " Addressing:\n" " -d <device> - FPGA device (/dev/fpga0)\n" " -m <model> - Memory model (autodetected)\n" @@ -1939,7 +1958,7 @@ size_t FindUse(size_t *n_uses, kmem_use_info_t *uses, pcilib_kmem_use_t use) { if (n == MAX_USES) return 0; - memset(&uses[n], 0, sizeof(pcilib_kmem_use_t)); + memset(&uses[n], 0, sizeof(kmem_use_info_t)); uses[n].use = use; return (*n_uses)++; } @@ -2029,6 +2048,8 @@ int ListKMEM(pcilib_t *handle, const char *device) { size_t i, useid, n_uses; kmem_use_info_t uses[MAX_USES]; + const pcilib_model_description_t *model_info = pcilib_get_model_description(handle); + err = ParseKMEM(handle, device, &n_uses, uses); if (err) Error("Failed to parse kernel memory information provided through sysfs"); @@ -2036,7 +2057,7 @@ int ListKMEM(pcilib_t *handle, const char *device) { printf("No kernel memory is allocated\n"); return 0; } - + printf("Use Type Count Total Size REF Mode \n"); printf("--------------------------------------------------------------------------------\n"); for (useid = 0; useid < n_uses; useid++) { @@ -2046,17 +2067,39 @@ int ListKMEM(pcilib_t *handle, const char *device) { } else i = useid + 1; printf("%08x ", 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 if ((uses[i].use >> 16) == PCILIB_KMEM_USE_USER) printf("User %04x ", uses[i].use&0xFFFF); - else printf (" "); + if (i) { + switch(PCILIB_KMEM_USE_TYPE(uses[i].use)) { + case PCILIB_KMEM_USE_DMA_RING: + printf("DMA%u %s Ring ", uses[i].use&0x7F, ((uses[i].use&0x80)?"S2C":"C2S")); + break; + case PCILIB_KMEM_USE_DMA_PAGES: + printf("DMA%u %s Pages ", uses[i].use&0x7F, ((uses[i].use&0x80)?"S2C":"C2S")); + break; + case PCILIB_KMEM_USE_SOFTWARE_REGISTERS: { + pcilib_register_bank_t bank = pcilib_find_register_bank_by_addr(handle, PCILIB_KMEM_USE_SUBTYPE(uses[i].use)); + if (bank == PCILIB_REGISTER_BANK_INVALID) + printf("SoftRegs (%8u)", PCILIB_KMEM_USE_SUBTYPE(uses[i].use)); + else + printf("SoftRegs (%8s)", model_info->banks[bank].name); + break; + } + case PCILIB_KMEM_USE_LOCKS: + printf("Locks "); + break; + case PCILIB_KMEM_USE_USER: + printf("User %04x ", uses[i].use&0xFFFF); + break; + default: + printf (" "); + } + } else printf("All Others "); + printf(" "); printf("%6zu", uses[i].count); printf(" "); printf("%10s", GetPrintSize(stmp, uses[i].size)); printf(" "); - if (uses[i].referenced&&uses[i].hw_lock) printf("HW+SW"); + 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(" - "); @@ -2396,6 +2439,88 @@ int ReadBuffer(pcilib_t *handle, const char *device, const pcilib_model_descript return ReadKMEM(handle, device, ((dma&0x7F)|((dma_direction == PCILIB_DMA_TO_DEVICE)?0x80:0x00))|(PCILIB_KMEM_USE_DMA_PAGES<<16), block, size, o); } +int ListLocks(pcilib_t *ctx, int verbose) { + int err; + pcilib_lock_id_t i; + + if (verbose) + printf("ID Refs Flags Locked Name\n"); + else + printf("ID Refs Flags Name\n"); + printf("--------------------------------------------------------------------------------\n"); + + for (i = 0; i < PCILIB_MAX_LOCKS; i++) { + pcilib_lock_t *lock = pcilib_get_lock_by_id(ctx, i); + const char *name = pcilib_lock_get_name(lock); + if (!name) break; + + pcilib_lock_flags_t flags = pcilib_lock_get_flags(lock); + size_t refs = pcilib_lock_get_refs(lock); + + printf("%4u %4zu ", i, refs); + + if (flags&PCILIB_LOCK_FLAG_PERSISTENT) printf("P"); + else printf(" "); + printf(" "); + + if (verbose) { + err = pcilib_lock_custom(lock, PCILIB_LOCK_FLAGS_DEFAULT, PCILIB_TIMEOUT_IMMEDIATE); + switch (err) { + case 0: + pcilib_unlock(lock); + printf("No "); + break; + case PCILIB_ERROR_TIMEOUT: + printf("Yes "); + break; + default: + printf("Error "); + } + } + printf("%s\n", name); + } + printf("--------------------------------------------------------------------------------\n"); + printf("P - Persistent\n"); + + return 0; +} + +int FreeLocks(pcilib_t *handle, int force) { + return pcilib_destroy_all_locks(handle, force); +} + +int LockUnlock(pcilib_t *handle, const char *name, int do_lock, pcilib_timeout_t timeout) { + int err = 0; + + pcilib_lock_t *lock = pcilib_get_lock(handle, PCILIB_LOCK_FLAG_PERSISTENT, name); + if (!lock) Error("Error getting persistent lock %s", name); + + if (do_lock) + err = pcilib_lock_custom(lock, PCILIB_LOCK_FLAGS_DEFAULT, timeout); + else + pcilib_unlock(lock); + + if (err) { + pcilib_return_lock(handle, PCILIB_LOCK_FLAGS_DEFAULT, lock); + switch (err) { + case PCILIB_ERROR_TIMEOUT: + printf("Timeout locking %s\n", name); + break; + default: + Error("Error (%i) locking %s", err, name); + } + } else if (do_lock) { + pcilib_lock_ref(lock); + pcilib_return_lock(handle, PCILIB_LOCK_FLAGS_DEFAULT, lock); + printf("%s is locked\n", name); + } else { + pcilib_lock_unref(lock); + pcilib_return_lock(handle, PCILIB_LOCK_FLAGS_DEFAULT, lock); + } + + return err; +} + int EnableIRQ(pcilib_t *handle, const pcilib_model_description_t *model_info, pcilib_irq_type_t irq_type) { int err; @@ -2483,6 +2608,7 @@ int main(int argc, char **argv) { const char *data_type = NULL; const char *dma_channel = NULL; const char *use = NULL; + const char *lock = NULL; size_t block = (size_t)-1; pcilib_irq_type_t irq_type = PCILIB_IRQ_TYPE_ALL; pcilib_irq_hw_source_t irq_source = PCILIB_IRQ_SOURCE_DEFAULT; @@ -2689,7 +2815,6 @@ int main(int argc, char **argv) { case OPT_LIST_KMEM: if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); mode = MODE_LIST_KMEM; - if (!model) model = "pci"; if (optarg) use = optarg; else if ((optind < argc)&&(argv[optind][0] != '-')) use = argv[optind++]; @@ -2739,6 +2864,25 @@ int main(int argc, char **argv) { if (optarg) use = optarg; else if ((optind < argc)&&(argv[optind][0] != '-')) use = argv[optind++]; break; + case OPT_LIST_LOCKS: + if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); + mode = MODE_LIST_LOCKS; + break; + case OPT_FREE_LOCKS: + if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); + mode = MODE_FREE_LOCKS; + model = "maintenance"; + break; + case OPT_LOCK: + if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); + mode = MODE_LOCK; + lock = optarg; + break; + case OPT_UNLOCK: + if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); + mode = MODE_UNLOCK; + lock = optarg; + break; case OPT_DEVICE: fpga_device = optarg; break; @@ -2949,7 +3093,6 @@ int main(int argc, char **argv) { model_info = pcilib_get_model_description(handle); dma_info = pcilib_get_dma_description(handle); - switch (mode) { case MODE_WRITE: if (((argc - optind) == 1)&&(*argv[optind] == '*')) { @@ -3214,6 +3357,18 @@ int main(int argc, char **argv) { case MODE_FREE_KMEM: FreeKMEM(handle, fpga_device, use, force); break; + case MODE_LIST_LOCKS: + ListLocks(handle, verbose); + break; + case MODE_FREE_LOCKS: + FreeLocks(handle, force); + break; + case MODE_LOCK: + LockUnlock(handle, lock, 1, timeout_set?timeout:PCILIB_TIMEOUT_INFINITE); + break; + case MODE_UNLOCK: + LockUnlock(handle, lock, 0, timeout_set?timeout:PCILIB_TIMEOUT_INFINITE); + break; case MODE_INVALID: break; } |