ioatcontrol(8): Add support for interrupt coalescing
The new flag, -c <period>, sets the interrupt coalescing period in microseconds through the new ioat(4) API ioat_set_interrupt_coalesce(). Also add a -z flag to zero ioat statistics before tests, to make it easy to measure results. Sponsored by: EMC / Isilon Storage Division
This commit is contained in:
parent
5ca9fc2a8d
commit
d37872da34
@ -337,10 +337,11 @@ ioat_test_submit_1_tx(struct ioat_test *test, bus_dmaengine_t dma)
|
|||||||
static void
|
static void
|
||||||
ioat_dma_test(void *arg)
|
ioat_dma_test(void *arg)
|
||||||
{
|
{
|
||||||
|
struct ioat_softc *ioat;
|
||||||
struct ioat_test *test;
|
struct ioat_test *test;
|
||||||
bus_dmaengine_t dmaengine;
|
bus_dmaengine_t dmaengine;
|
||||||
uint32_t loops;
|
uint32_t loops;
|
||||||
int index, rc, start, end;
|
int index, rc, start, end, error;
|
||||||
|
|
||||||
test = arg;
|
test = arg;
|
||||||
memset(__DEVOLATILE(void *, test->status), 0, sizeof(test->status));
|
memset(__DEVOLATILE(void *, test->status), 0, sizeof(test->status));
|
||||||
@ -393,9 +394,10 @@ ioat_dma_test(void *arg)
|
|||||||
test->status[IOAT_TEST_NO_DMA_ENGINE]++;
|
test->status[IOAT_TEST_NO_DMA_ENGINE]++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ioat = to_ioat_softc(dmaengine);
|
||||||
|
|
||||||
if (test->testkind == IOAT_TEST_FILL &&
|
if (test->testkind == IOAT_TEST_FILL &&
|
||||||
(to_ioat_softc(dmaengine)->capabilities & IOAT_DMACAP_BFILL) == 0)
|
(ioat->capabilities & IOAT_DMACAP_BFILL) == 0)
|
||||||
{
|
{
|
||||||
ioat_test_log(0,
|
ioat_test_log(0,
|
||||||
"Hardware doesn't support block fill, aborting test\n");
|
"Hardware doesn't support block fill, aborting test\n");
|
||||||
@ -403,6 +405,25 @@ ioat_dma_test(void *arg)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (test->coalesce_period > ioat->intrdelay_max) {
|
||||||
|
ioat_test_log(0,
|
||||||
|
"Hardware doesn't support intrdelay of %u us.\n",
|
||||||
|
(unsigned)test->coalesce_period);
|
||||||
|
test->status[IOAT_TEST_INVALID_INPUT]++;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
error = ioat_set_interrupt_coalesce(dmaengine, test->coalesce_period);
|
||||||
|
if (error == ENODEV && test->coalesce_period == 0)
|
||||||
|
error = 0;
|
||||||
|
if (error != 0) {
|
||||||
|
ioat_test_log(0, "ioat_set_interrupt_coalesce: %d\n", error);
|
||||||
|
test->status[IOAT_TEST_INVALID_INPUT]++;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test->zero_stats)
|
||||||
|
memset(&ioat->stats, 0, sizeof(ioat->stats));
|
||||||
|
|
||||||
if (test->testkind == IOAT_TEST_RAW_DMA) {
|
if (test->testkind == IOAT_TEST_RAW_DMA) {
|
||||||
if (test->raw_is_virtual) {
|
if (test->raw_is_virtual) {
|
||||||
test->raw_vtarget = (void *)test->raw_target;
|
test->raw_vtarget = (void *)test->raw_target;
|
||||||
|
@ -75,6 +75,10 @@ struct ioat_test {
|
|||||||
bool raw_write;
|
bool raw_write;
|
||||||
bool raw_is_virtual;
|
bool raw_is_virtual;
|
||||||
|
|
||||||
|
bool zero_stats;
|
||||||
|
/* Configure coalesce period */
|
||||||
|
uint16_t coalesce_period;
|
||||||
|
|
||||||
/* Internal usage -- not test inputs */
|
/* Internal usage -- not test inputs */
|
||||||
TAILQ_HEAD(, test_transaction) free_q;
|
TAILQ_HEAD(, test_transaction) free_q;
|
||||||
TAILQ_HEAD(, test_transaction) pend_q;
|
TAILQ_HEAD(, test_transaction) pend_q;
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd December 9, 2015
|
.Dd December 14, 2015
|
||||||
.Dt IOATCONTROL 8
|
.Dt IOATCONTROL 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -33,10 +33,12 @@
|
|||||||
.Xr ioat 4
|
.Xr ioat 4
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
|
.Op Fl c Ar period
|
||||||
.Op Fl E
|
.Op Fl E
|
||||||
.Op Fl f
|
.Op Fl f
|
||||||
.Op Fl m
|
.Op Fl m
|
||||||
.Op Fl V
|
.Op Fl V
|
||||||
|
.Op Fl z
|
||||||
.Ar channel_number
|
.Ar channel_number
|
||||||
.Ar num_txns
|
.Ar num_txns
|
||||||
.Ar [ bufsize
|
.Ar [ bufsize
|
||||||
@ -44,9 +46,11 @@
|
|||||||
.Ar [ duration ] ] ]
|
.Ar [ duration ] ] ]
|
||||||
.Nm
|
.Nm
|
||||||
.Fl r
|
.Fl r
|
||||||
|
.Op Fl c Ar period
|
||||||
.Op Fl v
|
.Op Fl v
|
||||||
.Op Fl V
|
.Op Fl V
|
||||||
.Op Fl w
|
.Op Fl w
|
||||||
|
.Op Fl z
|
||||||
.Ar channel_number
|
.Ar channel_number
|
||||||
.Ar address
|
.Ar address
|
||||||
.Ar [ bufsize ]
|
.Ar [ bufsize ]
|
||||||
@ -57,6 +61,8 @@ allows one to issue some number of test operations to the
|
|||||||
driver on a specific hardware channel.
|
driver on a specific hardware channel.
|
||||||
The arguments are as follows:
|
The arguments are as follows:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
|
.It Fl c Ar period
|
||||||
|
Configure the channel's interrupt coalescing period, in microseconds.
|
||||||
.It Fl E
|
.It Fl E
|
||||||
Test non-contiguous 8k copy.
|
Test non-contiguous 8k copy.
|
||||||
.It Fl f
|
.It Fl f
|
||||||
@ -67,6 +73,8 @@ tests copy)
|
|||||||
Test memcpy instead of DMA.
|
Test memcpy instead of DMA.
|
||||||
.It Fl V
|
.It Fl V
|
||||||
Verify copies/fills for accuracy
|
Verify copies/fills for accuracy
|
||||||
|
.It Fl z
|
||||||
|
Zero device statistics before running test.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
Alternatively one can use
|
Alternatively one can use
|
||||||
@ -76,6 +84,8 @@ to issue DMA to or from a specific
|
|||||||
.Ar address .
|
.Ar address .
|
||||||
The arguments in "raw" mode are:
|
The arguments in "raw" mode are:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
|
.It Fl c Ar period
|
||||||
|
As above.
|
||||||
.It Fl v
|
.It Fl v
|
||||||
.Ar address
|
.Ar address
|
||||||
is a kernel virtual address (by default,
|
is a kernel virtual address (by default,
|
||||||
@ -90,6 +100,8 @@ Write to the specified
|
|||||||
.Nm
|
.Nm
|
||||||
.Fl r
|
.Fl r
|
||||||
reads)
|
reads)
|
||||||
|
.It Fl z
|
||||||
|
As above.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
.Nm
|
.Nm
|
||||||
|
@ -48,10 +48,14 @@ static void
|
|||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
printf("Usage: %s [-E|-f|-m] [-V] <channel #> <txns> [<bufsize> "
|
printf("Usage: %s [-E|-f|-m] OPTIONS <channel #> <txns> [<bufsize> "
|
||||||
"[<chain-len> [duration]]]\n", getprogname());
|
"[<chain-len> [duration]]]\n", getprogname());
|
||||||
printf(" %s -r [-vV] <channel #> <addr> [<bufsize>]\n",
|
printf(" %s -r [-v] OPTIONS <channel #> <addr> [<bufsize>]\n\n",
|
||||||
getprogname());
|
getprogname());
|
||||||
|
printf(" OPTIONS:\n");
|
||||||
|
printf(" -c <period> - Enable interrupt coalescing (us)\n");
|
||||||
|
printf(" -V - Enable verification\n");
|
||||||
|
printf(" -z - Zero device stats before test\n");
|
||||||
exit(EX_USAGE);
|
exit(EX_USAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,8 +107,11 @@ main(int argc, char **argv)
|
|||||||
fflag = rflag = Eflag = mflag = false;
|
fflag = rflag = Eflag = mflag = false;
|
||||||
modeflags = 0;
|
modeflags = 0;
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "EfmrvVw")) != -1) {
|
while ((ch = getopt(argc, argv, "c:EfmrvVwz")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
|
case 'c':
|
||||||
|
t.coalesce_period = atoi(optarg);
|
||||||
|
break;
|
||||||
case 'E':
|
case 'E':
|
||||||
Eflag = true;
|
Eflag = true;
|
||||||
modeflags++;
|
modeflags++;
|
||||||
@ -130,6 +137,9 @@ main(int argc, char **argv)
|
|||||||
case 'w':
|
case 'w':
|
||||||
t.raw_write = true;
|
t.raw_write = true;
|
||||||
break;
|
break;
|
||||||
|
case 'z':
|
||||||
|
t.zero_stats = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user