summaryrefslogtreecommitdiffstats
path: root/pcitool/cli.c
diff options
context:
space:
mode:
Diffstat (limited to 'pcitool/cli.c')
-rw-r--r--pcitool/cli.c177
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;
}