196f556f5SAlexander Motin /*-
296f556f5SAlexander Motin * This file is provided under a dual BSD/GPLv2 license. When using or
396f556f5SAlexander Motin * redistributing this file, you may do so under either license.
496f556f5SAlexander Motin *
596f556f5SAlexander Motin * GPL LICENSE SUMMARY
696f556f5SAlexander Motin *
796f556f5SAlexander Motin * Copyright (c) 2019 Advanced Micro Devices, Inc. All Rights Reserved.
896f556f5SAlexander Motin *
996f556f5SAlexander Motin * This program is free software; you can redistribute it and/or modify
1096f556f5SAlexander Motin * it under the terms of version 2 of the GNU General Public License as
1196f556f5SAlexander Motin * published by the Free Software Foundation.
1296f556f5SAlexander Motin *
1396f556f5SAlexander Motin * This program is distributed in the hope that it will be useful, but
1496f556f5SAlexander Motin * WITHOUT ANY WARRANTY; without even the implied warranty of
1596f556f5SAlexander Motin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1696f556f5SAlexander Motin * General Public License for more details.
1796f556f5SAlexander Motin *
1896f556f5SAlexander Motin * BSD LICENSE
1996f556f5SAlexander Motin *
2096f556f5SAlexander Motin * Copyright (c) 2019 Advanced Micro Devices, Inc. All Rights Reserved.
2196f556f5SAlexander Motin *
2296f556f5SAlexander Motin * Redistribution and use in source and binary forms, with or without
2396f556f5SAlexander Motin * modification, are permitted provided that the following conditions
2496f556f5SAlexander Motin * are met:
2596f556f5SAlexander Motin *
2696f556f5SAlexander Motin * * Redistributions of source code must retain the above copyright
2796f556f5SAlexander Motin * notice, this list of conditions and the following disclaimer.
2896f556f5SAlexander Motin * * Redistributions in binary form must reproduce the above copy
2996f556f5SAlexander Motin * notice, this list of conditions and the following disclaimer in
3096f556f5SAlexander Motin * the documentation and/or other materials provided with the
3196f556f5SAlexander Motin * distribution.
3296f556f5SAlexander Motin * * Neither the name of Advanced Micro Devices, Inc nor the names of its
3396f556f5SAlexander Motin * contributors may be used to endorse or promote products derived
3496f556f5SAlexander Motin * from this software without specific prior written permission.
3596f556f5SAlexander Motin *
3696f556f5SAlexander Motin * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3796f556f5SAlexander Motin * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3896f556f5SAlexander Motin * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3996f556f5SAlexander Motin * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
4096f556f5SAlexander Motin * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4196f556f5SAlexander Motin * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4296f556f5SAlexander Motin * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4396f556f5SAlexander Motin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4496f556f5SAlexander Motin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4596f556f5SAlexander Motin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
4696f556f5SAlexander Motin * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4796f556f5SAlexander Motin *
4896f556f5SAlexander Motin * PCIe NTB Debugging Tool FreeBSD driver
4996f556f5SAlexander Motin */
5096f556f5SAlexander Motin
5196f556f5SAlexander Motin /*
5296f556f5SAlexander Motin * How to use this tool, by example.
5396f556f5SAlexander Motin *
5496f556f5SAlexander Motin * List of sysctl for ntb_tool driver.
5596f556f5SAlexander Motin * root@local# sysctl -a | grep ntb_tool
5696f556f5SAlexander Motin * dev.ntb_tool.0.peer0.spad7: 0x0
5796f556f5SAlexander Motin * dev.ntb_tool.0.peer0.spad6: 0x0
5896f556f5SAlexander Motin * dev.ntb_tool.0.peer0.spad5: 0x0
5996f556f5SAlexander Motin * dev.ntb_tool.0.peer0.spad4: 0x0
6096f556f5SAlexander Motin * dev.ntb_tool.0.peer0.spad3: 0x0
6196f556f5SAlexander Motin * dev.ntb_tool.0.peer0.spad2: 0x0
6296f556f5SAlexander Motin * dev.ntb_tool.0.peer0.spad1: 0x0
6396f556f5SAlexander Motin * dev.ntb_tool.0.peer0.spad0: 0x0
6496f556f5SAlexander Motin * dev.ntb_tool.0.peer0.mw_trans2:
6596f556f5SAlexander Motin * dev.ntb_tool.0.peer0.mw_trans1:
6696f556f5SAlexander Motin * dev.ntb_tool.0.peer0.mw_trans0:
6796f556f5SAlexander Motin * dev.ntb_tool.0.peer0.peer_mw2:
6896f556f5SAlexander Motin * dev.ntb_tool.0.peer0.peer_mw1:
6996f556f5SAlexander Motin * dev.ntb_tool.0.peer0.peer_mw0:
7096f556f5SAlexander Motin * dev.ntb_tool.0.peer0.mw2:
7196f556f5SAlexander Motin * dev.ntb_tool.0.peer0.mw1:
7296f556f5SAlexander Motin * dev.ntb_tool.0.peer0.mw0:
7396f556f5SAlexander Motin * dev.ntb_tool.0.peer0.link_event: 0x0
7496f556f5SAlexander Motin * dev.ntb_tool.0.peer0.link: Y
7596f556f5SAlexander Motin * dev.ntb_tool.0.peer0.port: 1
7696f556f5SAlexander Motin * dev.ntb_tool.0.spad7: 0x0
7796f556f5SAlexander Motin * dev.ntb_tool.0.spad6: 0x0
7896f556f5SAlexander Motin * dev.ntb_tool.0.spad5: 0x0
7996f556f5SAlexander Motin * dev.ntb_tool.0.spad4: 0x0
8096f556f5SAlexander Motin * dev.ntb_tool.0.spad3: 0x0
8196f556f5SAlexander Motin * dev.ntb_tool.0.spad2: 0x0
8296f556f5SAlexander Motin * dev.ntb_tool.0.spad1: 0x0
8396f556f5SAlexander Motin * dev.ntb_tool.0.spad0: 0x0
8496f556f5SAlexander Motin * dev.ntb_tool.0.db: 0x0
8596f556f5SAlexander Motin * dev.ntb_tool.0.db_event: 0x0
8696f556f5SAlexander Motin * dev.ntb_tool.0.db_mask: 0xffff
8796f556f5SAlexander Motin * dev.ntb_tool.0.db_valid_mask: 0xffff
8896f556f5SAlexander Motin * dev.ntb_tool.0.peer_db: 0x0
8996f556f5SAlexander Motin * dev.ntb_tool.0.peer_db_mask: 0xffff
9096f556f5SAlexander Motin * dev.ntb_tool.0.link: Y
9196f556f5SAlexander Motin * dev.ntb_tool.0.port: 0
9296f556f5SAlexander Motin *
9396f556f5SAlexander Motin * The above example list shows
9496f556f5SAlexander Motin * 1) three memory windows,
9596f556f5SAlexander Motin * 1) eight scratchpad registers.
9696f556f5SAlexander Motin * 3) doorbell config.
9796f556f5SAlexander Motin * 4) link config.
9896f556f5SAlexander Motin * 2) One peer.
9996f556f5SAlexander Motin *
10096f556f5SAlexander Motin * Based on the underlined ntb_hw driver config & connection topology, these
10196f556f5SAlexander Motin * things might differ.
10296f556f5SAlexander Motin *-----------------------------------------------------------------------------
10396f556f5SAlexander Motin * Eg: check local/peer port information.
10496f556f5SAlexander Motin *
10596f556f5SAlexander Motin * # Get local device port number
10696f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.port
10796f556f5SAlexander Motin *
10896f556f5SAlexander Motin * # Check peer device port number
10996f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer0.port
11096f556f5SAlexander Motin *-----------------------------------------------------------------------------
11196f556f5SAlexander Motin * Eg: NTB link tests
11296f556f5SAlexander Motin *
11396f556f5SAlexander Motin * # Set local link up/down
11496f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.link=Y
11596f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.link=N
11696f556f5SAlexander Motin *
11796f556f5SAlexander Motin * # Check if link with peer device is up/down:
11896f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer0.link
11996f556f5SAlexander Motin *
12096f556f5SAlexander Motin * # Poll until the link specified as up/down. For up, value needs to be set
12196f556f5SAlexander Motin * depends on peer index, i.e., for peer0 it is 0x1 and for down, value needs
12296f556f5SAlexander Motin * to be set as 0x0.
12396f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer0.link_event=0x1
12496f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer0.link_event=0x0
12596f556f5SAlexander Motin *-----------------------------------------------------------------------------
12696f556f5SAlexander Motin * Eg: Doorbell registers tests
12796f556f5SAlexander Motin *
12896f556f5SAlexander Motin * # clear/get local doorbell
12996f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.db="c 0x1"
13096f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.db
13196f556f5SAlexander Motin *
13296f556f5SAlexander Motin * # Set/clear/get local doorbell mask
13396f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.db_mask="s 0x1"
13496f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.db_mask="c 0x1"
13596f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.db_mask
13696f556f5SAlexander Motin *
13796f556f5SAlexander Motin * # Ring/clear/get peer doorbell
13896f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer_db="s 0x1"
13996f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer_db="c 0x1"
14096f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer_db
14196f556f5SAlexander Motin *
14296f556f5SAlexander Motin * # Set/clear/get peer doorbell mask (functionality is absent)
14396f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer_db_mask="s 0x1"
14496f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer_db_mask="c 0x1"
14596f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer_db_mask
14696f556f5SAlexander Motin *
14796f556f5SAlexander Motin * # Poll until local doorbell is set with the specified db bits
14896f556f5SAlexander Motin * root@local# dev.ntb_tool.0.db_event=0x1
14996f556f5SAlexander Motin *-----------------------------------------------------------------------------
15096f556f5SAlexander Motin * Eg: Scratchpad registers tests
15196f556f5SAlexander Motin *
15296f556f5SAlexander Motin * # Write/read to/from local scratchpad register #0
15396f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.spad0=0x1023457
15496f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.spad0
15596f556f5SAlexander Motin *
15696f556f5SAlexander Motin * # Write/read to/from peer scratchpad register #0
15796f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer0.spad0=0x01020304
15896f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer0.spad0
15996f556f5SAlexander Motin *-----------------------------------------------------------------------------
16096f556f5SAlexander Motin * Eg: Memory windows tests (need to configure local mw_trans on both sides)
16196f556f5SAlexander Motin *
16296f556f5SAlexander Motin * # Create inbound memory window buffer of specified size/get its dma address
16396f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer0.mw_trans0=16384
16496f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer0.mw_trans0
16596f556f5SAlexander Motin *
16696f556f5SAlexander Motin * # Write/read data to/from inbound memory window with specific pattern/random
16796f556f5SAlexander Motin * data.
16896f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer0.mw0="W offset 0 nbytes 100 pattern ab"
16996f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer0.mw0="R offset 0 nbytes 100"
17096f556f5SAlexander Motin *
17196f556f5SAlexander Motin * # Write/read data to/from outbound memory window on the local device with
17296f556f5SAlexander Motin * specific pattern/random (on peer device)
17396f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer0.peer_mw0="W offset 0 nbytes 100 pattern ab"
17496f556f5SAlexander Motin * root@local# sysctl dev.ntb_tool.0.peer0.peer_mw0="R offset 0 nbytes 100"
17596f556f5SAlexander Motin *-----------------------------------------------------------------------------
17696f556f5SAlexander Motin * NOTE: *Message registers are not supported*
17796f556f5SAlexander Motin *-----------------------------------------------------------------------------
17896f556f5SAlexander Motin *
17996f556f5SAlexander Motin * contact information:
18096f556f5SAlexander Motin * Arpan Palit <arpan.palit@amd.com>
18196f556f5SAlexander Motin *
18296f556f5SAlexander Motin */
18396f556f5SAlexander Motin
18496f556f5SAlexander Motin #include <sys/param.h>
18596f556f5SAlexander Motin #include <sys/bus.h>
18696f556f5SAlexander Motin #include <sys/kernel.h>
18796f556f5SAlexander Motin #include <sys/module.h>
18896f556f5SAlexander Motin #include <sys/mbuf.h>
18996f556f5SAlexander Motin #include <sys/sysctl.h>
19096f556f5SAlexander Motin #include <sys/sbuf.h>
19196f556f5SAlexander Motin
19296f556f5SAlexander Motin #include <machine/bus.h>
19396f556f5SAlexander Motin
19496f556f5SAlexander Motin #include <vm/vm.h>
19596f556f5SAlexander Motin
19696f556f5SAlexander Motin #include "../ntb.h"
19796f556f5SAlexander Motin
19896f556f5SAlexander Motin /* Buffer length for User input */
19996f556f5SAlexander Motin #define TOOL_BUF_LEN 48
20096f556f5SAlexander Motin /* Memory window default command read and write offset. */
20196f556f5SAlexander Motin #define DEFAULT_MW_OFF 0
20296f556f5SAlexander Motin /* Memory window default size and also max command read size. */
20396f556f5SAlexander Motin #define DEFAULT_MW_SIZE 1024
20496f556f5SAlexander Motin
20596f556f5SAlexander Motin MALLOC_DEFINE(M_NTB_TOOL, "ntb_tool", "ntb_tool driver memory allocation");
20696f556f5SAlexander Motin
20796f556f5SAlexander Motin /*
20896f556f5SAlexander Motin * Memory windows descriptor structure
20996f556f5SAlexander Motin */
21096f556f5SAlexander Motin struct tool_mw {
21196f556f5SAlexander Motin struct tool_ctx *tc;
21296f556f5SAlexander Motin int widx;
21396f556f5SAlexander Motin int pidx;
21496f556f5SAlexander Motin
21596f556f5SAlexander Motin /* Rx buff is off virt_addr / dma_base */
21696f556f5SAlexander Motin bus_addr_t dma_base;
21796f556f5SAlexander Motin caddr_t virt_addr;
21896f556f5SAlexander Motin bus_dmamap_t dma_map;
21996f556f5SAlexander Motin bus_dma_tag_t dma_tag;
22096f556f5SAlexander Motin
22196f556f5SAlexander Motin /* Tx buff is off vbase / phys_addr */
22296f556f5SAlexander Motin caddr_t mm_base;
22396f556f5SAlexander Motin vm_paddr_t phys_addr;
22496f556f5SAlexander Motin bus_addr_t addr_limit;
22596f556f5SAlexander Motin size_t phys_size;
22696f556f5SAlexander Motin size_t xlat_align;
22796f556f5SAlexander Motin size_t xlat_align_size;
22896f556f5SAlexander Motin
22996f556f5SAlexander Motin /* Memory window configured size and limits */
23096f556f5SAlexander Motin size_t size;
23196f556f5SAlexander Motin ssize_t mw_buf_size;
23296f556f5SAlexander Motin ssize_t mw_buf_offset;
23396f556f5SAlexander Motin ssize_t mw_peer_buf_size;
23496f556f5SAlexander Motin ssize_t mw_peer_buf_offset;
23596f556f5SAlexander Motin
23696f556f5SAlexander Motin /* options to handle sysctl out */
23796f556f5SAlexander Motin int mw_cmd_rw;
23896f556f5SAlexander Motin int mw_peer_cmd_rw;
23996f556f5SAlexander Motin };
24096f556f5SAlexander Motin
24196f556f5SAlexander Motin struct tool_spad {
24296f556f5SAlexander Motin int sidx;
24396f556f5SAlexander Motin int pidx;
24496f556f5SAlexander Motin struct tool_ctx *tc;
24596f556f5SAlexander Motin };
24696f556f5SAlexander Motin
24796f556f5SAlexander Motin struct tool_peer {
24896f556f5SAlexander Motin int pidx;
24996f556f5SAlexander Motin struct tool_ctx *tc;
25096f556f5SAlexander Motin int inmw_cnt;
25196f556f5SAlexander Motin struct tool_mw *inmws;
25296f556f5SAlexander Motin int outspad_cnt;
25396f556f5SAlexander Motin struct tool_spad *outspads;
25496f556f5SAlexander Motin unsigned int port_no;
25596f556f5SAlexander Motin };
25696f556f5SAlexander Motin
25796f556f5SAlexander Motin struct tool_ctx {
25896f556f5SAlexander Motin device_t dev;
25996f556f5SAlexander Motin struct callout link_event_timer;
26096f556f5SAlexander Motin struct callout db_event_timer;
26196f556f5SAlexander Motin int peer_cnt;
26296f556f5SAlexander Motin struct tool_peer *peers;
26396f556f5SAlexander Motin int inmsg_cnt;
26496f556f5SAlexander Motin struct tool_msg *inmsgs;
26596f556f5SAlexander Motin int inspad_cnt;
26696f556f5SAlexander Motin struct tool_spad *inspads;
26796f556f5SAlexander Motin unsigned int unsafe;
26896f556f5SAlexander Motin
26996f556f5SAlexander Motin /* sysctl read out variables */
27096f556f5SAlexander Motin char link_status;
27196f556f5SAlexander Motin uint64_t link_bits;
27296f556f5SAlexander Motin uint64_t link_mask;
27396f556f5SAlexander Motin uint64_t db_valid_mask;
27496f556f5SAlexander Motin uint64_t db_mask_val;
27596f556f5SAlexander Motin uint64_t db_event_val;
27696f556f5SAlexander Motin uint64_t peer_db_val;
27796f556f5SAlexander Motin uint64_t peer_db_mask_val;
27896f556f5SAlexander Motin unsigned int port_no;
27996f556f5SAlexander Motin };
28096f556f5SAlexander Motin
28196f556f5SAlexander Motin /* structure to save dma_addr after dma load */
28296f556f5SAlexander Motin struct ntb_tool_load_cb_args {
28396f556f5SAlexander Motin bus_addr_t addr;
28496f556f5SAlexander Motin int error;
28596f556f5SAlexander Motin };
28696f556f5SAlexander Motin
28796f556f5SAlexander Motin /*
28896f556f5SAlexander Motin * NTB events handlers
28996f556f5SAlexander Motin */
29096f556f5SAlexander Motin static void
tool_link_event(void * ctx)29196f556f5SAlexander Motin tool_link_event(void *ctx)
29296f556f5SAlexander Motin {
29396f556f5SAlexander Motin struct tool_ctx *tc = ctx;
29496f556f5SAlexander Motin enum ntb_speed speed = 0;
29596f556f5SAlexander Motin enum ntb_width width = 0;
29696f556f5SAlexander Motin int up = 0;
29796f556f5SAlexander Motin
29896f556f5SAlexander Motin up = ntb_link_is_up(tc->dev, &speed, &width);
29996f556f5SAlexander Motin if (up)
30096f556f5SAlexander Motin tc->link_status = 'Y';
30196f556f5SAlexander Motin else
30296f556f5SAlexander Motin tc->link_status = 'N';
30396f556f5SAlexander Motin
30496f556f5SAlexander Motin device_printf(tc->dev, "link is %s speed %d width %d\n",
30596f556f5SAlexander Motin up ? "up" : "down", speed, width);
30696f556f5SAlexander Motin }
30796f556f5SAlexander Motin
30896f556f5SAlexander Motin static void
tool_db_event(void * ctx,uint32_t vec)30996f556f5SAlexander Motin tool_db_event(void *ctx, uint32_t vec)
31096f556f5SAlexander Motin {
31196f556f5SAlexander Motin struct tool_ctx *tc = ctx;
31296f556f5SAlexander Motin uint64_t db_bits, db_mask;
31396f556f5SAlexander Motin
31496f556f5SAlexander Motin db_mask = ntb_db_vector_mask(tc->dev, vec);
31596f556f5SAlexander Motin db_bits = ntb_db_read(tc->dev);
31696f556f5SAlexander Motin
31796f556f5SAlexander Motin device_printf(tc->dev, "doorbell vec %d mask %#llx bits %#llx\n",
31896f556f5SAlexander Motin vec, (unsigned long long)db_mask, (unsigned long long)db_bits);
31996f556f5SAlexander Motin }
32096f556f5SAlexander Motin
32196f556f5SAlexander Motin static const struct ntb_ctx_ops tool_ops = {
32296f556f5SAlexander Motin .link_event = tool_link_event,
32396f556f5SAlexander Motin .db_event = tool_db_event,
32496f556f5SAlexander Motin };
32596f556f5SAlexander Motin
32696f556f5SAlexander Motin /*
32796f556f5SAlexander Motin * Callout event methods
32896f556f5SAlexander Motin */
32996f556f5SAlexander Motin static void
tool_link_event_handler(void * arg)33096f556f5SAlexander Motin tool_link_event_handler(void *arg)
33196f556f5SAlexander Motin {
33296f556f5SAlexander Motin struct tool_ctx *tc = (struct tool_ctx *)arg;
33396f556f5SAlexander Motin uint64_t val;
33496f556f5SAlexander Motin
33596f556f5SAlexander Motin val = ntb_link_is_up(tc->dev, NULL, NULL) & tc->link_mask;
33696f556f5SAlexander Motin
33796f556f5SAlexander Motin if (val == tc->link_bits) {
33896f556f5SAlexander Motin device_printf(tc->dev, "link_event successful for link val="
33996f556f5SAlexander Motin "0x%jx\n", tc->link_bits);
34096f556f5SAlexander Motin tc->link_bits = 0x0;
34196f556f5SAlexander Motin tc->link_mask = 0x0;
34296f556f5SAlexander Motin } else
34396f556f5SAlexander Motin callout_reset(&tc->link_event_timer, 1, tool_link_event_handler, tc);
34496f556f5SAlexander Motin }
34596f556f5SAlexander Motin
34696f556f5SAlexander Motin static void
tool_db_event_handler(void * arg)34796f556f5SAlexander Motin tool_db_event_handler(void *arg)
34896f556f5SAlexander Motin {
34996f556f5SAlexander Motin struct tool_ctx *tc = (struct tool_ctx *)arg;
35096f556f5SAlexander Motin uint64_t db_bits;
35196f556f5SAlexander Motin
35296f556f5SAlexander Motin db_bits = ntb_db_read(tc->dev);
35396f556f5SAlexander Motin
35496f556f5SAlexander Motin if (db_bits == tc->db_event_val) {
35596f556f5SAlexander Motin device_printf(tc->dev, "db_event successful for db val=0x%jx\n",
35696f556f5SAlexander Motin tc->db_event_val);
35796f556f5SAlexander Motin tc->db_event_val = 0x0;
35896f556f5SAlexander Motin } else
35996f556f5SAlexander Motin callout_reset(&tc->db_event_timer, 1, tool_db_event_handler, tc);
36096f556f5SAlexander Motin }
36196f556f5SAlexander Motin
36296f556f5SAlexander Motin /*
36396f556f5SAlexander Motin * Common read/write methods
36496f556f5SAlexander Motin */
36596f556f5SAlexander Motin static inline int
get_ubuf(struct sysctl_req * req,char * ubuf)36696f556f5SAlexander Motin get_ubuf(struct sysctl_req *req, char *ubuf)
36796f556f5SAlexander Motin {
36896f556f5SAlexander Motin int rc;
36996f556f5SAlexander Motin
37096f556f5SAlexander Motin if (req->newlen >= TOOL_BUF_LEN)
37196f556f5SAlexander Motin return (EINVAL);
37296f556f5SAlexander Motin
37396f556f5SAlexander Motin rc = SYSCTL_IN(req, ubuf, req->newlen);
37496f556f5SAlexander Motin if (rc)
37596f556f5SAlexander Motin return (rc);
37696f556f5SAlexander Motin ubuf[req->newlen] = '\0';
37796f556f5SAlexander Motin
37896f556f5SAlexander Motin return (0);
37996f556f5SAlexander Motin }
38096f556f5SAlexander Motin
38196f556f5SAlexander Motin static int
read_out(struct sysctl_req * req,uint64_t val)38296f556f5SAlexander Motin read_out(struct sysctl_req *req, uint64_t val)
38396f556f5SAlexander Motin {
384c59370f0SEric van Gyzen char ubuf[19];
38596f556f5SAlexander Motin
38696f556f5SAlexander Motin memset((void *)ubuf, 0, sizeof(ubuf));
38796f556f5SAlexander Motin snprintf(ubuf, sizeof(ubuf), "0x%jx", val);
38896f556f5SAlexander Motin
38996f556f5SAlexander Motin return SYSCTL_OUT(req, ubuf, sizeof(ubuf));
39096f556f5SAlexander Motin }
39196f556f5SAlexander Motin
39296f556f5SAlexander Motin static int
tool_fn_read(struct tool_ctx * tc,struct sysctl_req * req,uint64_t (* fn_read)(device_t),uint64_t val)39396f556f5SAlexander Motin tool_fn_read(struct tool_ctx *tc, struct sysctl_req *req,
39496f556f5SAlexander Motin uint64_t (*fn_read)(device_t ), uint64_t val)
39596f556f5SAlexander Motin {
39696f556f5SAlexander Motin if (fn_read == NULL)
39796f556f5SAlexander Motin return read_out(req, val);
39896f556f5SAlexander Motin else if (fn_read)
39996f556f5SAlexander Motin return read_out(req, (uint64_t)fn_read(tc->dev));
40096f556f5SAlexander Motin else
40196f556f5SAlexander Motin return (EINVAL);
40296f556f5SAlexander Motin }
40396f556f5SAlexander Motin
40496f556f5SAlexander Motin static int
tool_fn_write(struct tool_ctx * tc,struct sysctl_oid * oidp,struct sysctl_req * req,char * ubuf,uint64_t * val,bool db_mask_sflag,void (* fn_set)(device_t,uint64_t),void (* fn_clear)(device_t,uint64_t))40596f556f5SAlexander Motin tool_fn_write(struct tool_ctx *tc, struct sysctl_oid *oidp,
40696f556f5SAlexander Motin struct sysctl_req *req, char *ubuf, uint64_t *val, bool db_mask_sflag,
40796f556f5SAlexander Motin void (*fn_set)(device_t , uint64_t), void (*fn_clear)(device_t , uint64_t))
40896f556f5SAlexander Motin {
40996f556f5SAlexander Motin uint64_t db_valid_mask = tc->db_valid_mask;
41096f556f5SAlexander Motin uint64_t bits;
41196f556f5SAlexander Motin char cmd;
41296f556f5SAlexander Motin
41396f556f5SAlexander Motin if (fn_set == NULL && fn_clear == NULL) {
41496f556f5SAlexander Motin device_printf(tc->dev, "ERR: Set & Clear both are not supported\n");
41596f556f5SAlexander Motin return (EINVAL);
41696f556f5SAlexander Motin }
41796f556f5SAlexander Motin
41896f556f5SAlexander Motin if (tc->db_valid_mask == 0)
41996f556f5SAlexander Motin db_valid_mask = tc->db_valid_mask = ntb_db_valid_mask(tc->dev);
42096f556f5SAlexander Motin
42196f556f5SAlexander Motin bits = 0;
42296f556f5SAlexander Motin sscanf(ubuf, "%c %jx", &cmd, &bits);
42396f556f5SAlexander Motin if (cmd == 's') {
42496f556f5SAlexander Motin if ((bits | db_valid_mask) > db_valid_mask) {
42596f556f5SAlexander Motin device_printf(tc->dev, "0x%jx value is not supported\n", bits);
42696f556f5SAlexander Motin return (EINVAL);
42796f556f5SAlexander Motin }
42896f556f5SAlexander Motin if (fn_set)
42996f556f5SAlexander Motin fn_set(tc->dev, bits);
43096f556f5SAlexander Motin else
43196f556f5SAlexander Motin return (EINVAL);
43296f556f5SAlexander Motin if (val)
43396f556f5SAlexander Motin *val |= bits;
43496f556f5SAlexander Motin } else if (cmd == 'c') {
43596f556f5SAlexander Motin if ((bits | db_valid_mask) > db_valid_mask) {
43696f556f5SAlexander Motin device_printf(tc->dev, "0x%jx value is not supported\n", bits);
43796f556f5SAlexander Motin return (EINVAL);
43896f556f5SAlexander Motin }
43996f556f5SAlexander Motin if (fn_clear)
44096f556f5SAlexander Motin fn_clear(tc->dev, bits);
44196f556f5SAlexander Motin if (val)
44296f556f5SAlexander Motin *val &= ~bits;
44396f556f5SAlexander Motin } else {
44496f556f5SAlexander Motin device_printf(tc->dev, "Wrong Write\n");
44596f556f5SAlexander Motin return (EINVAL);
44696f556f5SAlexander Motin }
44796f556f5SAlexander Motin
44896f556f5SAlexander Motin return (0);
44996f556f5SAlexander Motin }
45096f556f5SAlexander Motin
45196f556f5SAlexander Motin static int
parse_mw_buf(char * buf,char * cmd,ssize_t * offset,ssize_t * buf_size,uint64_t * pattern,bool * s_pflag)45296f556f5SAlexander Motin parse_mw_buf(char *buf, char *cmd, ssize_t *offset, ssize_t *buf_size,
45396f556f5SAlexander Motin uint64_t *pattern, bool *s_pflag)
45496f556f5SAlexander Motin {
45596f556f5SAlexander Motin char op1[8], op2[8], op3[8];
45696f556f5SAlexander Motin uint64_t val1, val2, val3;
45796f556f5SAlexander Motin bool vs1, vs2, vs3;
45896f556f5SAlexander Motin int rc = 0;
45996f556f5SAlexander Motin
46096f556f5SAlexander Motin vs1 = vs2 = vs3 = false;
46196f556f5SAlexander Motin sscanf(buf, "%c %s %jx %s %jx %s %jx",
46296f556f5SAlexander Motin cmd, op1, &val1, op2, &val2, op3, &val3);
46396f556f5SAlexander Motin
46496f556f5SAlexander Motin if (*cmd != 'W' && *cmd != 'R')
46596f556f5SAlexander Motin return (EINVAL);
46696f556f5SAlexander Motin
46796f556f5SAlexander Motin if (!strcmp(op1, "offset")) {
46896f556f5SAlexander Motin *offset = val1 ? val1 : DEFAULT_MW_OFF;
46996f556f5SAlexander Motin vs1 = true;
47096f556f5SAlexander Motin } else if (!strcmp(op1, "nbytes")) {
47196f556f5SAlexander Motin *buf_size = val1 ? val1: DEFAULT_MW_SIZE;
47296f556f5SAlexander Motin vs2 = true;
47396f556f5SAlexander Motin } else if (!strcmp(op1, "pattern")) {
47496f556f5SAlexander Motin *pattern = val1;
47596f556f5SAlexander Motin vs3 = true;
47696f556f5SAlexander Motin }
47796f556f5SAlexander Motin
47896f556f5SAlexander Motin if (!vs1 && !strcmp(op2, "offset")) {
47996f556f5SAlexander Motin *offset = val2 ? val2 : DEFAULT_MW_OFF;
48096f556f5SAlexander Motin vs1 = true;
48196f556f5SAlexander Motin } else if (!vs2 && !strcmp(op2, "nbytes")) {
48296f556f5SAlexander Motin *buf_size = val2 ? val2: DEFAULT_MW_SIZE;
48396f556f5SAlexander Motin vs2 = true;
48496f556f5SAlexander Motin } else if (!vs3 && !strcmp(op2, "pattern")) {
48596f556f5SAlexander Motin *pattern = val2;
48696f556f5SAlexander Motin vs3 = true;
48796f556f5SAlexander Motin }
48896f556f5SAlexander Motin
48996f556f5SAlexander Motin if (!vs1 && !strcmp(op3, "offset")) {
49096f556f5SAlexander Motin *offset = val3 ? val3 : DEFAULT_MW_OFF;
49196f556f5SAlexander Motin } else if (!vs2 && !strcmp(op3, "nbytes")) {
49296f556f5SAlexander Motin *buf_size = val3 ? val3: DEFAULT_MW_SIZE;
49396f556f5SAlexander Motin } else if (!vs3 && !strcmp(op3, "pattern")) {
49496f556f5SAlexander Motin *pattern = val3;
49596f556f5SAlexander Motin vs3 = true;
49696f556f5SAlexander Motin }
49796f556f5SAlexander Motin
49896f556f5SAlexander Motin *s_pflag = vs3;
49996f556f5SAlexander Motin if (vs3 && *cmd == 'R')
50096f556f5SAlexander Motin printf("NTB_TOOL_WARN: pattern is not supported with read "
50196f556f5SAlexander Motin "command\n");
50296f556f5SAlexander Motin
50396f556f5SAlexander Motin return (rc);
50496f556f5SAlexander Motin }
50596f556f5SAlexander Motin
50696f556f5SAlexander Motin static int
tool_mw_read_fn(struct sysctl_req * req,struct tool_mw * inmw,char * read_addr,int * cmd_op,ssize_t buf_off,ssize_t buf_size,char * type)50796f556f5SAlexander Motin tool_mw_read_fn(struct sysctl_req *req, struct tool_mw *inmw, char *read_addr,
50896f556f5SAlexander Motin int *cmd_op, ssize_t buf_off, ssize_t buf_size, char *type)
50996f556f5SAlexander Motin {
51096f556f5SAlexander Motin ssize_t index, size;
51196f556f5SAlexander Motin struct sbuf *sb;
51296f556f5SAlexander Motin int i, loop, rc;
51396f556f5SAlexander Motin char *tmp;
51496f556f5SAlexander Motin
51596f556f5SAlexander Motin /* The below check is made to ignore sysctl read call. */
51696f556f5SAlexander Motin if (*cmd_op == 0)
51796f556f5SAlexander Motin return (0);
51896f556f5SAlexander Motin
51996f556f5SAlexander Motin /* Proceeds only when command R/W is requested using sysctl. */
52096f556f5SAlexander Motin index = buf_off;
52196f556f5SAlexander Motin tmp = read_addr;
52296f556f5SAlexander Motin tmp += index;
52396f556f5SAlexander Motin loop = ((buf_size == 0) || (buf_size > DEFAULT_MW_SIZE)) ?
52496f556f5SAlexander Motin DEFAULT_MW_SIZE : buf_size;
52596f556f5SAlexander Motin /*
52696f556f5SAlexander Motin * 256 bytes of extra buffer has been allocated to print details like
52796f556f5SAlexander Motin * summary, size, notes, i.e., excluding data part.
52896f556f5SAlexander Motin */
52996f556f5SAlexander Motin size = loop + 256;
53096f556f5SAlexander Motin sb = sbuf_new_for_sysctl(NULL, NULL, size, req);
53196f556f5SAlexander Motin if (sb == NULL) {
53296f556f5SAlexander Motin rc = sb->s_error;
53396f556f5SAlexander Motin return (rc);
53496f556f5SAlexander Motin }
53596f556f5SAlexander Motin
53696f556f5SAlexander Motin if (!strcmp(type, "mw"))
53796f556f5SAlexander Motin sbuf_printf(sb, "\nConfigured MW size\t: %zu\n", inmw->size);
53896f556f5SAlexander Motin else if (!strcmp(type, "peer_mw"))
53996f556f5SAlexander Motin sbuf_printf(sb, "\nConfigured Peer MW size\t: %zu\n",
54096f556f5SAlexander Motin inmw->size);
54196f556f5SAlexander Motin sbuf_printf(sb, "R/W size\t\t: %zi\nR/W Offset\t\t: %zi\n\nData\n----"
54296f556f5SAlexander Motin "->", buf_size, buf_off);
54396f556f5SAlexander Motin
54496f556f5SAlexander Motin /*
54596f556f5SAlexander Motin * Data will be read based on MW size provided by the user using nbytes,
54696f556f5SAlexander Motin * which is limited to 1024 bytes if user req bigger size to read, check
54796f556f5SAlexander Motin * above loop calculation which is limiting or setting the MW read size.
54896f556f5SAlexander Motin * Below for loop prints data where in each line contains 32 bytes data
54996f556f5SAlexander Motin * and after each 8 bytes of data we used four spaces which ensures one
55096f556f5SAlexander Motin * data block.
55196f556f5SAlexander Motin */
55296f556f5SAlexander Motin for (i = 0 ; i < loop; i++) {
55396f556f5SAlexander Motin if ((i % 32) == 0) {
55496f556f5SAlexander Motin sbuf_printf(sb, "\n%08zx:", index);
55596f556f5SAlexander Motin index += 32;
55696f556f5SAlexander Motin }
55796f556f5SAlexander Motin if ((i % 8) == 0)
55896f556f5SAlexander Motin sbuf_printf(sb, " ");
55996f556f5SAlexander Motin sbuf_printf(sb, "%02hhx", *(tmp+i));
56096f556f5SAlexander Motin }
56196f556f5SAlexander Motin if (buf_size > DEFAULT_MW_SIZE)
56296f556f5SAlexander Motin sbuf_printf(sb, "\n\nNOTE: Truncating read size %zi->1024 "
56396f556f5SAlexander Motin "bytes\n", buf_size);
56496f556f5SAlexander Motin
56596f556f5SAlexander Motin /* cmd_op is set to zero after completion of each R/W command. */
56696f556f5SAlexander Motin *cmd_op -= 1;
56796f556f5SAlexander Motin rc = sbuf_finish(sb);
56896f556f5SAlexander Motin sbuf_delete(sb);
56996f556f5SAlexander Motin
57096f556f5SAlexander Motin return (rc);
57196f556f5SAlexander Motin }
57296f556f5SAlexander Motin
57396f556f5SAlexander Motin static int
tool_mw_write_fn(struct sysctl_oid * oidp,struct sysctl_req * req,struct tool_mw * inmw,char * ubuf,caddr_t write_buf,int * cmd_op,ssize_t * buf_offset,ssize_t * buf_size)57496f556f5SAlexander Motin tool_mw_write_fn(struct sysctl_oid *oidp, struct sysctl_req *req,
57596f556f5SAlexander Motin struct tool_mw *inmw, char *ubuf, caddr_t write_buf, int *cmd_op,
57696f556f5SAlexander Motin ssize_t *buf_offset, ssize_t *buf_size)
57796f556f5SAlexander Motin {
57896f556f5SAlexander Motin ssize_t data_buf_size;
57996f556f5SAlexander Motin uint64_t pattern = 0;
58096f556f5SAlexander Motin bool s_pflag = false;
58196f556f5SAlexander Motin void *data_buf;
58296f556f5SAlexander Motin char cmd;
58396f556f5SAlexander Motin int rc;
58496f556f5SAlexander Motin
58596f556f5SAlexander Motin if (!write_buf)
58696f556f5SAlexander Motin return (ENXIO);
58796f556f5SAlexander Motin
58896f556f5SAlexander Motin /* buf_offset and buf_size set to default in case user does not req */
58996f556f5SAlexander Motin *buf_offset = DEFAULT_MW_OFF;
59096f556f5SAlexander Motin *buf_size = DEFAULT_MW_SIZE;
59196f556f5SAlexander Motin rc = parse_mw_buf(ubuf, &cmd, buf_offset, buf_size, &pattern, &s_pflag);
59296f556f5SAlexander Motin if (rc) {
59396f556f5SAlexander Motin device_printf(inmw->tc->dev, "Wrong Command \"%c\" provided\n",
59496f556f5SAlexander Motin cmd);
59596f556f5SAlexander Motin return (rc);
59696f556f5SAlexander Motin }
59796f556f5SAlexander Motin
59896f556f5SAlexander Motin /* Check for req size and buffer limit */
59996f556f5SAlexander Motin if ((*buf_offset + *buf_size) > inmw->size) {
60096f556f5SAlexander Motin device_printf(inmw->tc->dev, "%s: configured mw size :%zi and "
60196f556f5SAlexander Motin "requested size :%zi.\n", __func__, inmw->size,
60296f556f5SAlexander Motin (*buf_offset + *buf_size));
60396f556f5SAlexander Motin *buf_offset = DEFAULT_MW_OFF;
60496f556f5SAlexander Motin *buf_size = DEFAULT_MW_SIZE;
60596f556f5SAlexander Motin rc = EINVAL;
60696f556f5SAlexander Motin goto out;
60796f556f5SAlexander Motin }
60896f556f5SAlexander Motin
60996f556f5SAlexander Motin if (cmd == 'R')
61096f556f5SAlexander Motin goto read_out;
61196f556f5SAlexander Motin else if (cmd == 'W')
61296f556f5SAlexander Motin goto write;
61396f556f5SAlexander Motin else
61496f556f5SAlexander Motin goto out;
61596f556f5SAlexander Motin
61696f556f5SAlexander Motin write:
61796f556f5SAlexander Motin data_buf_size = *buf_size;
61896f556f5SAlexander Motin data_buf = malloc(data_buf_size, M_NTB_TOOL, M_WAITOK | M_ZERO);
61996f556f5SAlexander Motin
62096f556f5SAlexander Motin if (s_pflag)
62196f556f5SAlexander Motin memset(data_buf, pattern, data_buf_size);
62296f556f5SAlexander Motin else
62396f556f5SAlexander Motin arc4rand(data_buf, data_buf_size, 1);
62496f556f5SAlexander Motin
62596f556f5SAlexander Motin memcpy(write_buf + *buf_offset, data_buf, data_buf_size);
62696f556f5SAlexander Motin
62796f556f5SAlexander Motin free(data_buf, M_NTB_TOOL);
62896f556f5SAlexander Motin
62996f556f5SAlexander Motin read_out:
63096f556f5SAlexander Motin /* cmd_op value is set to two as sysctl read call executes twice */
63196f556f5SAlexander Motin *cmd_op = 2;
63296f556f5SAlexander Motin out:
63396f556f5SAlexander Motin return (rc);
63496f556f5SAlexander Motin }
63596f556f5SAlexander Motin
63696f556f5SAlexander Motin /*
63796f556f5SAlexander Motin * Port sysctl read/write methods
63896f556f5SAlexander Motin */
63996f556f5SAlexander Motin static int
sysctl_peer_port_number(SYSCTL_HANDLER_ARGS)64096f556f5SAlexander Motin sysctl_peer_port_number(SYSCTL_HANDLER_ARGS)
64196f556f5SAlexander Motin {
64296f556f5SAlexander Motin struct tool_ctx *tc = (struct tool_ctx *)arg1;
64396f556f5SAlexander Motin int rc, pidx = arg2, peer_port;
64496f556f5SAlexander Motin
64596f556f5SAlexander Motin peer_port = ntb_peer_port_number(tc->dev, pidx);
64696f556f5SAlexander Motin rc = sysctl_handle_int(oidp, &peer_port, 0, req);
64796f556f5SAlexander Motin if (rc)
64896f556f5SAlexander Motin device_printf(tc->dev, "Peer port sysctl set failed with err="
64996f556f5SAlexander Motin "(%d).\n", rc);
65096f556f5SAlexander Motin else
65196f556f5SAlexander Motin tc->peers[pidx].port_no = peer_port;
65296f556f5SAlexander Motin
65396f556f5SAlexander Motin return (rc);
65496f556f5SAlexander Motin }
65596f556f5SAlexander Motin
65696f556f5SAlexander Motin static int
sysctl_local_port_number(SYSCTL_HANDLER_ARGS)65796f556f5SAlexander Motin sysctl_local_port_number(SYSCTL_HANDLER_ARGS)
65896f556f5SAlexander Motin {
65996f556f5SAlexander Motin struct tool_ctx *tc = (struct tool_ctx *)arg1;
66096f556f5SAlexander Motin int rc, local_port;
66196f556f5SAlexander Motin
66296f556f5SAlexander Motin local_port = ntb_port_number(tc->dev);
66396f556f5SAlexander Motin rc = sysctl_handle_int(oidp, &local_port, 0, req);
66496f556f5SAlexander Motin if (rc)
66596f556f5SAlexander Motin device_printf(tc->dev, "Local port sysctl set failed with err="
66696f556f5SAlexander Motin "(%d).\n", rc);
66796f556f5SAlexander Motin else
66896f556f5SAlexander Motin tc->port_no = local_port;
66996f556f5SAlexander Motin
67096f556f5SAlexander Motin return (rc);
67196f556f5SAlexander Motin }
67296f556f5SAlexander Motin
673dace3812SMark Johnston static void
tool_init_peers(struct tool_ctx * tc)67496f556f5SAlexander Motin tool_init_peers(struct tool_ctx *tc)
67596f556f5SAlexander Motin {
67696f556f5SAlexander Motin int pidx;
67796f556f5SAlexander Motin
67896f556f5SAlexander Motin tc->peer_cnt = ntb_peer_port_count(tc->dev);
67996f556f5SAlexander Motin tc->peers = malloc(tc->peer_cnt * sizeof(*tc->peers), M_NTB_TOOL,
68096f556f5SAlexander Motin M_WAITOK | M_ZERO);
68196f556f5SAlexander Motin for (pidx = 0; pidx < tc->peer_cnt; pidx++) {
68296f556f5SAlexander Motin tc->peers[pidx].pidx = pidx;
68396f556f5SAlexander Motin tc->peers[pidx].tc = tc;
68496f556f5SAlexander Motin }
68596f556f5SAlexander Motin }
68696f556f5SAlexander Motin
68796f556f5SAlexander Motin static void
tool_clear_peers(struct tool_ctx * tc)68896f556f5SAlexander Motin tool_clear_peers(struct tool_ctx *tc)
68996f556f5SAlexander Motin {
69096f556f5SAlexander Motin
69196f556f5SAlexander Motin free(tc->peers, M_NTB_TOOL);
69296f556f5SAlexander Motin }
69396f556f5SAlexander Motin
69496f556f5SAlexander Motin /*
69596f556f5SAlexander Motin * Link state sysctl read/write methods
69696f556f5SAlexander Motin */
69796f556f5SAlexander Motin static int
sysctl_link_handle(SYSCTL_HANDLER_ARGS)69896f556f5SAlexander Motin sysctl_link_handle(SYSCTL_HANDLER_ARGS)
69996f556f5SAlexander Motin {
70096f556f5SAlexander Motin struct tool_ctx *tc = (struct tool_ctx *)arg1;
70196f556f5SAlexander Motin char buf[TOOL_BUF_LEN];
70296f556f5SAlexander Motin int rc;
70396f556f5SAlexander Motin
70496f556f5SAlexander Motin if (req->newptr == NULL) {
70596f556f5SAlexander Motin snprintf(buf, 2, "%c", tc->link_status);
70696f556f5SAlexander Motin
70796f556f5SAlexander Motin return SYSCTL_OUT(req, buf, 2);
70896f556f5SAlexander Motin }
70996f556f5SAlexander Motin
71096f556f5SAlexander Motin rc = get_ubuf(req, buf);
71196f556f5SAlexander Motin if (rc)
71296f556f5SAlexander Motin return (rc);
71396f556f5SAlexander Motin
71496f556f5SAlexander Motin if (buf[0] == 'Y')
71596f556f5SAlexander Motin rc = ntb_link_enable(tc->dev, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
71696f556f5SAlexander Motin else if (buf[0] == 'N')
71796f556f5SAlexander Motin rc = ntb_link_disable(tc->dev);
71896f556f5SAlexander Motin else
71996f556f5SAlexander Motin rc = EINVAL;
72096f556f5SAlexander Motin
72196f556f5SAlexander Motin sscanf(buf, "%c", &tc->link_status);
72296f556f5SAlexander Motin
72396f556f5SAlexander Motin return (0);
72496f556f5SAlexander Motin }
72596f556f5SAlexander Motin
72696f556f5SAlexander Motin static int
sysctl_peer_link_handle(SYSCTL_HANDLER_ARGS)72796f556f5SAlexander Motin sysctl_peer_link_handle(SYSCTL_HANDLER_ARGS)
72896f556f5SAlexander Motin {
72996f556f5SAlexander Motin struct tool_ctx *tc = (struct tool_ctx *)arg1;
73096f556f5SAlexander Motin int up = 0, pidx = arg2;
73196f556f5SAlexander Motin char buf[TOOL_BUF_LEN];
73296f556f5SAlexander Motin
73396f556f5SAlexander Motin if (req->newptr)
73496f556f5SAlexander Motin return (0);
73596f556f5SAlexander Motin
73696f556f5SAlexander Motin up = ntb_link_is_up(tc->dev, NULL, NULL);
73796f556f5SAlexander Motin memset((void *)buf, 0, TOOL_BUF_LEN);
73896f556f5SAlexander Motin if (up & (1UL << pidx))
73996f556f5SAlexander Motin buf[0] = 'Y';
74096f556f5SAlexander Motin else
74196f556f5SAlexander Motin buf[0] = 'N';
74296f556f5SAlexander Motin
74396f556f5SAlexander Motin return SYSCTL_OUT(req, buf, sizeof(buf));
74496f556f5SAlexander Motin }
74596f556f5SAlexander Motin
74696f556f5SAlexander Motin static int
sysctl_peer_link_event_handle(SYSCTL_HANDLER_ARGS)74796f556f5SAlexander Motin sysctl_peer_link_event_handle(SYSCTL_HANDLER_ARGS)
74896f556f5SAlexander Motin {
74996f556f5SAlexander Motin struct tool_ctx *tc = (struct tool_ctx *)arg1;
75096f556f5SAlexander Motin char buf[TOOL_BUF_LEN];
75196f556f5SAlexander Motin int rc, pidx = arg2;
75296f556f5SAlexander Motin uint64_t bits;
75396f556f5SAlexander Motin
75496f556f5SAlexander Motin if (req->newptr == NULL)
75596f556f5SAlexander Motin return read_out(req, tc->link_bits);
75696f556f5SAlexander Motin
75796f556f5SAlexander Motin rc = get_ubuf(req, buf);
75896f556f5SAlexander Motin if (rc)
75996f556f5SAlexander Motin return (rc);
76096f556f5SAlexander Motin
76196f556f5SAlexander Motin sscanf(buf, "0x%jx", &bits);
76296f556f5SAlexander Motin tc->link_bits = bits;
76396f556f5SAlexander Motin tc->link_mask = (1ULL << ((pidx) % 64));
76496f556f5SAlexander Motin
76596f556f5SAlexander Motin callout_reset(&tc->link_event_timer, 1, tool_link_event_handler, tc);
76696f556f5SAlexander Motin return (0);
76796f556f5SAlexander Motin }
76896f556f5SAlexander Motin
76996f556f5SAlexander Motin /*
77096f556f5SAlexander Motin * Memory windows read/write/setting methods
77196f556f5SAlexander Motin */
77296f556f5SAlexander Motin static void
ntb_tool_load_cb(void * arg,bus_dma_segment_t * segs,int nsegs,int error)77396f556f5SAlexander Motin ntb_tool_load_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
77496f556f5SAlexander Motin {
77596f556f5SAlexander Motin struct ntb_tool_load_cb_args *cba = (struct ntb_tool_load_cb_args *)arg;
77696f556f5SAlexander Motin
77796f556f5SAlexander Motin if (!(cba->error = error))
77896f556f5SAlexander Motin cba->addr = segs[0].ds_addr;
77996f556f5SAlexander Motin }
78096f556f5SAlexander Motin
78196f556f5SAlexander Motin static int
sysctl_mw_handle(SYSCTL_HANDLER_ARGS)78296f556f5SAlexander Motin sysctl_mw_handle(SYSCTL_HANDLER_ARGS)
78396f556f5SAlexander Motin {
78496f556f5SAlexander Motin struct tool_mw *inmw = (struct tool_mw *)arg1;
78596f556f5SAlexander Motin char buf[TOOL_BUF_LEN];
78696f556f5SAlexander Motin int rc;
78796f556f5SAlexander Motin
78896f556f5SAlexander Motin if (req->newptr == NULL)
78996f556f5SAlexander Motin return tool_mw_read_fn(req, inmw, (char *)inmw->mm_base,
79096f556f5SAlexander Motin &inmw->mw_cmd_rw, inmw->mw_buf_offset, inmw->mw_buf_size,
79196f556f5SAlexander Motin "mw");
79296f556f5SAlexander Motin
79396f556f5SAlexander Motin rc = get_ubuf(req, buf);
79496f556f5SAlexander Motin if (!rc)
79596f556f5SAlexander Motin return tool_mw_write_fn(oidp, req, inmw, buf, inmw->mm_base,
79696f556f5SAlexander Motin &inmw->mw_cmd_rw, &inmw->mw_buf_offset, &inmw->mw_buf_size);
79796f556f5SAlexander Motin
79896f556f5SAlexander Motin return (rc);
79996f556f5SAlexander Motin }
80096f556f5SAlexander Motin
80196f556f5SAlexander Motin static int
tool_setup_mw(struct tool_ctx * tc,unsigned int pidx,unsigned int widx,size_t req_size)80296f556f5SAlexander Motin tool_setup_mw(struct tool_ctx *tc, unsigned int pidx, unsigned int widx,
80396f556f5SAlexander Motin size_t req_size)
80496f556f5SAlexander Motin {
80596f556f5SAlexander Motin struct tool_mw *inmw = &tc->peers[pidx].inmws[widx];
80696f556f5SAlexander Motin struct ntb_tool_load_cb_args cba;
80796f556f5SAlexander Motin int rc;
80896f556f5SAlexander Motin
80996f556f5SAlexander Motin if (req_size == 0)
81096f556f5SAlexander Motin inmw->size = roundup(inmw->phys_size, inmw->xlat_align_size);
81196f556f5SAlexander Motin else
81296f556f5SAlexander Motin inmw->size = roundup(req_size, inmw->xlat_align_size);
81396f556f5SAlexander Motin
81496f556f5SAlexander Motin device_printf(tc->dev, "mw_size %zi req_size %zi buff %zi\n",
81596f556f5SAlexander Motin inmw->phys_size, req_size, inmw->size);
81696f556f5SAlexander Motin
81796f556f5SAlexander Motin if (bus_dma_tag_create(bus_get_dma_tag(tc->dev), inmw->xlat_align, 0,
81896f556f5SAlexander Motin inmw->addr_limit, BUS_SPACE_MAXADDR, NULL, NULL, inmw->size, 1,
81996f556f5SAlexander Motin inmw->size, 0, NULL, NULL, &inmw->dma_tag)) {
82096f556f5SAlexander Motin device_printf(tc->dev, "Unable to create MW tag of size "
82196f556f5SAlexander Motin "%zu/%zu\n", inmw->phys_size, inmw->size);
82296f556f5SAlexander Motin rc = ENOMEM;
82396f556f5SAlexander Motin goto err_free_dma_var;
82496f556f5SAlexander Motin }
82596f556f5SAlexander Motin
82696f556f5SAlexander Motin if (bus_dmamem_alloc(inmw->dma_tag, (void **)&inmw->virt_addr,
82796f556f5SAlexander Motin BUS_DMA_WAITOK | BUS_DMA_ZERO, &inmw->dma_map)) {
82896f556f5SAlexander Motin device_printf(tc->dev, "Unable to allocate MW buffer of size "
82996f556f5SAlexander Motin "%zu/%zu\n", inmw->phys_size, inmw->size);
83096f556f5SAlexander Motin rc = ENOMEM;
83196f556f5SAlexander Motin goto err_free_tag_rem;
83296f556f5SAlexander Motin }
83396f556f5SAlexander Motin
83496f556f5SAlexander Motin if (bus_dmamap_load(inmw->dma_tag, inmw->dma_map, inmw->virt_addr,
83596f556f5SAlexander Motin inmw->size, ntb_tool_load_cb, &cba, BUS_DMA_NOWAIT) || cba.error) {
83696f556f5SAlexander Motin device_printf(tc->dev, "Unable to load MW buffer of size "
83796f556f5SAlexander Motin "%zu/%zu\n", inmw->phys_size, inmw->size);
83896f556f5SAlexander Motin rc = ENOMEM;
83996f556f5SAlexander Motin goto err_free_dma;
84096f556f5SAlexander Motin }
84196f556f5SAlexander Motin inmw->dma_base = cba.addr;
84296f556f5SAlexander Motin
84396f556f5SAlexander Motin rc = ntb_mw_set_trans(tc->dev, widx, inmw->dma_base, inmw->size);
84496f556f5SAlexander Motin if (rc)
84596f556f5SAlexander Motin goto err_free_mw;
84696f556f5SAlexander Motin
84796f556f5SAlexander Motin return (0);
84896f556f5SAlexander Motin
84996f556f5SAlexander Motin err_free_mw:
85096f556f5SAlexander Motin bus_dmamap_unload(inmw->dma_tag, inmw->dma_map);
85196f556f5SAlexander Motin
85296f556f5SAlexander Motin err_free_dma:
85396f556f5SAlexander Motin bus_dmamem_free(inmw->dma_tag, inmw->virt_addr, inmw->dma_map);
85496f556f5SAlexander Motin
85596f556f5SAlexander Motin err_free_tag_rem:
85696f556f5SAlexander Motin bus_dma_tag_destroy(inmw->dma_tag);
85796f556f5SAlexander Motin
85896f556f5SAlexander Motin err_free_dma_var:
85996f556f5SAlexander Motin inmw->size = 0;
86096f556f5SAlexander Motin inmw->virt_addr = 0;
86196f556f5SAlexander Motin inmw->dma_base = 0;
86296f556f5SAlexander Motin inmw->dma_tag = 0;
86396f556f5SAlexander Motin inmw->dma_map = 0;
86496f556f5SAlexander Motin
86596f556f5SAlexander Motin return (rc);
86696f556f5SAlexander Motin }
86796f556f5SAlexander Motin
86896f556f5SAlexander Motin static void
tool_free_mw(struct tool_ctx * tc,int pidx,int widx)86996f556f5SAlexander Motin tool_free_mw(struct tool_ctx *tc, int pidx, int widx)
87096f556f5SAlexander Motin {
87196f556f5SAlexander Motin struct tool_mw *inmw = &tc->peers[pidx].inmws[widx];
87296f556f5SAlexander Motin
87396f556f5SAlexander Motin if (inmw->dma_base)
87496f556f5SAlexander Motin ntb_mw_clear_trans(tc->dev, widx);
87596f556f5SAlexander Motin
87696f556f5SAlexander Motin if (inmw->virt_addr && inmw->dma_tag) {
87796f556f5SAlexander Motin bus_dmamap_unload(inmw->dma_tag, inmw->dma_map);
87896f556f5SAlexander Motin bus_dmamem_free(inmw->dma_tag, inmw->virt_addr, inmw->dma_map);
87996f556f5SAlexander Motin bus_dma_tag_destroy(inmw->dma_tag);
88096f556f5SAlexander Motin }
88196f556f5SAlexander Motin
88296f556f5SAlexander Motin inmw->virt_addr = 0;
88396f556f5SAlexander Motin inmw->dma_base = 0;
88496f556f5SAlexander Motin inmw->dma_tag = 0;
88596f556f5SAlexander Motin inmw->dma_map = 0;
88696f556f5SAlexander Motin inmw->mm_base = 0;
88796f556f5SAlexander Motin inmw->size = 0;
88896f556f5SAlexander Motin }
88996f556f5SAlexander Motin
89096f556f5SAlexander Motin static int
tool_mw_trans_read(struct tool_mw * inmw,struct sysctl_req * req)89196f556f5SAlexander Motin tool_mw_trans_read(struct tool_mw *inmw, struct sysctl_req *req)
89296f556f5SAlexander Motin {
89396f556f5SAlexander Motin ssize_t buf_size = 512;
89496f556f5SAlexander Motin struct sbuf *sb;
89596f556f5SAlexander Motin int rc = 0;
89696f556f5SAlexander Motin
89796f556f5SAlexander Motin sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
89896f556f5SAlexander Motin if (sb == NULL) {
89996f556f5SAlexander Motin rc = sb->s_error;
90096f556f5SAlexander Motin return (rc);
90196f556f5SAlexander Motin }
90296f556f5SAlexander Motin
90396f556f5SAlexander Motin sbuf_printf(sb, "\nInbound MW \t%d\n", inmw->widx);
90496f556f5SAlexander Motin sbuf_printf(sb, "Port \t%d (%d)\n",
90596f556f5SAlexander Motin ntb_peer_port_number(inmw->tc->dev, inmw->pidx), inmw->pidx);
90696f556f5SAlexander Motin sbuf_printf(sb, "Window Address \t%p\n", inmw->mm_base);
90796f556f5SAlexander Motin sbuf_printf(sb, "DMA Address \t0x%016llx\n", (long long)inmw->dma_base);
90896f556f5SAlexander Motin sbuf_printf(sb, "Window Size \t0x%016zx[p]\n", inmw->size);
90996f556f5SAlexander Motin sbuf_printf(sb, "Alignment \t0x%016zx[p]\n", inmw->xlat_align);
91096f556f5SAlexander Motin sbuf_printf(sb, "Size Alignment \t0x%016zx[p]\n",
91196f556f5SAlexander Motin inmw->xlat_align_size);
91296f556f5SAlexander Motin sbuf_printf(sb, "Size Max \t0x%016zx[p]\n", inmw->phys_size);
91396f556f5SAlexander Motin
91496f556f5SAlexander Motin rc = sbuf_finish(sb);
91596f556f5SAlexander Motin sbuf_delete(sb);
91696f556f5SAlexander Motin
91796f556f5SAlexander Motin return (rc);
91896f556f5SAlexander Motin }
91996f556f5SAlexander Motin
92096f556f5SAlexander Motin static int
tool_mw_trans_write(struct sysctl_oid * oidp,struct sysctl_req * req,struct tool_mw * inmw,size_t wsize)92196f556f5SAlexander Motin tool_mw_trans_write(struct sysctl_oid *oidp, struct sysctl_req *req,
92296f556f5SAlexander Motin struct tool_mw *inmw, size_t wsize)
92396f556f5SAlexander Motin {
92496f556f5SAlexander Motin struct tool_ctx *tc = inmw->tc;
92596f556f5SAlexander Motin int rc = 0;
92696f556f5SAlexander Motin
92796f556f5SAlexander Motin if (wsize == 0)
92896f556f5SAlexander Motin return (EINVAL);
92996f556f5SAlexander Motin
93096f556f5SAlexander Motin /* No need to re-setup mw */
93196f556f5SAlexander Motin if (inmw->size == wsize)
93296f556f5SAlexander Motin return (0);
93396f556f5SAlexander Motin
93496f556f5SAlexander Motin /* free mw dma buffer */
93596f556f5SAlexander Motin if (inmw->size)
93696f556f5SAlexander Motin tool_free_mw(tc, inmw->pidx, inmw->widx);
93796f556f5SAlexander Motin
93896f556f5SAlexander Motin rc = tool_setup_mw(tc, inmw->pidx, inmw->widx, wsize);
93996f556f5SAlexander Motin
94096f556f5SAlexander Motin return (rc);
94196f556f5SAlexander Motin }
94296f556f5SAlexander Motin
94396f556f5SAlexander Motin static int
sysctl_mw_trans_handler(SYSCTL_HANDLER_ARGS)94496f556f5SAlexander Motin sysctl_mw_trans_handler(SYSCTL_HANDLER_ARGS)
94596f556f5SAlexander Motin {
94696f556f5SAlexander Motin struct tool_mw *inmw = (struct tool_mw *)arg1;
94796f556f5SAlexander Motin char buf[TOOL_BUF_LEN];
94896f556f5SAlexander Motin ssize_t wsize;
94996f556f5SAlexander Motin int rc;
95096f556f5SAlexander Motin
95196f556f5SAlexander Motin if (req->newptr == NULL)
95296f556f5SAlexander Motin return tool_mw_trans_read(inmw, req);
95396f556f5SAlexander Motin
95496f556f5SAlexander Motin rc = get_ubuf(req, buf);
95596f556f5SAlexander Motin if (rc == 0) {
95696f556f5SAlexander Motin sscanf(buf, "%zi", &wsize);
95796f556f5SAlexander Motin return tool_mw_trans_write(oidp, req, inmw, wsize);
95896f556f5SAlexander Motin }
95996f556f5SAlexander Motin
96096f556f5SAlexander Motin return (rc);
96196f556f5SAlexander Motin }
96296f556f5SAlexander Motin
96396f556f5SAlexander Motin static int
sysctl_peer_mw_handle(SYSCTL_HANDLER_ARGS)96496f556f5SAlexander Motin sysctl_peer_mw_handle(SYSCTL_HANDLER_ARGS)
96596f556f5SAlexander Motin {
96696f556f5SAlexander Motin struct tool_mw *inmw = (struct tool_mw *)arg1;
96796f556f5SAlexander Motin char buf[TOOL_BUF_LEN];
96896f556f5SAlexander Motin int rc;
96996f556f5SAlexander Motin
97096f556f5SAlexander Motin if (req->newptr == NULL)
97196f556f5SAlexander Motin return tool_mw_read_fn(req, inmw, (char *)inmw->virt_addr,
97296f556f5SAlexander Motin &inmw->mw_peer_cmd_rw, inmw->mw_peer_buf_offset,
97396f556f5SAlexander Motin inmw->mw_peer_buf_size, "mw");
97496f556f5SAlexander Motin
97596f556f5SAlexander Motin rc = get_ubuf(req, buf);
97696f556f5SAlexander Motin if (rc == 0)
97796f556f5SAlexander Motin return tool_mw_write_fn(oidp, req, inmw, buf, inmw->virt_addr,
97896f556f5SAlexander Motin &inmw->mw_peer_cmd_rw, &inmw->mw_peer_buf_offset,
97996f556f5SAlexander Motin &inmw->mw_peer_buf_size);
98096f556f5SAlexander Motin
98196f556f5SAlexander Motin return (rc);
98296f556f5SAlexander Motin }
98396f556f5SAlexander Motin
tool_clear_mws(struct tool_ctx * tc)98496f556f5SAlexander Motin static void tool_clear_mws(struct tool_ctx *tc)
98596f556f5SAlexander Motin {
98696f556f5SAlexander Motin int widx, pidx;
98796f556f5SAlexander Motin
98896f556f5SAlexander Motin /* Free outbound memory windows */
98996f556f5SAlexander Motin for (pidx = 0; pidx < tc->peer_cnt; pidx++) {
99096f556f5SAlexander Motin for (widx = 0; widx < tc->peers[pidx].inmw_cnt; widx++)
99196f556f5SAlexander Motin tool_free_mw(tc, pidx, widx);
99296f556f5SAlexander Motin free(tc->peers[pidx].inmws, M_NTB_TOOL);
99396f556f5SAlexander Motin }
99496f556f5SAlexander Motin }
99596f556f5SAlexander Motin
99696f556f5SAlexander Motin static int
tool_init_mws(struct tool_ctx * tc)99796f556f5SAlexander Motin tool_init_mws(struct tool_ctx *tc)
99896f556f5SAlexander Motin {
99996f556f5SAlexander Motin struct tool_mw *mw;
100096f556f5SAlexander Motin int widx, pidx, rc;
100196f556f5SAlexander Motin
100296f556f5SAlexander Motin /* Initialize inbound memory windows and outbound MWs wrapper */
100396f556f5SAlexander Motin for (pidx = 0; pidx < tc->peer_cnt; pidx++) {
100496f556f5SAlexander Motin tc->peers[pidx].inmw_cnt = ntb_mw_count(tc->dev);
100596f556f5SAlexander Motin tc->peers[pidx].inmws = malloc(tc->peers[pidx].inmw_cnt *
100696f556f5SAlexander Motin sizeof(*tc->peers[pidx].inmws), M_NTB_TOOL,
100796f556f5SAlexander Motin M_WAITOK | M_ZERO);
100896f556f5SAlexander Motin
100996f556f5SAlexander Motin for (widx = 0; widx < tc->peers[pidx].inmw_cnt; widx++) {
101096f556f5SAlexander Motin mw = &tc->peers[pidx].inmws[widx];
101196f556f5SAlexander Motin memset((void *)mw, 0, sizeof(*mw));
101296f556f5SAlexander Motin mw->tc = tc;
101396f556f5SAlexander Motin mw->widx = widx;
101496f556f5SAlexander Motin mw->pidx = pidx;
101596f556f5SAlexander Motin mw->mw_buf_offset = DEFAULT_MW_OFF;
101696f556f5SAlexander Motin mw->mw_buf_size = DEFAULT_MW_SIZE;
101796f556f5SAlexander Motin /* get the tx buff details for each mw attached with each peer */
101896f556f5SAlexander Motin rc = ntb_mw_get_range(tc->dev, widx, &mw->phys_addr,
101996f556f5SAlexander Motin &mw->mm_base, &mw->phys_size, &mw->xlat_align,
102096f556f5SAlexander Motin &mw->xlat_align_size, &mw->addr_limit);
102196f556f5SAlexander Motin if (rc)
102296f556f5SAlexander Motin goto free_mws;
102396f556f5SAlexander Motin }
102496f556f5SAlexander Motin }
102596f556f5SAlexander Motin
102696f556f5SAlexander Motin return (0);
102796f556f5SAlexander Motin
102896f556f5SAlexander Motin free_mws:
102996f556f5SAlexander Motin tool_clear_mws(tc);
103096f556f5SAlexander Motin return (rc);
103196f556f5SAlexander Motin }
103296f556f5SAlexander Motin
103396f556f5SAlexander Motin /*
103496f556f5SAlexander Motin * Doorbell handler for read/write
103596f556f5SAlexander Motin */
103696f556f5SAlexander Motin static int
sysctl_db_handle(SYSCTL_HANDLER_ARGS)103796f556f5SAlexander Motin sysctl_db_handle(SYSCTL_HANDLER_ARGS)
103896f556f5SAlexander Motin {
103996f556f5SAlexander Motin struct tool_ctx *tc = (struct tool_ctx *)arg1;
104096f556f5SAlexander Motin char buf[TOOL_BUF_LEN];
104196f556f5SAlexander Motin uint64_t db_bits;
104296f556f5SAlexander Motin int rc;
104396f556f5SAlexander Motin
104496f556f5SAlexander Motin if (req->newptr == NULL) {
104596f556f5SAlexander Motin db_bits = ntb_db_read(tc->dev);
104696f556f5SAlexander Motin return read_out(req, db_bits);
104796f556f5SAlexander Motin }
104896f556f5SAlexander Motin
104996f556f5SAlexander Motin rc = get_ubuf(req, buf);
105096f556f5SAlexander Motin if (rc == 0)
105196f556f5SAlexander Motin return tool_fn_write(tc, oidp, req, buf, NULL, false, NULL,
105296f556f5SAlexander Motin ntb_db_clear);
105396f556f5SAlexander Motin
105496f556f5SAlexander Motin return (rc);
105596f556f5SAlexander Motin }
105696f556f5SAlexander Motin
105796f556f5SAlexander Motin static int
sysctl_db_valid_mask_handle(SYSCTL_HANDLER_ARGS)105896f556f5SAlexander Motin sysctl_db_valid_mask_handle(SYSCTL_HANDLER_ARGS)
105996f556f5SAlexander Motin {
106096f556f5SAlexander Motin struct tool_ctx *tc = (struct tool_ctx *)arg1;
106196f556f5SAlexander Motin
106296f556f5SAlexander Motin tc->db_valid_mask = ntb_db_valid_mask(tc->dev);
106396f556f5SAlexander Motin if (!tc->db_valid_mask) {
106496f556f5SAlexander Motin device_printf(tc->dev, "Error getting db_valid_mask from "
106596f556f5SAlexander Motin "hw driver\n");
106696f556f5SAlexander Motin return (EINVAL);
106796f556f5SAlexander Motin } else {
106896f556f5SAlexander Motin return read_out(req, tc->db_valid_mask);
106996f556f5SAlexander Motin }
107096f556f5SAlexander Motin }
107196f556f5SAlexander Motin
107296f556f5SAlexander Motin static int
sysctl_db_mask_handle(SYSCTL_HANDLER_ARGS)107396f556f5SAlexander Motin sysctl_db_mask_handle(SYSCTL_HANDLER_ARGS)
107496f556f5SAlexander Motin {
107596f556f5SAlexander Motin struct tool_ctx *tc = (struct tool_ctx *)arg1;
107696f556f5SAlexander Motin char buf[TOOL_BUF_LEN];
107796f556f5SAlexander Motin int rc;
107896f556f5SAlexander Motin
107996f556f5SAlexander Motin if (req->newptr == NULL) {
108096f556f5SAlexander Motin if (tc->db_mask_val == 0)
108196f556f5SAlexander Motin ntb_db_valid_mask(tc->dev);
108296f556f5SAlexander Motin return tool_fn_read(tc, req, NULL, tc->db_mask_val);
108396f556f5SAlexander Motin }
108496f556f5SAlexander Motin
108596f556f5SAlexander Motin rc = get_ubuf(req, buf);
108696f556f5SAlexander Motin if (rc == 0)
108796f556f5SAlexander Motin return tool_fn_write(tc, oidp, req, buf, &tc->db_mask_val, true,
108896f556f5SAlexander Motin ntb_db_set_mask, ntb_db_clear_mask);
108996f556f5SAlexander Motin
109096f556f5SAlexander Motin return (rc);
109196f556f5SAlexander Motin }
109296f556f5SAlexander Motin
109396f556f5SAlexander Motin static int
sysctl_peer_db_handle(SYSCTL_HANDLER_ARGS)109496f556f5SAlexander Motin sysctl_peer_db_handle(SYSCTL_HANDLER_ARGS)
109596f556f5SAlexander Motin {
109696f556f5SAlexander Motin struct tool_ctx *tc = (struct tool_ctx *)arg1;
109796f556f5SAlexander Motin char buf[TOOL_BUF_LEN];
109896f556f5SAlexander Motin int rc;
109996f556f5SAlexander Motin
110096f556f5SAlexander Motin if (req->newptr == NULL)
110196f556f5SAlexander Motin return tool_fn_read(tc, req, NULL, tc->peer_db_val);
110296f556f5SAlexander Motin
110396f556f5SAlexander Motin rc = get_ubuf(req, buf);
110496f556f5SAlexander Motin if (rc == 0)
110596f556f5SAlexander Motin return tool_fn_write(tc, oidp, req, buf, &tc->peer_db_val,
110696f556f5SAlexander Motin false, ntb_peer_db_set, NULL);
110796f556f5SAlexander Motin
110896f556f5SAlexander Motin return (rc);
110996f556f5SAlexander Motin }
111096f556f5SAlexander Motin
111196f556f5SAlexander Motin static int
sysctl_peer_db_mask_handle(SYSCTL_HANDLER_ARGS)111296f556f5SAlexander Motin sysctl_peer_db_mask_handle(SYSCTL_HANDLER_ARGS)
111396f556f5SAlexander Motin {
111496f556f5SAlexander Motin struct tool_ctx *tc = (struct tool_ctx *)arg1;
111596f556f5SAlexander Motin char buf[TOOL_BUF_LEN];
111696f556f5SAlexander Motin int rc;
111796f556f5SAlexander Motin
111896f556f5SAlexander Motin if (req->newptr == NULL){
111996f556f5SAlexander Motin if (tc->peer_db_mask_val == 0)
112096f556f5SAlexander Motin ntb_db_valid_mask(tc->dev);
112196f556f5SAlexander Motin return tool_fn_read(tc, req, NULL, tc->peer_db_mask_val);
112296f556f5SAlexander Motin }
112396f556f5SAlexander Motin
112496f556f5SAlexander Motin rc = get_ubuf(req, buf);
112596f556f5SAlexander Motin if (rc == 0)
112696f556f5SAlexander Motin return tool_fn_write(tc, oidp, req, buf, &tc->peer_db_mask_val,
112796f556f5SAlexander Motin true, NULL, NULL);
112896f556f5SAlexander Motin
112996f556f5SAlexander Motin return (rc);
113096f556f5SAlexander Motin }
113196f556f5SAlexander Motin
113296f556f5SAlexander Motin static int
sysctl_db_event_handle(SYSCTL_HANDLER_ARGS)113396f556f5SAlexander Motin sysctl_db_event_handle(SYSCTL_HANDLER_ARGS)
113496f556f5SAlexander Motin {
113596f556f5SAlexander Motin struct tool_ctx *tc = (struct tool_ctx *)arg1;
113696f556f5SAlexander Motin char buf[TOOL_BUF_LEN];
113796f556f5SAlexander Motin uint64_t bits;
113896f556f5SAlexander Motin int rc;
113996f556f5SAlexander Motin
114096f556f5SAlexander Motin if (req->newptr == NULL)
114196f556f5SAlexander Motin return read_out(req, tc->db_event_val);
114296f556f5SAlexander Motin
114396f556f5SAlexander Motin rc = get_ubuf(req, buf);
114496f556f5SAlexander Motin if (rc)
114596f556f5SAlexander Motin return (rc);
114696f556f5SAlexander Motin
114796f556f5SAlexander Motin sscanf(buf, "%ju", &bits);
114896f556f5SAlexander Motin tc->db_event_val = bits;
114996f556f5SAlexander Motin callout_reset(&tc->db_event_timer, 1, tool_db_event_handler, tc);
115096f556f5SAlexander Motin
115196f556f5SAlexander Motin return (0);
115296f556f5SAlexander Motin }
115396f556f5SAlexander Motin
115496f556f5SAlexander Motin /*
115596f556f5SAlexander Motin * Scratchpads read/write methods
115696f556f5SAlexander Motin */
115796f556f5SAlexander Motin static int
sysctl_spad_handle(SYSCTL_HANDLER_ARGS)115896f556f5SAlexander Motin sysctl_spad_handle(SYSCTL_HANDLER_ARGS)
115996f556f5SAlexander Motin {
116096f556f5SAlexander Motin struct tool_ctx *tc = (struct tool_ctx *)arg1;
116196f556f5SAlexander Motin unsigned int sidx = arg2;
116296f556f5SAlexander Motin char buf[TOOL_BUF_LEN];
116396f556f5SAlexander Motin uint32_t bits;
116496f556f5SAlexander Motin int rc;
116596f556f5SAlexander Motin
116696f556f5SAlexander Motin if (req->newptr == NULL) {
116796f556f5SAlexander Motin rc = ntb_spad_read(tc->dev, sidx, &bits);
116896f556f5SAlexander Motin if (rc)
116996f556f5SAlexander Motin return (rc);
117096f556f5SAlexander Motin else
117196f556f5SAlexander Motin return read_out(req, (uint64_t )bits);
117296f556f5SAlexander Motin }
117396f556f5SAlexander Motin
117496f556f5SAlexander Motin rc = get_ubuf(req, buf);
117596f556f5SAlexander Motin if (rc == 0) {
117696f556f5SAlexander Motin sscanf(buf, "%i", &bits);
117796f556f5SAlexander Motin return ntb_spad_write(tc->dev, sidx, bits);
117896f556f5SAlexander Motin }
117996f556f5SAlexander Motin
118096f556f5SAlexander Motin return (rc);
118196f556f5SAlexander Motin }
118296f556f5SAlexander Motin
118396f556f5SAlexander Motin static int
sysctl_peer_spad_handle(SYSCTL_HANDLER_ARGS)118496f556f5SAlexander Motin sysctl_peer_spad_handle(SYSCTL_HANDLER_ARGS)
118596f556f5SAlexander Motin {
118696f556f5SAlexander Motin struct tool_ctx *tc = (struct tool_ctx *)arg1;
118796f556f5SAlexander Motin unsigned int sidx = arg2;
118896f556f5SAlexander Motin char buf[TOOL_BUF_LEN];
118996f556f5SAlexander Motin uint32_t bits;
119096f556f5SAlexander Motin int rc;
119196f556f5SAlexander Motin
119296f556f5SAlexander Motin if (req->newptr == NULL) {
119396f556f5SAlexander Motin rc = ntb_peer_spad_read(tc->dev, sidx, &bits);
119496f556f5SAlexander Motin if (rc)
119596f556f5SAlexander Motin return (rc);
119696f556f5SAlexander Motin else
119796f556f5SAlexander Motin return read_out(req, (uint64_t )bits);
119896f556f5SAlexander Motin }
119996f556f5SAlexander Motin
120096f556f5SAlexander Motin rc = get_ubuf(req, buf);
120196f556f5SAlexander Motin if (rc == 0) {
120296f556f5SAlexander Motin sscanf(buf, "%i", &bits);
120396f556f5SAlexander Motin return ntb_peer_spad_write(tc->dev, sidx, bits);
120496f556f5SAlexander Motin }
120596f556f5SAlexander Motin
120696f556f5SAlexander Motin return (rc);
120796f556f5SAlexander Motin }
120896f556f5SAlexander Motin
1209dace3812SMark Johnston static void
tool_init_spads(struct tool_ctx * tc)121096f556f5SAlexander Motin tool_init_spads(struct tool_ctx *tc)
121196f556f5SAlexander Motin {
121296f556f5SAlexander Motin int sidx, pidx;
121396f556f5SAlexander Motin
121496f556f5SAlexander Motin /* Initialize inbound scratchpad structures */
121596f556f5SAlexander Motin tc->inspad_cnt = ntb_spad_count(tc->dev);
121696f556f5SAlexander Motin tc->inspads = malloc(tc->inspad_cnt * sizeof(*tc->inspads), M_NTB_TOOL,
121796f556f5SAlexander Motin M_WAITOK | M_ZERO);
121896f556f5SAlexander Motin
121996f556f5SAlexander Motin for (sidx = 0; sidx < tc->inspad_cnt; sidx++) {
122096f556f5SAlexander Motin tc->inspads[sidx].sidx = sidx;
122196f556f5SAlexander Motin tc->inspads[sidx].pidx = -1;
122296f556f5SAlexander Motin tc->inspads[sidx].tc = tc;
122396f556f5SAlexander Motin }
122496f556f5SAlexander Motin
122596f556f5SAlexander Motin /* Initialize outbound scratchpad structures */
122696f556f5SAlexander Motin for (pidx = 0; pidx < tc->peer_cnt; pidx++) {
122796f556f5SAlexander Motin tc->peers[pidx].outspad_cnt = ntb_spad_count(tc->dev);
122896f556f5SAlexander Motin tc->peers[pidx].outspads = malloc(tc->peers[pidx].outspad_cnt *
122996f556f5SAlexander Motin sizeof(*tc->peers[pidx].outspads), M_NTB_TOOL, M_WAITOK |
123096f556f5SAlexander Motin M_ZERO);
123196f556f5SAlexander Motin
123296f556f5SAlexander Motin for (sidx = 0; sidx < tc->peers[pidx].outspad_cnt; sidx++) {
123396f556f5SAlexander Motin tc->peers[pidx].outspads[sidx].sidx = sidx;
123496f556f5SAlexander Motin tc->peers[pidx].outspads[sidx].pidx = pidx;
123596f556f5SAlexander Motin tc->peers[pidx].outspads[sidx].tc = tc;
123696f556f5SAlexander Motin }
123796f556f5SAlexander Motin }
123896f556f5SAlexander Motin }
123996f556f5SAlexander Motin
124096f556f5SAlexander Motin static void
tool_clear_spads(struct tool_ctx * tc)124196f556f5SAlexander Motin tool_clear_spads(struct tool_ctx *tc)
124296f556f5SAlexander Motin {
124396f556f5SAlexander Motin int pidx;
124496f556f5SAlexander Motin
124596f556f5SAlexander Motin /* Free local inspads. */
124696f556f5SAlexander Motin free(tc->inspads, M_NTB_TOOL);
124796f556f5SAlexander Motin
124896f556f5SAlexander Motin /* Free outspads for each peer. */
124996f556f5SAlexander Motin for (pidx = 0; pidx < tc->peer_cnt; pidx++)
125096f556f5SAlexander Motin free(tc->peers[pidx].outspads, M_NTB_TOOL);
125196f556f5SAlexander Motin }
125296f556f5SAlexander Motin
125396f556f5SAlexander Motin /*
125496f556f5SAlexander Motin * Initialization methods
125596f556f5SAlexander Motin */
125696f556f5SAlexander Motin static int
tool_check_ntb(struct tool_ctx * tc)125796f556f5SAlexander Motin tool_check_ntb(struct tool_ctx *tc)
125896f556f5SAlexander Motin {
125996f556f5SAlexander Motin
126096f556f5SAlexander Motin /* create and initialize link callout handler */
126196f556f5SAlexander Motin callout_init(&tc->link_event_timer, 1);
126296f556f5SAlexander Motin
126396f556f5SAlexander Motin /* create and initialize db callout handler */
126496f556f5SAlexander Motin callout_init(&tc->db_event_timer, 1);
126596f556f5SAlexander Motin
126696f556f5SAlexander Motin /* Initialize sysctl read out values to default */
126796f556f5SAlexander Motin tc->link_status = 'U';
126896f556f5SAlexander Motin tc->db_mask_val = 0;
126996f556f5SAlexander Motin tc->peer_db_val = 0;
127096f556f5SAlexander Motin tc->peer_db_mask_val = 0;
127196f556f5SAlexander Motin tc->db_event_val = 0;
127296f556f5SAlexander Motin tc->link_bits = 0;
127396f556f5SAlexander Motin
127496f556f5SAlexander Motin return (0);
127596f556f5SAlexander Motin }
127696f556f5SAlexander Motin
127796f556f5SAlexander Motin static void
tool_clear_data(struct tool_ctx * tc)127896f556f5SAlexander Motin tool_clear_data(struct tool_ctx *tc)
127996f556f5SAlexander Motin {
128096f556f5SAlexander Motin
128196f556f5SAlexander Motin callout_drain(&tc->link_event_timer);
128296f556f5SAlexander Motin callout_drain(&tc->db_event_timer);
128396f556f5SAlexander Motin }
128496f556f5SAlexander Motin
128596f556f5SAlexander Motin static int
tool_init_ntb(struct tool_ctx * tc)128696f556f5SAlexander Motin tool_init_ntb(struct tool_ctx *tc)
128796f556f5SAlexander Motin {
128896f556f5SAlexander Motin
128996f556f5SAlexander Motin return ntb_set_ctx(tc->dev, tc, &tool_ops);
129096f556f5SAlexander Motin }
129196f556f5SAlexander Motin
129296f556f5SAlexander Motin static void
tool_clear_ntb(struct tool_ctx * tc)129396f556f5SAlexander Motin tool_clear_ntb(struct tool_ctx *tc)
129496f556f5SAlexander Motin {
129596f556f5SAlexander Motin
129696f556f5SAlexander Motin ntb_clear_ctx(tc->dev);
129796f556f5SAlexander Motin ntb_link_disable(tc->dev);
129896f556f5SAlexander Motin }
129996f556f5SAlexander Motin
130096f556f5SAlexander Motin /*
130196f556f5SAlexander Motin * Current sysctl implementation is made such that it gets attached to the
130296f556f5SAlexander Motin * device and while detach it gets cleared automatically.
130396f556f5SAlexander Motin */
130496f556f5SAlexander Motin static void
tool_setup_sysctl(struct tool_ctx * tc)130596f556f5SAlexander Motin tool_setup_sysctl(struct tool_ctx *tc)
130696f556f5SAlexander Motin {
130796f556f5SAlexander Motin char buf[TOOL_BUF_LEN], desc[TOOL_BUF_LEN];
130896f556f5SAlexander Motin struct sysctl_oid_list *top, *peer_top;
130996f556f5SAlexander Motin struct sysctl_oid *parent, *peer;
131096f556f5SAlexander Motin struct sysctl_ctx_list *clist;
131196f556f5SAlexander Motin unsigned int pidx, sidx, widx;
131296f556f5SAlexander Motin
131396f556f5SAlexander Motin clist = device_get_sysctl_ctx(tc->dev);
131496f556f5SAlexander Motin parent = device_get_sysctl_tree(tc->dev);
131596f556f5SAlexander Motin top = SYSCTL_CHILDREN(parent);
131696f556f5SAlexander Motin
131796f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, top, OID_AUTO, "port", CTLTYPE_UINT |
131896f556f5SAlexander Motin CTLFLAG_RDTUN | CTLFLAG_MPSAFE, tc, 0, sysctl_local_port_number,
131996f556f5SAlexander Motin "IU", "local port number");
132096f556f5SAlexander Motin
132196f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, top, OID_AUTO, "link", CTLTYPE_STRING |
132296f556f5SAlexander Motin CTLFLAG_RWTUN | CTLFLAG_MPSAFE, tc, 0, sysctl_link_handle,
132396f556f5SAlexander Motin "IU", "link info");
132496f556f5SAlexander Motin
132596f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, top, OID_AUTO, "db", CTLTYPE_STRING |
132696f556f5SAlexander Motin CTLFLAG_RWTUN | CTLFLAG_MPSAFE, tc, 0, sysctl_db_handle,
132796f556f5SAlexander Motin "A", "db info");
132896f556f5SAlexander Motin
132996f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, top, OID_AUTO, "db_valid_mask", CTLTYPE_STRING |
133096f556f5SAlexander Motin CTLFLAG_RD | CTLFLAG_MPSAFE, tc, 0, sysctl_db_valid_mask_handle,
133196f556f5SAlexander Motin "A", "db valid mask");
133296f556f5SAlexander Motin
133396f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, top, OID_AUTO, "db_mask", CTLTYPE_STRING |
133496f556f5SAlexander Motin CTLFLAG_RWTUN | CTLFLAG_MPSAFE, tc, 0, sysctl_db_mask_handle,
133596f556f5SAlexander Motin "A", "db mask");
133696f556f5SAlexander Motin
133796f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, top, OID_AUTO, "db_event", CTLTYPE_STRING |
133896f556f5SAlexander Motin CTLFLAG_WR | CTLFLAG_MPSAFE, tc, 0, sysctl_db_event_handle,
133996f556f5SAlexander Motin "A", "db event");
134096f556f5SAlexander Motin
134196f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, top, OID_AUTO, "peer_db", CTLTYPE_STRING |
134296f556f5SAlexander Motin CTLFLAG_RWTUN | CTLFLAG_MPSAFE, tc, 0, sysctl_peer_db_handle,
134396f556f5SAlexander Motin "A", "peer db");
134496f556f5SAlexander Motin
134596f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, top, OID_AUTO, "peer_db_mask", CTLTYPE_STRING |
134696f556f5SAlexander Motin CTLFLAG_RWTUN | CTLFLAG_MPSAFE, tc, 0, sysctl_peer_db_mask_handle,
134796f556f5SAlexander Motin "IU", "peer db mask info");
134896f556f5SAlexander Motin
134996f556f5SAlexander Motin if (tc->inspad_cnt != 0) {
135096f556f5SAlexander Motin for (sidx = 0; sidx < tc->inspad_cnt; sidx++) {
135196f556f5SAlexander Motin snprintf(buf, sizeof(buf), "spad%d", sidx);
135296f556f5SAlexander Motin snprintf(desc, sizeof(desc), "spad%d info", sidx);
135396f556f5SAlexander Motin
135496f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, top, OID_AUTO, buf,
135596f556f5SAlexander Motin CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
135696f556f5SAlexander Motin tc, sidx, sysctl_spad_handle, "IU", desc);
135796f556f5SAlexander Motin }
135896f556f5SAlexander Motin }
135996f556f5SAlexander Motin
136096f556f5SAlexander Motin for (pidx = 0; pidx < tc->peer_cnt; pidx++) {
136196f556f5SAlexander Motin snprintf(buf, sizeof(buf), "peer%d", pidx);
136296f556f5SAlexander Motin
13637029da5cSPawel Biernacki peer = SYSCTL_ADD_NODE(clist, top, OID_AUTO, buf,
13647029da5cSPawel Biernacki CTLFLAG_RW | CTLFLAG_MPSAFE, 0, buf);
136596f556f5SAlexander Motin peer_top = SYSCTL_CHILDREN(peer);
136696f556f5SAlexander Motin
136796f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, peer_top, OID_AUTO, "port",
136896f556f5SAlexander Motin CTLTYPE_UINT | CTLFLAG_RDTUN | CTLFLAG_MPSAFE, tc, pidx,
136996f556f5SAlexander Motin sysctl_peer_port_number, "IU", "peer port number");
137096f556f5SAlexander Motin
137196f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, peer_top, OID_AUTO, "link",
137296f556f5SAlexander Motin CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, tc, pidx,
137396f556f5SAlexander Motin sysctl_peer_link_handle, "IU", "peer_link info");
137496f556f5SAlexander Motin
137596f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, peer_top, OID_AUTO, "link_event",
137696f556f5SAlexander Motin CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, tc, pidx,
137796f556f5SAlexander Motin sysctl_peer_link_event_handle, "IU", "link event");
137896f556f5SAlexander Motin
137996f556f5SAlexander Motin for (widx = 0; widx < tc->peers[pidx].inmw_cnt; widx++) {
138096f556f5SAlexander Motin snprintf(buf, sizeof(buf), "mw_trans%d", widx);
138196f556f5SAlexander Motin snprintf(desc, sizeof(desc), "mw trans%d info", widx);
138296f556f5SAlexander Motin
138396f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, peer_top, OID_AUTO, buf,
138496f556f5SAlexander Motin CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
138596f556f5SAlexander Motin &tc->peers[pidx].inmws[widx], 0,
138696f556f5SAlexander Motin sysctl_mw_trans_handler, "IU", desc);
138796f556f5SAlexander Motin
138896f556f5SAlexander Motin snprintf(buf, sizeof(buf), "mw%d", widx);
138996f556f5SAlexander Motin snprintf(desc, sizeof(desc), "mw%d info", widx);
139096f556f5SAlexander Motin
139196f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, peer_top, OID_AUTO, buf,
139296f556f5SAlexander Motin CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
139396f556f5SAlexander Motin &tc->peers[pidx].inmws[widx], 0,
139496f556f5SAlexander Motin sysctl_mw_handle, "IU", desc);
139596f556f5SAlexander Motin
139696f556f5SAlexander Motin snprintf(buf, sizeof(buf), "peer_mw%d", widx);
139796f556f5SAlexander Motin snprintf(desc, sizeof(desc), "peer_mw%d info", widx);
139896f556f5SAlexander Motin
139996f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, peer_top, OID_AUTO, buf,
140096f556f5SAlexander Motin CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
140196f556f5SAlexander Motin &tc->peers[pidx].inmws[widx], 0,
140296f556f5SAlexander Motin sysctl_peer_mw_handle, "IU", desc);
140396f556f5SAlexander Motin }
140496f556f5SAlexander Motin
140596f556f5SAlexander Motin for (sidx = 0; sidx < tc->peers[pidx].outspad_cnt; sidx++) {
140696f556f5SAlexander Motin snprintf(buf, sizeof(buf), "spad%d", sidx);
140796f556f5SAlexander Motin snprintf(desc, sizeof(desc), "spad%d info", sidx);
140896f556f5SAlexander Motin
140996f556f5SAlexander Motin SYSCTL_ADD_PROC(clist, peer_top, OID_AUTO, buf,
141096f556f5SAlexander Motin CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
141196f556f5SAlexander Motin tc, sidx, sysctl_peer_spad_handle, "IU", desc);
141296f556f5SAlexander Motin }
141396f556f5SAlexander Motin }
141496f556f5SAlexander Motin }
141596f556f5SAlexander Motin
141696f556f5SAlexander Motin static int
ntb_tool_probe(device_t dev)141796f556f5SAlexander Motin ntb_tool_probe(device_t dev)
141896f556f5SAlexander Motin {
141996f556f5SAlexander Motin device_set_desc(dev, "NTB TOOL");
142096f556f5SAlexander Motin return (0);
142196f556f5SAlexander Motin }
142296f556f5SAlexander Motin
142396f556f5SAlexander Motin static int
ntb_tool_attach(device_t dev)142496f556f5SAlexander Motin ntb_tool_attach(device_t dev)
142596f556f5SAlexander Motin {
142696f556f5SAlexander Motin struct tool_ctx *tc = device_get_softc(dev);
142796f556f5SAlexander Motin int rc = 0;
142896f556f5SAlexander Motin
142996f556f5SAlexander Motin tc->dev = dev;
143096f556f5SAlexander Motin rc = tool_check_ntb(tc);
143196f556f5SAlexander Motin if (rc)
143296f556f5SAlexander Motin goto out;
143396f556f5SAlexander Motin
1434dace3812SMark Johnston tool_init_peers(tc);
143596f556f5SAlexander Motin
143696f556f5SAlexander Motin rc = tool_init_mws(tc);
143796f556f5SAlexander Motin if (rc)
143896f556f5SAlexander Motin goto err_clear_data;
143996f556f5SAlexander Motin
1440dace3812SMark Johnston tool_init_spads(tc);
144196f556f5SAlexander Motin
144296f556f5SAlexander Motin rc = tool_init_ntb(tc);
144396f556f5SAlexander Motin if (rc)
144496f556f5SAlexander Motin goto err_clear_spads;
144596f556f5SAlexander Motin
144696f556f5SAlexander Motin tool_setup_sysctl(tc);
144796f556f5SAlexander Motin
144896f556f5SAlexander Motin return (0);
144996f556f5SAlexander Motin
145096f556f5SAlexander Motin err_clear_spads:
145196f556f5SAlexander Motin tool_clear_spads(tc);
145296f556f5SAlexander Motin tool_clear_mws(tc);
145396f556f5SAlexander Motin tool_clear_peers(tc);
145496f556f5SAlexander Motin err_clear_data:
145596f556f5SAlexander Motin tool_clear_data(tc);
145696f556f5SAlexander Motin out:
145796f556f5SAlexander Motin device_printf(dev, "ntb_tool attached failed with err=(%d).\n", rc);
145896f556f5SAlexander Motin return (rc);
145996f556f5SAlexander Motin }
146096f556f5SAlexander Motin
146196f556f5SAlexander Motin static int
ntb_tool_detach(device_t dev)146296f556f5SAlexander Motin ntb_tool_detach(device_t dev)
146396f556f5SAlexander Motin {
146496f556f5SAlexander Motin struct tool_ctx *tc = device_get_softc(dev);
146596f556f5SAlexander Motin
146696f556f5SAlexander Motin tool_clear_ntb(tc);
146796f556f5SAlexander Motin
146896f556f5SAlexander Motin tool_clear_spads(tc);
146996f556f5SAlexander Motin
147096f556f5SAlexander Motin tool_clear_mws(tc);
147196f556f5SAlexander Motin
147296f556f5SAlexander Motin tool_clear_peers(tc);
147396f556f5SAlexander Motin
147496f556f5SAlexander Motin tool_clear_data(tc);
147596f556f5SAlexander Motin
147696f556f5SAlexander Motin return (0);
147796f556f5SAlexander Motin }
147896f556f5SAlexander Motin
147996f556f5SAlexander Motin static device_method_t ntb_tool_methods[] = {
148096f556f5SAlexander Motin /* Device interface */
148196f556f5SAlexander Motin DEVMETHOD(device_probe, ntb_tool_probe),
148296f556f5SAlexander Motin DEVMETHOD(device_attach, ntb_tool_attach),
148396f556f5SAlexander Motin DEVMETHOD(device_detach, ntb_tool_detach),
148496f556f5SAlexander Motin DEVMETHOD_END
148596f556f5SAlexander Motin };
148696f556f5SAlexander Motin
148796f556f5SAlexander Motin static DEFINE_CLASS_0(ntb_tool, ntb_tool_driver, ntb_tool_methods,
148896f556f5SAlexander Motin sizeof(struct tool_ctx));
14899940f7a7SJohn Baldwin DRIVER_MODULE(ntb_tool, ntb_hw, ntb_tool_driver, NULL, NULL);
149096f556f5SAlexander Motin MODULE_DEPEND(ntb_tool, ntb, 1, 1, 1);
149196f556f5SAlexander Motin MODULE_VERSION(ntb_tool, 1.0);
1492