From 6a301ac85a71a4f645c2ce7f72ea594015c41348 Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Thu, 10 Dec 2015 02:05:35 +0000 Subject: [PATCH] ioat(4): Add ioatcontrol(8) testing for copy_8k Add -E ("Eight k") and -m ("Memcpy") modes to the ioatcontrol(8) tool. Prompted by: rpokala Sponsored by: EMC / Isilon Storage Division --- sys/dev/ioat/ioat_test.c | 53 ++++++++++++++++++++++++++++------ sys/dev/ioat/ioat_test.h | 2 ++ tools/tools/ioat/ioatcontrol.8 | 8 ++++- tools/tools/ioat/ioatcontrol.c | 29 +++++++++++++++---- 4 files changed, 77 insertions(+), 15 deletions(-) diff --git a/sys/dev/ioat/ioat_test.c b/sys/dev/ioat/ioat_test.c index a8311abf8a48..f39786e07c4b 100644 --- a/sys/dev/ioat/ioat_test.c +++ b/sys/dev/ioat/ioat_test.c @@ -84,11 +84,17 @@ static inline void _ioat_test_log(int verbosity, const char *fmt, ...); static void ioat_test_transaction_destroy(struct test_transaction *tx) { + struct ioat_test *test; int i; + test = tx->test; + for (i = 0; i < IOAT_MAX_BUFS; i++) { if (tx->buf[i] != NULL) { - contigfree(tx->buf[i], tx->length, M_IOAT_TEST); + if (test->testkind == IOAT_TEST_DMA_8K) + free(tx->buf[i], M_IOAT_TEST); + else + contigfree(tx->buf[i], tx->length, M_IOAT_TEST); tx->buf[i] = NULL; } } @@ -97,8 +103,8 @@ ioat_test_transaction_destroy(struct test_transaction *tx) } static struct -test_transaction *ioat_test_transaction_create(unsigned num_buffers, - uint32_t buffer_size) +test_transaction *ioat_test_transaction_create(struct ioat_test *test, + unsigned num_buffers) { struct test_transaction *tx; unsigned i; @@ -107,11 +113,16 @@ test_transaction *ioat_test_transaction_create(unsigned num_buffers, if (tx == NULL) return (NULL); - tx->length = buffer_size; + tx->length = test->buffer_size; for (i = 0; i < num_buffers; i++) { - tx->buf[i] = contigmalloc(buffer_size, M_IOAT_TEST, M_NOWAIT, - 0, BUS_SPACE_MAXADDR, PAGE_SIZE, 0); + if (test->testkind == IOAT_TEST_DMA_8K) + tx->buf[i] = malloc(test->buffer_size, M_IOAT_TEST, + M_NOWAIT); + else + tx->buf[i] = contigmalloc(test->buffer_size, + M_IOAT_TEST, M_NOWAIT, 0, BUS_SPACE_MAXADDR, + PAGE_SIZE, 0); if (tx->buf[i] == NULL) { ioat_test_transaction_destroy(tx); @@ -197,8 +208,7 @@ ioat_test_prealloc_memory(struct ioat_test *test, int index) struct test_transaction *tx; for (i = 0; i < test->transactions; i++) { - tx = ioat_test_transaction_create(test->chain_depth * 2, - test->buffer_size); + tx = ioat_test_transaction_create(test, test->chain_depth * 2); if (tx == NULL) { ioat_test_log(0, "tx == NULL - memory exhausted\n"); test->status[IOAT_TEST_NO_MEMORY]++; @@ -258,8 +268,16 @@ ioat_test_submit_1_tx(struct ioat_test *test, bus_dmaengine_t dma) TAILQ_INSERT_HEAD(&test->pend_q, tx, entry); IT_UNLOCK(); - ioat_acquire(dma); + if (test->testkind != IOAT_TEST_MEMCPY) + ioat_acquire(dma); for (i = 0; i < tx->depth; i++) { + if (test->testkind == IOAT_TEST_MEMCPY) { + memcpy(tx->buf[2 * i + 1], tx->buf[2 * i], tx->length); + if (i == tx->depth - 1) + ioat_dma_test_callback(tx, 0); + continue; + } + src = vtophys((vm_offset_t)tx->buf[2*i]); dest = vtophys((vm_offset_t)tx->buf[2*i+1]); @@ -286,10 +304,20 @@ ioat_test_submit_1_tx(struct ioat_test *test, bus_dmaengine_t dma) fillpattern = *(uint64_t *)tx->buf[2*i]; desc = ioat_blockfill(dma, dest, fillpattern, tx->length, cb, tx, flags); + } else if (test->testkind == IOAT_TEST_DMA_8K) { + bus_addr_t src2, dst2; + + src2 = vtophys((vm_offset_t)tx->buf[2*i] + PAGE_SIZE); + dst2 = vtophys((vm_offset_t)tx->buf[2*i+1] + PAGE_SIZE); + + desc = ioat_copy_8k_aligned(dma, dest, dst2, src, src2, + cb, tx, flags); } if (desc == NULL) break; } + if (test->testkind == IOAT_TEST_MEMCPY) + return; ioat_release(dma); /* @@ -317,6 +345,13 @@ ioat_dma_test(void *arg) test = arg; memset(__DEVOLATILE(void *, test->status), 0, sizeof(test->status)); + if (test->testkind == IOAT_TEST_DMA_8K && + test->buffer_size != 2 * PAGE_SIZE) { + ioat_test_log(0, "Asked for 8k test and buffer size isn't 8k\n"); + test->status[IOAT_TEST_INVALID_INPUT]++; + return; + } + if (test->buffer_size > 1024 * 1024) { ioat_test_log(0, "Buffer size too large >1MB\n"); test->status[IOAT_TEST_NO_MEMORY]++; diff --git a/sys/dev/ioat/ioat_test.h b/sys/dev/ioat/ioat_test.h index b6e6a15acb9e..4306b3bffff1 100644 --- a/sys/dev/ioat/ioat_test.h +++ b/sys/dev/ioat/ioat_test.h @@ -42,6 +42,8 @@ enum ioat_test_kind { IOAT_TEST_FILL = 0, IOAT_TEST_DMA, IOAT_TEST_RAW_DMA, + IOAT_TEST_DMA_8K, + IOAT_TEST_MEMCPY, IOAT_NUM_TESTKINDS }; diff --git a/tools/tools/ioat/ioatcontrol.8 b/tools/tools/ioat/ioatcontrol.8 index 2306d3876a36..002759fb5be8 100644 --- a/tools/tools/ioat/ioatcontrol.8 +++ b/tools/tools/ioat/ioatcontrol.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 28, 2015 +.Dd December 9, 2015 .Dt IOATCONTROL 8 .Os .Sh NAME @@ -33,7 +33,9 @@ .Xr ioat 4 .Sh SYNOPSIS .Nm +.Op Fl E .Op Fl f +.Op Fl m .Op Fl V .Ar channel_number .Ar num_txns @@ -55,10 +57,14 @@ allows one to issue some number of test operations to the driver on a specific hardware channel. The arguments are as follows: .Bl -tag -width Ds +.It Fl E +Test non-contiguous 8k copy. .It Fl f Test block fill (by default, .Nm tests copy) +.It Fl m +Test memcpy instead of DMA. .It Fl V Verify copies/fills for accuracy .El diff --git a/tools/tools/ioat/ioatcontrol.c b/tools/tools/ioat/ioatcontrol.c index 90255e7c7d25..d40ae1506882 100644 --- a/tools/tools/ioat/ioatcontrol.c +++ b/tools/tools/ioat/ioatcontrol.c @@ -48,7 +48,7 @@ static void usage(void) { - printf("Usage: %s [-fV] [ " + printf("Usage: %s [-E|-f|-m] [-V] [ " "[ [duration]]]\n", getprogname()); printf(" %s -r [-vV] []\n", getprogname()); @@ -97,15 +97,29 @@ main(int argc, char **argv) { struct ioat_test t; int fd, ch; - bool fflag, rflag; + bool fflag, rflag, Eflag, mflag; + unsigned modeflags; - while ((ch = getopt(argc, argv, "rfvVw")) != -1) { + fflag = rflag = Eflag = mflag = false; + modeflags = 0; + + while ((ch = getopt(argc, argv, "EfmrvVw")) != -1) { switch (ch) { + case 'E': + Eflag = true; + modeflags++; + break; case 'f': fflag = true; + modeflags++; + break; + case 'm': + mflag = true; + modeflags++; break; case 'r': rflag = true; + modeflags++; break; case 'v': t.raw_is_virtual = true; @@ -126,8 +140,8 @@ main(int argc, char **argv) if (argc < 2) usage(); - if (rflag && fflag) { - printf("Invalid: -r and -f\n"); + if (modeflags > 1) { + printf("Invalid: Cannot use >1 mode flag (-E, -f, -m, or -r)\n"); usage(); } @@ -139,6 +153,11 @@ main(int argc, char **argv) if (fflag) t.testkind = IOAT_TEST_FILL; + else if (Eflag) { + t.testkind = IOAT_TEST_DMA_8K; + t.buffer_size = 8 * 1024; + } else if (mflag) + t.testkind = IOAT_TEST_MEMCPY; t.channel_index = atoi(argv[0]); if (t.channel_index > 8) {