1*1bdd6c0eSSue Gleeson /* 2*1bdd6c0eSSue Gleeson * CDDL HEADER START 3*1bdd6c0eSSue Gleeson * 4*1bdd6c0eSSue Gleeson * The contents of this file are subject to the terms of the 5*1bdd6c0eSSue Gleeson * Common Development and Distribution License (the "License"). 6*1bdd6c0eSSue Gleeson * You may not use this file except in compliance with the License. 7*1bdd6c0eSSue Gleeson * 8*1bdd6c0eSSue Gleeson * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1bdd6c0eSSue Gleeson * or http://www.opensolaris.org/os/licensing. 10*1bdd6c0eSSue Gleeson * See the License for the specific language governing permissions 11*1bdd6c0eSSue Gleeson * and limitations under the License. 12*1bdd6c0eSSue Gleeson * 13*1bdd6c0eSSue Gleeson * When distributing Covered Code, include this CDDL HEADER in each 14*1bdd6c0eSSue Gleeson * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1bdd6c0eSSue Gleeson * If applicable, add the following below this CDDL HEADER, with the 16*1bdd6c0eSSue Gleeson * fields enclosed by brackets "[]" replaced with your own identifying 17*1bdd6c0eSSue Gleeson * information: Portions Copyright [yyyy] [name of copyright owner] 18*1bdd6c0eSSue Gleeson * 19*1bdd6c0eSSue Gleeson * CDDL HEADER END 20*1bdd6c0eSSue Gleeson */ 21*1bdd6c0eSSue Gleeson /* 22*1bdd6c0eSSue Gleeson * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*1bdd6c0eSSue Gleeson * Use is subject to license terms. 24*1bdd6c0eSSue Gleeson */ 25*1bdd6c0eSSue Gleeson 26*1bdd6c0eSSue Gleeson #include <sys/dditypes.h> 27*1bdd6c0eSSue Gleeson #include <sys/mdb_modapi.h> 28*1bdd6c0eSSue Gleeson #include <sys/modctl.h> 29*1bdd6c0eSSue Gleeson #include <sys/sunddi.h> 30*1bdd6c0eSSue Gleeson #include <sys/sysmacros.h> 31*1bdd6c0eSSue Gleeson #include <sys/lpif.h> 32*1bdd6c0eSSue Gleeson #include <srp.h> 33*1bdd6c0eSSue Gleeson #include <srpt_impl.h> 34*1bdd6c0eSSue Gleeson 35*1bdd6c0eSSue Gleeson /* 36*1bdd6c0eSSue Gleeson * byteswap macros since ntohl not available in kernel mdb 37*1bdd6c0eSSue Gleeson */ 38*1bdd6c0eSSue Gleeson #if defined(_LITTLE_ENDIAN) 39*1bdd6c0eSSue Gleeson #define SRPT_BSWAP_32(x) (((uint32_t)(x) << 24) | \ 40*1bdd6c0eSSue Gleeson (((uint32_t)(x) << 8) & 0xff0000) | \ 41*1bdd6c0eSSue Gleeson (((uint32_t)(x) >> 8) & 0xff00) | \ 42*1bdd6c0eSSue Gleeson ((uint32_t)(x) >> 24)) 43*1bdd6c0eSSue Gleeson #define SRPT_BSWAP_16(x) ((((x) & 0xff) << 8) | ((x) >> 8)) 44*1bdd6c0eSSue Gleeson #else 45*1bdd6c0eSSue Gleeson #define SRPT_BSWAP_32(x) (x) 46*1bdd6c0eSSue Gleeson #define SRPT_BSWAP_16(x) (x) 47*1bdd6c0eSSue Gleeson #endif /* _LITTLE_ENDIAN */ 48*1bdd6c0eSSue Gleeson 49*1bdd6c0eSSue Gleeson /* 50*1bdd6c0eSSue Gleeson * Walker to list the addresses of all the active I/O Controllers 51*1bdd6c0eSSue Gleeson */ 52*1bdd6c0eSSue Gleeson static int 53*1bdd6c0eSSue Gleeson srpt_ioc_walk_init(mdb_walk_state_t *wsp) 54*1bdd6c0eSSue Gleeson { 55*1bdd6c0eSSue Gleeson srpt_ctxt_t *srpt; 56*1bdd6c0eSSue Gleeson uintptr_t srpt_global_addr, list_addr; 57*1bdd6c0eSSue Gleeson 58*1bdd6c0eSSue Gleeson if (mdb_readvar(&srpt, "srpt_ctxt") == -1) { 59*1bdd6c0eSSue Gleeson mdb_warn("failed to read srpt soft state"); 60*1bdd6c0eSSue Gleeson return (WALK_ERR); 61*1bdd6c0eSSue Gleeson } 62*1bdd6c0eSSue Gleeson 63*1bdd6c0eSSue Gleeson srpt_global_addr = (uintptr_t)srpt; 64*1bdd6c0eSSue Gleeson 65*1bdd6c0eSSue Gleeson list_addr = srpt_global_addr + offsetof(srpt_ctxt_t, sc_ioc_list); 66*1bdd6c0eSSue Gleeson 67*1bdd6c0eSSue Gleeson wsp->walk_addr = list_addr; 68*1bdd6c0eSSue Gleeson 69*1bdd6c0eSSue Gleeson if (mdb_layered_walk("list", wsp) == -1) { 70*1bdd6c0eSSue Gleeson mdb_warn("list walk failed"); 71*1bdd6c0eSSue Gleeson return (WALK_ERR); 72*1bdd6c0eSSue Gleeson } 73*1bdd6c0eSSue Gleeson return (WALK_NEXT); 74*1bdd6c0eSSue Gleeson } 75*1bdd6c0eSSue Gleeson 76*1bdd6c0eSSue Gleeson static int 77*1bdd6c0eSSue Gleeson srpt_list_walk_step(mdb_walk_state_t *wsp) 78*1bdd6c0eSSue Gleeson { 79*1bdd6c0eSSue Gleeson if (wsp->walk_addr == NULL) { 80*1bdd6c0eSSue Gleeson return (WALK_DONE); 81*1bdd6c0eSSue Gleeson } 82*1bdd6c0eSSue Gleeson return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 83*1bdd6c0eSSue Gleeson wsp->walk_cbdata)); 84*1bdd6c0eSSue Gleeson } 85*1bdd6c0eSSue Gleeson 86*1bdd6c0eSSue Gleeson /* 87*1bdd6c0eSSue Gleeson * Walker to list the target services per I/O Controller. The I/O Controller is 88*1bdd6c0eSSue Gleeson * provided as input. 89*1bdd6c0eSSue Gleeson */ 90*1bdd6c0eSSue Gleeson static int 91*1bdd6c0eSSue Gleeson srpt_tgt_walk_init(mdb_walk_state_t *wsp) 92*1bdd6c0eSSue Gleeson { 93*1bdd6c0eSSue Gleeson srpt_ioc_t srpt_ioc; 94*1bdd6c0eSSue Gleeson 95*1bdd6c0eSSue Gleeson /* 96*1bdd6c0eSSue Gleeson * Input should be a srpt_ioc_t, read it to get the 97*1bdd6c0eSSue Gleeson * srpt_target_port_t 98*1bdd6c0eSSue Gleeson */ 99*1bdd6c0eSSue Gleeson if (wsp->walk_addr == NULL) { 100*1bdd6c0eSSue Gleeson mdb_warn("<srpt_ioc_t addr>::walk srpt_target\n"); 101*1bdd6c0eSSue Gleeson return (WALK_ERR); 102*1bdd6c0eSSue Gleeson } 103*1bdd6c0eSSue Gleeson 104*1bdd6c0eSSue Gleeson if (mdb_vread(&srpt_ioc, sizeof (srpt_ioc_t), wsp->walk_addr) == -1) { 105*1bdd6c0eSSue Gleeson mdb_warn("failed to read in the srpt_ioc\n "); 106*1bdd6c0eSSue Gleeson return (WALK_ERR); 107*1bdd6c0eSSue Gleeson } 108*1bdd6c0eSSue Gleeson 109*1bdd6c0eSSue Gleeson wsp->walk_addr = (uintptr_t)srpt_ioc.ioc_tgt_port; 110*1bdd6c0eSSue Gleeson wsp->walk_data = mdb_alloc(sizeof (srpt_target_port_t), UM_SLEEP); 111*1bdd6c0eSSue Gleeson return (WALK_NEXT); 112*1bdd6c0eSSue Gleeson } 113*1bdd6c0eSSue Gleeson 114*1bdd6c0eSSue Gleeson static int 115*1bdd6c0eSSue Gleeson srpt_tgt_walk_step(mdb_walk_state_t *wsp) 116*1bdd6c0eSSue Gleeson { 117*1bdd6c0eSSue Gleeson if (wsp->walk_addr == NULL) { 118*1bdd6c0eSSue Gleeson return (WALK_DONE); 119*1bdd6c0eSSue Gleeson } 120*1bdd6c0eSSue Gleeson 121*1bdd6c0eSSue Gleeson (void) wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 122*1bdd6c0eSSue Gleeson wsp->walk_cbdata); 123*1bdd6c0eSSue Gleeson 124*1bdd6c0eSSue Gleeson /* Currently there is only one target per IOC */ 125*1bdd6c0eSSue Gleeson return (WALK_DONE); 126*1bdd6c0eSSue Gleeson 127*1bdd6c0eSSue Gleeson } 128*1bdd6c0eSSue Gleeson 129*1bdd6c0eSSue Gleeson static void 130*1bdd6c0eSSue Gleeson srpt_tgt_walk_fini(mdb_walk_state_t *wsp) 131*1bdd6c0eSSue Gleeson { 132*1bdd6c0eSSue Gleeson mdb_free(wsp->walk_data, sizeof (srpt_target_port_t)); 133*1bdd6c0eSSue Gleeson } 134*1bdd6c0eSSue Gleeson 135*1bdd6c0eSSue Gleeson /* 136*1bdd6c0eSSue Gleeson * Walker to list the channels per SRP target service. The target port is 137*1bdd6c0eSSue Gleeson * provided as input. 138*1bdd6c0eSSue Gleeson */ 139*1bdd6c0eSSue Gleeson static int 140*1bdd6c0eSSue Gleeson srpt_channel_walk_init(mdb_walk_state_t *wsp) 141*1bdd6c0eSSue Gleeson { 142*1bdd6c0eSSue Gleeson /* 143*1bdd6c0eSSue Gleeson * Input should be a srpt_target_port_t, read it to get the 144*1bdd6c0eSSue Gleeson * list of channels 145*1bdd6c0eSSue Gleeson */ 146*1bdd6c0eSSue Gleeson if (wsp->walk_addr == NULL) { 147*1bdd6c0eSSue Gleeson mdb_warn("<srpt_target_port_t addr>::walk srpt_channel\n"); 148*1bdd6c0eSSue Gleeson return (WALK_ERR); 149*1bdd6c0eSSue Gleeson } 150*1bdd6c0eSSue Gleeson 151*1bdd6c0eSSue Gleeson wsp->walk_addr += offsetof(srpt_target_port_t, tp_ch_list); 152*1bdd6c0eSSue Gleeson 153*1bdd6c0eSSue Gleeson if (mdb_layered_walk("list", wsp) == -1) { 154*1bdd6c0eSSue Gleeson mdb_warn("Could not walk tp_ch_list"); 155*1bdd6c0eSSue Gleeson return (WALK_ERR); 156*1bdd6c0eSSue Gleeson } 157*1bdd6c0eSSue Gleeson return (WALK_NEXT); 158*1bdd6c0eSSue Gleeson } 159*1bdd6c0eSSue Gleeson 160*1bdd6c0eSSue Gleeson /* 161*1bdd6c0eSSue Gleeson * Walker to list the SCSI sessions per target. The target is 162*1bdd6c0eSSue Gleeson * provided as input. 163*1bdd6c0eSSue Gleeson */ 164*1bdd6c0eSSue Gleeson static int 165*1bdd6c0eSSue Gleeson srpt_scsi_session_walk_init(mdb_walk_state_t *wsp) 166*1bdd6c0eSSue Gleeson { 167*1bdd6c0eSSue Gleeson /* 168*1bdd6c0eSSue Gleeson * Input should be a srpt_target_port_t, read it to get the 169*1bdd6c0eSSue Gleeson * srpt_session_t 170*1bdd6c0eSSue Gleeson */ 171*1bdd6c0eSSue Gleeson if (wsp->walk_addr == NULL) { 172*1bdd6c0eSSue Gleeson mdb_warn("<srpt_target_port_t addr>::walk srpt_scsi_session\n"); 173*1bdd6c0eSSue Gleeson return (WALK_ERR); 174*1bdd6c0eSSue Gleeson } 175*1bdd6c0eSSue Gleeson 176*1bdd6c0eSSue Gleeson wsp->walk_addr += offsetof(srpt_target_port_t, tp_sess_list); 177*1bdd6c0eSSue Gleeson 178*1bdd6c0eSSue Gleeson if (mdb_layered_walk("list", wsp) == -1) { 179*1bdd6c0eSSue Gleeson mdb_warn("target session list walk failed"); 180*1bdd6c0eSSue Gleeson return (WALK_ERR); 181*1bdd6c0eSSue Gleeson } 182*1bdd6c0eSSue Gleeson return (WALK_NEXT); 183*1bdd6c0eSSue Gleeson } 184*1bdd6c0eSSue Gleeson 185*1bdd6c0eSSue Gleeson /* 186*1bdd6c0eSSue Gleeson * Walker to list the tasks in a session. The session is 187*1bdd6c0eSSue Gleeson * provided as input. 188*1bdd6c0eSSue Gleeson */ 189*1bdd6c0eSSue Gleeson static int 190*1bdd6c0eSSue Gleeson srpt_task_walk_init(mdb_walk_state_t *wsp) 191*1bdd6c0eSSue Gleeson { 192*1bdd6c0eSSue Gleeson if (wsp->walk_addr == NULL) { 193*1bdd6c0eSSue Gleeson mdb_warn("<srpt_session_t addr>::walk srpt_tasks\n"); 194*1bdd6c0eSSue Gleeson return (WALK_ERR); 195*1bdd6c0eSSue Gleeson } 196*1bdd6c0eSSue Gleeson 197*1bdd6c0eSSue Gleeson wsp->walk_addr += offsetof(srpt_session_t, ss_task_list); 198*1bdd6c0eSSue Gleeson 199*1bdd6c0eSSue Gleeson if (mdb_layered_walk("list", wsp) == -1) { 200*1bdd6c0eSSue Gleeson mdb_warn("session task list walk failed"); 201*1bdd6c0eSSue Gleeson return (WALK_ERR); 202*1bdd6c0eSSue Gleeson } 203*1bdd6c0eSSue Gleeson return (WALK_NEXT); 204*1bdd6c0eSSue Gleeson } 205*1bdd6c0eSSue Gleeson 206*1bdd6c0eSSue Gleeson /* ARGSUSED */ 207*1bdd6c0eSSue Gleeson static int 208*1bdd6c0eSSue Gleeson srpt_print_ioc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 209*1bdd6c0eSSue Gleeson { 210*1bdd6c0eSSue Gleeson srpt_ioc_t ioc; 211*1bdd6c0eSSue Gleeson char mask[9]; 212*1bdd6c0eSSue Gleeson int i; 213*1bdd6c0eSSue Gleeson 214*1bdd6c0eSSue Gleeson if (addr == NULL) { 215*1bdd6c0eSSue Gleeson mdb_warn("address of srpt_ioc should be specified\n"); 216*1bdd6c0eSSue Gleeson return (DCMD_ERR); 217*1bdd6c0eSSue Gleeson } 218*1bdd6c0eSSue Gleeson 219*1bdd6c0eSSue Gleeson if (mdb_vread(&ioc, sizeof (srpt_ioc_t), addr) == -1) { 220*1bdd6c0eSSue Gleeson mdb_warn("failed to read srpt_ioc at %p", addr); 221*1bdd6c0eSSue Gleeson return (DCMD_ERR); 222*1bdd6c0eSSue Gleeson } 223*1bdd6c0eSSue Gleeson 224*1bdd6c0eSSue Gleeson mdb_printf("IOC %p\n", addr); 225*1bdd6c0eSSue Gleeson mdb_printf(" guid: %x\n", ioc.ioc_guid); 226*1bdd6c0eSSue Gleeson mdb_printf(" target port: %p\n", ioc.ioc_tgt_port); 227*1bdd6c0eSSue Gleeson mdb_printf(" srq handle: %p\n", ioc.ioc_srq_hdl); 228*1bdd6c0eSSue Gleeson mdb_printf(" current srq size: %u\n", ioc.ioc_num_iu_entries); 229*1bdd6c0eSSue Gleeson mdb_printf(" max srq size: %d\n", ioc.ioc_srq_attr.srq_wr_sz); 230*1bdd6c0eSSue Gleeson mdb_printf(" iu pool: %p\n", ioc.ioc_iu_pool); 231*1bdd6c0eSSue Gleeson mdb_printf(" profile send qdepth: %d\n", 232*1bdd6c0eSSue Gleeson SRPT_BSWAP_16(ioc.ioc_profile.ioc_send_msg_qdepth)); 233*1bdd6c0eSSue Gleeson mdb_printf(" profile rmda read qdepth: %d\n", 234*1bdd6c0eSSue Gleeson ioc.ioc_profile.ioc_rdma_read_qdepth); 235*1bdd6c0eSSue Gleeson mdb_printf(" profile send msg size: %d\n", 236*1bdd6c0eSSue Gleeson SRPT_BSWAP_32(ioc.ioc_profile.ioc_send_msg_sz)); 237*1bdd6c0eSSue Gleeson mdb_printf(" profile rmda xfer size: %d\n", 238*1bdd6c0eSSue Gleeson SRPT_BSWAP_32(ioc.ioc_profile.ioc_rdma_xfer_sz)); 239*1bdd6c0eSSue Gleeson for (i = 0; i < 8; i++) { 240*1bdd6c0eSSue Gleeson if (ioc.ioc_profile.ioc_ctrl_opcap_mask & 1<<i) { 241*1bdd6c0eSSue Gleeson mask[i] = 'x'; 242*1bdd6c0eSSue Gleeson } else { 243*1bdd6c0eSSue Gleeson mask[i] = '-'; 244*1bdd6c0eSSue Gleeson } 245*1bdd6c0eSSue Gleeson } 246*1bdd6c0eSSue Gleeson mask[i] = '\0'; 247*1bdd6c0eSSue Gleeson mdb_printf(" profile opcap mask: %s\n", mask); 248*1bdd6c0eSSue Gleeson 249*1bdd6c0eSSue Gleeson return (DCMD_OK); 250*1bdd6c0eSSue Gleeson } 251*1bdd6c0eSSue Gleeson 252*1bdd6c0eSSue Gleeson static const mdb_dcmd_t dcmds[] = { 253*1bdd6c0eSSue Gleeson { "srpt_print_ioc", ":", "Print information about an SRPT IOC", 254*1bdd6c0eSSue Gleeson srpt_print_ioc, NULL}, 255*1bdd6c0eSSue Gleeson { NULL } 256*1bdd6c0eSSue Gleeson }; 257*1bdd6c0eSSue Gleeson 258*1bdd6c0eSSue Gleeson static const mdb_walker_t walkers[] = { 259*1bdd6c0eSSue Gleeson { "srpt_ioc", "Walk active IO controllers", 260*1bdd6c0eSSue Gleeson srpt_ioc_walk_init, srpt_list_walk_step, NULL}, 261*1bdd6c0eSSue Gleeson { "srpt_tgt", "Walk the targets", 262*1bdd6c0eSSue Gleeson srpt_tgt_walk_init, srpt_tgt_walk_step, srpt_tgt_walk_fini}, 263*1bdd6c0eSSue Gleeson { "srpt_channel", "Walk the channels", 264*1bdd6c0eSSue Gleeson srpt_channel_walk_init, srpt_list_walk_step, NULL}, 265*1bdd6c0eSSue Gleeson { "srpt_scsi_session", "Walk the scsi sessions", 266*1bdd6c0eSSue Gleeson srpt_scsi_session_walk_init, srpt_list_walk_step, NULL}, 267*1bdd6c0eSSue Gleeson { "srpt_tasks", "Walk the tasks in a scsi session", 268*1bdd6c0eSSue Gleeson srpt_task_walk_init, srpt_list_walk_step, NULL}, 269*1bdd6c0eSSue Gleeson { NULL } 270*1bdd6c0eSSue Gleeson }; 271*1bdd6c0eSSue Gleeson 272*1bdd6c0eSSue Gleeson static const mdb_modinfo_t modinfo = { 273*1bdd6c0eSSue Gleeson MDB_API_VERSION, dcmds, walkers 274*1bdd6c0eSSue Gleeson }; 275*1bdd6c0eSSue Gleeson 276*1bdd6c0eSSue Gleeson const mdb_modinfo_t * 277*1bdd6c0eSSue Gleeson _mdb_init(void) 278*1bdd6c0eSSue Gleeson { 279*1bdd6c0eSSue Gleeson return (&modinfo); 280*1bdd6c0eSSue Gleeson } 281