nvme_sysctl.c revision 241434
1240616Sjimharris/*- 2240616Sjimharris * Copyright (C) 2012 Intel Corporation 3240616Sjimharris * All rights reserved. 4240616Sjimharris * 5240616Sjimharris * Redistribution and use in source and binary forms, with or without 6240616Sjimharris * modification, are permitted provided that the following conditions 7240616Sjimharris * are met: 8240616Sjimharris * 1. Redistributions of source code must retain the above copyright 9240616Sjimharris * notice, this list of conditions and the following disclaimer. 10240616Sjimharris * 2. Redistributions in binary form must reproduce the above copyright 11240616Sjimharris * notice, this list of conditions and the following disclaimer in the 12240616Sjimharris * documentation and/or other materials provided with the distribution. 13240616Sjimharris * 14240616Sjimharris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15240616Sjimharris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16240616Sjimharris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17240616Sjimharris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18240616Sjimharris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19240616Sjimharris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20240616Sjimharris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21240616Sjimharris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22240616Sjimharris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23240616Sjimharris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24240616Sjimharris * SUCH DAMAGE. 25240616Sjimharris */ 26240616Sjimharris 27240616Sjimharris#include <sys/cdefs.h> 28240616Sjimharris__FBSDID("$FreeBSD: head/sys/dev/nvme/nvme_sysctl.c 241434 2012-10-10 23:35:16Z jimharris $"); 29240616Sjimharris 30240616Sjimharris#include <sys/param.h> 31240616Sjimharris#include <sys/bus.h> 32240616Sjimharris#include <sys/sysctl.h> 33240616Sjimharris 34240616Sjimharris#include "nvme_private.h" 35240616Sjimharris 36241434Sjimharris/* 37241434Sjimharris * CTLTYPE_S64 and sysctl_handle_64 were added in r217616. Define these 38241434Sjimharris * explicitly here for older kernels that don't include the r217616 39241434Sjimharris * changeset. 40241434Sjimharris */ 41241434Sjimharris#ifndef CTLTYPE_S64 42241434Sjimharris#define CTLTYPE_S64 CTLTYPE_QUAD 43241434Sjimharris#define sysctl_handle_64 sysctl_handle_quad 44241434Sjimharris#endif 45241434Sjimharris 46240616Sjimharrisstatic void 47240616Sjimharrisnvme_dump_queue(struct nvme_qpair *qpair) 48240616Sjimharris{ 49240616Sjimharris struct nvme_completion *cpl; 50240616Sjimharris struct nvme_command *cmd; 51240616Sjimharris int i; 52240616Sjimharris 53240616Sjimharris printf("id:%04Xh phase:%d\n", qpair->id, qpair->phase); 54240616Sjimharris 55240616Sjimharris printf("Completion queue:\n"); 56240616Sjimharris for (i = 0; i < qpair->num_entries; i++) { 57240616Sjimharris cpl = &qpair->cpl[i]; 58240616Sjimharris printf("%05d: ", i); 59240616Sjimharris nvme_dump_completion(cpl); 60240616Sjimharris } 61240616Sjimharris 62240616Sjimharris printf("Submission queue:\n"); 63240616Sjimharris for (i = 0; i < qpair->num_entries; i++) { 64240616Sjimharris cmd = &qpair->cmd[i]; 65240616Sjimharris printf("%05d: ", i); 66240616Sjimharris nvme_dump_command(cmd); 67240616Sjimharris } 68240616Sjimharris} 69240616Sjimharris 70240616Sjimharris 71240616Sjimharrisstatic int 72240616Sjimharrisnvme_sysctl_dump_debug(SYSCTL_HANDLER_ARGS) 73240616Sjimharris{ 74240616Sjimharris struct nvme_qpair *qpair = arg1; 75240616Sjimharris uint32_t val = 0; 76240616Sjimharris 77240616Sjimharris int error = sysctl_handle_int(oidp, &val, 0, req); 78240616Sjimharris 79240616Sjimharris if (error) 80240616Sjimharris return (error); 81240616Sjimharris 82240616Sjimharris if (val != 0) 83240616Sjimharris nvme_dump_queue(qpair); 84240616Sjimharris 85240616Sjimharris return (0); 86240616Sjimharris} 87240616Sjimharris 88240616Sjimharrisstatic int 89240616Sjimharrisnvme_sysctl_int_coal_time(SYSCTL_HANDLER_ARGS) 90240616Sjimharris{ 91240616Sjimharris struct nvme_controller *ctrlr = arg1; 92240616Sjimharris uint32_t oldval = ctrlr->int_coal_time; 93240616Sjimharris int error = sysctl_handle_int(oidp, &ctrlr->int_coal_time, 0, 94240616Sjimharris req); 95240616Sjimharris 96240616Sjimharris if (error) 97240616Sjimharris return (error); 98240616Sjimharris 99240616Sjimharris if (oldval != ctrlr->int_coal_time) 100240616Sjimharris nvme_ctrlr_cmd_set_interrupt_coalescing(ctrlr, 101240616Sjimharris ctrlr->int_coal_time, ctrlr->int_coal_threshold, NULL, 102240616Sjimharris NULL); 103240616Sjimharris 104240616Sjimharris return (0); 105240616Sjimharris} 106240616Sjimharris 107240616Sjimharrisstatic int 108240616Sjimharrisnvme_sysctl_int_coal_threshold(SYSCTL_HANDLER_ARGS) 109240616Sjimharris{ 110240616Sjimharris struct nvme_controller *ctrlr = arg1; 111240616Sjimharris uint32_t oldval = ctrlr->int_coal_threshold; 112240616Sjimharris int error = sysctl_handle_int(oidp, &ctrlr->int_coal_threshold, 0, 113240616Sjimharris req); 114240616Sjimharris 115240616Sjimharris if (error) 116240616Sjimharris return (error); 117240616Sjimharris 118240616Sjimharris if (oldval != ctrlr->int_coal_threshold) 119240616Sjimharris nvme_ctrlr_cmd_set_interrupt_coalescing(ctrlr, 120240616Sjimharris ctrlr->int_coal_time, ctrlr->int_coal_threshold, NULL, 121240616Sjimharris NULL); 122240616Sjimharris 123240616Sjimharris return (0); 124240616Sjimharris} 125240616Sjimharris 126240616Sjimharrisstatic void 127241434Sjimharrisnvme_qpair_reset_stats(struct nvme_qpair *qpair) 128241434Sjimharris{ 129241434Sjimharris 130241434Sjimharris qpair->num_cmds = 0; 131241434Sjimharris qpair->num_intr_handler_calls = 0; 132241434Sjimharris} 133241434Sjimharris 134241434Sjimharrisstatic int 135241434Sjimharrisnvme_sysctl_num_cmds(SYSCTL_HANDLER_ARGS) 136241434Sjimharris{ 137241434Sjimharris struct nvme_controller *ctrlr = arg1; 138241434Sjimharris int64_t num_cmds = 0; 139241434Sjimharris int i; 140241434Sjimharris 141241434Sjimharris num_cmds = ctrlr->adminq.num_cmds; 142241434Sjimharris 143241434Sjimharris for (i = 0; i < ctrlr->num_io_queues; i++) 144241434Sjimharris num_cmds += ctrlr->ioq[i].num_cmds; 145241434Sjimharris 146241434Sjimharris return (sysctl_handle_64(oidp, &num_cmds, 0, req)); 147241434Sjimharris} 148241434Sjimharris 149241434Sjimharrisstatic int 150241434Sjimharrisnvme_sysctl_num_intr_handler_calls(SYSCTL_HANDLER_ARGS) 151241434Sjimharris{ 152241434Sjimharris struct nvme_controller *ctrlr = arg1; 153241434Sjimharris int64_t num_intr_handler_calls = 0; 154241434Sjimharris int i; 155241434Sjimharris 156241434Sjimharris num_intr_handler_calls = ctrlr->adminq.num_intr_handler_calls; 157241434Sjimharris 158241434Sjimharris for (i = 0; i < ctrlr->num_io_queues; i++) 159241434Sjimharris num_intr_handler_calls += ctrlr->ioq[i].num_intr_handler_calls; 160241434Sjimharris 161241434Sjimharris return (sysctl_handle_64(oidp, &num_intr_handler_calls, 0, req)); 162241434Sjimharris} 163241434Sjimharris 164241434Sjimharrisstatic int 165241434Sjimharrisnvme_sysctl_reset_stats(SYSCTL_HANDLER_ARGS) 166241434Sjimharris{ 167241434Sjimharris struct nvme_controller *ctrlr = arg1; 168241434Sjimharris uint32_t i, val = 0; 169241434Sjimharris 170241434Sjimharris int error = sysctl_handle_int(oidp, &val, 0, req); 171241434Sjimharris 172241434Sjimharris if (error) 173241434Sjimharris return (error); 174241434Sjimharris 175241434Sjimharris if (val != 0) { 176241434Sjimharris nvme_qpair_reset_stats(&ctrlr->adminq); 177241434Sjimharris 178241434Sjimharris for (i = 0; i < ctrlr->num_io_queues; i++) 179241434Sjimharris nvme_qpair_reset_stats(&ctrlr->ioq[i]); 180241434Sjimharris } 181241434Sjimharris 182241434Sjimharris return (0); 183241434Sjimharris} 184241434Sjimharris 185241434Sjimharris 186241434Sjimharrisstatic void 187240616Sjimharrisnvme_sysctl_initialize_queue(struct nvme_qpair *qpair, 188240616Sjimharris struct sysctl_ctx_list *ctrlr_ctx, struct sysctl_oid *que_tree) 189240616Sjimharris{ 190240616Sjimharris struct sysctl_oid_list *que_list = SYSCTL_CHILDREN(que_tree); 191240616Sjimharris 192240616Sjimharris SYSCTL_ADD_UINT(ctrlr_ctx, que_list, OID_AUTO, "num_entries", 193240616Sjimharris CTLFLAG_RD, &qpair->num_entries, 0, 194240616Sjimharris "Number of entries in hardware queue"); 195240616Sjimharris SYSCTL_ADD_UINT(ctrlr_ctx, que_list, OID_AUTO, "num_tr", 196240616Sjimharris CTLFLAG_RD, &qpair->num_tr, 0, 197240616Sjimharris "Number of trackers allocated"); 198240616Sjimharris SYSCTL_ADD_UINT(ctrlr_ctx, que_list, OID_AUTO, "num_prp_list", 199240616Sjimharris CTLFLAG_RD, &qpair->num_prp_list, 0, 200240616Sjimharris "Number of PRP lists allocated"); 201240616Sjimharris SYSCTL_ADD_UINT(ctrlr_ctx, que_list, OID_AUTO, "sq_head", 202240616Sjimharris CTLFLAG_RD, &qpair->sq_head, 0, 203240616Sjimharris "Current head of submission queue (as observed by driver)"); 204240616Sjimharris SYSCTL_ADD_UINT(ctrlr_ctx, que_list, OID_AUTO, "sq_tail", 205240616Sjimharris CTLFLAG_RD, &qpair->sq_tail, 0, 206240616Sjimharris "Current tail of submission queue (as observed by driver)"); 207240616Sjimharris SYSCTL_ADD_UINT(ctrlr_ctx, que_list, OID_AUTO, "cq_head", 208240616Sjimharris CTLFLAG_RD, &qpair->cq_head, 0, 209240616Sjimharris "Current head of completion queue (as observed by driver)"); 210240616Sjimharris 211240616Sjimharris SYSCTL_ADD_QUAD(ctrlr_ctx, que_list, OID_AUTO, "num_cmds", 212240616Sjimharris CTLFLAG_RD, &qpair->num_cmds, "Number of commands submitted"); 213241434Sjimharris SYSCTL_ADD_QUAD(ctrlr_ctx, que_list, OID_AUTO, "num_intr_handler_calls", 214241434Sjimharris CTLFLAG_RD, &qpair->num_intr_handler_calls, 215241434Sjimharris "Number of times interrupt handler was invoked (will typically be " 216241434Sjimharris "less than number of actual interrupts generated due to " 217241434Sjimharris "coalescing)"); 218240616Sjimharris 219240616Sjimharris SYSCTL_ADD_PROC(ctrlr_ctx, que_list, OID_AUTO, 220240616Sjimharris "dump_debug", CTLTYPE_UINT | CTLFLAG_RW, qpair, 0, 221240616Sjimharris nvme_sysctl_dump_debug, "IU", "Dump debug data"); 222240616Sjimharris} 223240616Sjimharris 224240616Sjimharrisvoid 225240616Sjimharrisnvme_sysctl_initialize_ctrlr(struct nvme_controller *ctrlr) 226240616Sjimharris{ 227240616Sjimharris struct sysctl_ctx_list *ctrlr_ctx; 228240616Sjimharris struct sysctl_oid *ctrlr_tree, *que_tree; 229240616Sjimharris struct sysctl_oid_list *ctrlr_list; 230240616Sjimharris#define QUEUE_NAME_LENGTH 16 231240616Sjimharris char queue_name[QUEUE_NAME_LENGTH]; 232240616Sjimharris int i; 233240616Sjimharris 234240616Sjimharris ctrlr_ctx = device_get_sysctl_ctx(ctrlr->dev); 235240616Sjimharris ctrlr_tree = device_get_sysctl_tree(ctrlr->dev); 236240616Sjimharris ctrlr_list = SYSCTL_CHILDREN(ctrlr_tree); 237240616Sjimharris 238240616Sjimharris if (ctrlr->is_started) { 239240616Sjimharris SYSCTL_ADD_PROC(ctrlr_ctx, ctrlr_list, OID_AUTO, 240240616Sjimharris "int_coal_time", CTLTYPE_UINT | CTLFLAG_RW, ctrlr, 0, 241240616Sjimharris nvme_sysctl_int_coal_time, "IU", 242240616Sjimharris "Interrupt coalescing timeout (in microseconds)"); 243240616Sjimharris 244240616Sjimharris SYSCTL_ADD_PROC(ctrlr_ctx, ctrlr_list, OID_AUTO, 245240616Sjimharris "int_coal_threshold", CTLTYPE_UINT | CTLFLAG_RW, ctrlr, 0, 246240616Sjimharris nvme_sysctl_int_coal_threshold, "IU", 247240616Sjimharris "Interrupt coalescing threshold"); 248241434Sjimharris 249241434Sjimharris SYSCTL_ADD_PROC(ctrlr_ctx, ctrlr_list, OID_AUTO, 250241434Sjimharris "num_cmds", CTLTYPE_S64 | CTLFLAG_RD, 251241434Sjimharris ctrlr, 0, nvme_sysctl_num_cmds, "IU", 252241434Sjimharris "Number of commands submitted"); 253241434Sjimharris 254241434Sjimharris SYSCTL_ADD_PROC(ctrlr_ctx, ctrlr_list, OID_AUTO, 255241434Sjimharris "num_intr_handler_calls", CTLTYPE_S64 | CTLFLAG_RD, 256241434Sjimharris ctrlr, 0, nvme_sysctl_num_intr_handler_calls, "IU", 257241434Sjimharris "Number of times interrupt handler was invoked (will " 258241434Sjimharris "typically be less than number of actual interrupts " 259241434Sjimharris "generated due to coalescing)"); 260241434Sjimharris 261241434Sjimharris SYSCTL_ADD_PROC(ctrlr_ctx, ctrlr_list, OID_AUTO, 262241434Sjimharris "reset_stats", CTLTYPE_UINT | CTLFLAG_RW, ctrlr, 0, 263241434Sjimharris nvme_sysctl_reset_stats, "IU", "Reset statistics to zero"); 264240616Sjimharris } 265240616Sjimharris 266240616Sjimharris que_tree = SYSCTL_ADD_NODE(ctrlr_ctx, ctrlr_list, OID_AUTO, "adminq", 267240616Sjimharris CTLFLAG_RD, NULL, "Admin Queue"); 268240616Sjimharris 269240616Sjimharris nvme_sysctl_initialize_queue(&ctrlr->adminq, ctrlr_ctx, que_tree); 270240616Sjimharris 271240616Sjimharris for (i = 0; i < ctrlr->num_io_queues; i++) { 272240616Sjimharris snprintf(queue_name, QUEUE_NAME_LENGTH, "ioq%d", i); 273240616Sjimharris que_tree = SYSCTL_ADD_NODE(ctrlr_ctx, ctrlr_list, OID_AUTO, 274240616Sjimharris queue_name, CTLFLAG_RD, NULL, "IO Queue"); 275240616Sjimharris nvme_sysctl_initialize_queue(&ctrlr->ioq[i], ctrlr_ctx, 276240616Sjimharris que_tree); 277240616Sjimharris } 278240616Sjimharris} 279