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