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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <hxge_impl.h> 27 #include <inet/common.h> 28 #include <inet/mi.h> 29 #include <inet/nd.h> 30 31 extern uint64_t hpi_debug_level; 32 33 #define HXGE_PARAM_MAC_RW \ 34 HXGE_PARAM_RW | HXGE_PARAM_MAC | \ 35 HXGE_PARAM_NDD_WR_OK | HXGE_PARAM_READ_PROP 36 37 #define HXGE_PARAM_RXDMA_RW HXGE_PARAM_RWP | HXGE_PARAM_RXDMA | \ 38 HXGE_PARAM_NDD_WR_OK | HXGE_PARAM_READ_PROP 39 40 #define HXGE_PARAM_L2CLASS_CFG \ 41 HXGE_PARAM_RW | HXGE_PARAM_PROP_ARR32 | \ 42 HXGE_PARAM_READ_PROP | HXGE_PARAM_NDD_WR_OK 43 44 #define HXGE_PARAM_CLASS_RWS \ 45 HXGE_PARAM_RWS | HXGE_PARAM_READ_PROP 46 47 #define HXGE_PARAM_ARRAY_INIT_SIZE 0x20ULL 48 49 #define BASE_ANY 0 50 #define BASE_BINARY 2 51 #define BASE_HEX 16 52 #define BASE_DECIMAL 10 53 #define ALL_FF_64 0xFFFFFFFFFFFFFFFFULL 54 #define ALL_FF_32 0xFFFFFFFFUL 55 56 #define HXGE_NDD_INFODUMP_BUFF_SIZE 2048 /* is 2k enough? */ 57 #define HXGE_NDD_INFODUMP_BUFF_8K 8192 58 #define HXGE_NDD_INFODUMP_BUFF_16K 0x2000 59 #define HXGE_NDD_INFODUMP_BUFF_64K 0x8000 60 61 #define PARAM_OUTOF_RANGE(vptr, eptr, rval, pa) \ 62 ((vptr == eptr) || (rval < pa->minimum) || (rval > pa->maximum)) 63 64 #define ADVANCE_PRINT_BUFFER(pmp, plen, rlen) { \ 65 ((mblk_t *)pmp)->b_wptr += plen; \ 66 rlen -= plen; \ 67 } 68 69 int hxge_param_rx_intr_pkts(p_hxge_t hxgep, queue_t *, 70 mblk_t *, char *, caddr_t); 71 int hxge_param_rx_intr_time(p_hxge_t hxgep, queue_t *, 72 mblk_t *, char *, caddr_t); 73 static int hxge_param_set_mac(p_hxge_t, queue_t *, 74 mblk_t *, char *, caddr_t); 75 static int hxge_param_set_ether_usr(p_hxge_t hxgep, queue_t *, mblk_t *, 76 char *, caddr_t); 77 int hxge_param_set_ip_opt(p_hxge_t hxgep, 78 queue_t *, mblk_t *, char *, caddr_t); 79 static int hxge_param_pfc_hash_init(p_hxge_t hxgep, 80 queue_t *, mblk_t *, char *, caddr_t); 81 static int hxge_param_tcam_enable(p_hxge_t hxgep, queue_t *, 82 mblk_t *, char *, caddr_t); 83 static int hxge_param_get_rxdma_info(p_hxge_t hxgep, queue_t *q, 84 p_mblk_t mp, caddr_t cp); 85 static int hxge_param_set_vlan_ids(p_hxge_t hxgep, queue_t *q, 86 mblk_t *mp, char *value, caddr_t cp); 87 static int hxge_param_get_vlan_ids(p_hxge_t hxgep, queue_t *q, 88 p_mblk_t mp, caddr_t cp); 89 int hxge_param_get_ip_opt(p_hxge_t hxgep, 90 queue_t *, mblk_t *, caddr_t); 91 static int hxge_param_get_mac(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, 92 caddr_t cp); 93 static int hxge_param_get_debug_flag(p_hxge_t hxgep, queue_t *q, 94 p_mblk_t mp, caddr_t cp); 95 static int hxge_param_set_hxge_debug_flag(p_hxge_t hxgep, 96 queue_t *, mblk_t *, char *, caddr_t); 97 static int hxge_param_set_hpi_debug_flag(p_hxge_t hxgep, 98 queue_t *, mblk_t *, char *, caddr_t); 99 static int hxge_param_dump_ptrs(p_hxge_t hxgep, queue_t *q, 100 p_mblk_t mp, caddr_t cp); 101 102 /* 103 * Global array of Hydra changable parameters. 104 * This array is initialized to correspond to the default 105 * Hydra configuration. This array would be copied 106 * into the parameter structure and modifed per 107 * fcode and hxge.conf configuration. Later, the parameters are 108 * exported to ndd to display and run-time configuration (at least 109 * some of them). 110 */ 111 112 static hxge_param_t hxge_param_arr[] = { 113 /* min max value old hw-name conf-name */ 114 {hxge_param_get_generic, NULL, HXGE_PARAM_READ, 115 0, 999, 1000, 0, "instance", "instance"}, 116 117 /* MTU cannot be propagated to the stack from here, so don't show it */ 118 {hxge_param_get_mac, hxge_param_set_mac, 119 HXGE_PARAM_MAC_RW | HXGE_PARAM_DONT_SHOW, 120 0, 1, 0, 0, "accept-jumbo", "accept_jumbo"}, 121 122 {hxge_param_get_rxdma_info, NULL, 123 HXGE_PARAM_READ | HXGE_PARAM_DONT_SHOW, 124 HXGE_RBR_RBB_MIN, HXGE_RBR_RBB_MAX, HXGE_RBR_RBB_DEFAULT, 0, 125 "rx-rbr-size", "rx_rbr_size"}, 126 127 {hxge_param_get_rxdma_info, NULL, 128 HXGE_PARAM_READ | HXGE_PARAM_DONT_SHOW, 129 HXGE_RCR_MIN, HXGE_RCR_MAX, HXGE_RCR_DEFAULT, 0, 130 "rx-rcr-size", "rx_rcr_size"}, 131 132 {hxge_param_get_generic, hxge_param_rx_intr_time, 133 HXGE_PARAM_RXDMA_RW, 134 HXGE_RDC_RCR_TIMEOUT_MIN, HXGE_RDC_RCR_TIMEOUT_MAX, 135 RXDMA_RCR_TO_DEFAULT, 0, "rxdma-intr-time", "rxdma_intr_time"}, 136 137 {hxge_param_get_generic, hxge_param_rx_intr_pkts, 138 HXGE_PARAM_RXDMA_RW, 139 HXGE_RDC_RCR_THRESHOLD_MIN, HXGE_RDC_RCR_THRESHOLD_MAX, 140 RXDMA_RCR_PTHRES_DEFAULT, 0, 141 "rxdma-intr-pkts", "rxdma_intr_pkts"}, 142 143 /* Hardware VLAN is not used currently, so don't show it */ 144 {hxge_param_get_vlan_ids, hxge_param_set_vlan_ids, 145 HXGE_PARAM_L2CLASS_CFG | HXGE_PARAM_DONT_SHOW, 146 VLAN_ID_MIN, VLAN_ID_MAX, 0, 0, "vlan-ids", "vlan_ids"}, 147 148 /* Hardware VLAN is not used currently, so don't show it */ 149 {hxge_param_get_generic, hxge_param_set_generic, 150 HXGE_PARAM_CLASS_RWS | HXGE_PARAM_DONT_SHOW, 151 VLAN_ID_MIN, VLAN_ID_MAX, VLAN_ID_IMPLICIT, VLAN_ID_IMPLICIT, 152 "implicit-vlan-id", "implicit_vlan_id"}, 153 154 {hxge_param_get_generic, hxge_param_tcam_enable, 155 HXGE_PARAM_CLASS_RWS | HXGE_PARAM_DONT_SHOW, 156 0, 0x1, 0x0, 0, "tcam-enable", "tcam_enable"}, 157 158 {hxge_param_get_generic, hxge_param_pfc_hash_init, 159 HXGE_PARAM_CLASS_RWS | HXGE_PARAM_DONT_SHOW, 160 0, ALL_FF_32, ALL_FF_32, 0, 161 "hash-init-value", "hash_init_value"}, 162 163 {hxge_param_get_generic, hxge_param_set_ether_usr, 164 HXGE_PARAM_CLASS_RWS | HXGE_PARAM_DONT_SHOW, 165 0, ALL_FF_32, 0x0, 0, 166 "class-cfg-ether-usr1", "class_cfg_ether_usr1"}, 167 168 {hxge_param_get_generic, hxge_param_set_ether_usr, 169 HXGE_PARAM_CLASS_RWS | HXGE_PARAM_DONT_SHOW, 170 0, ALL_FF_32, 0x0, 0, 171 "class-cfg-ether-usr2", "class_cfg_ether_usr2"}, 172 173 {hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS, 174 0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0, 175 "class-opt-ipv4-tcp", "class_opt_ipv4_tcp"}, 176 177 {hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS, 178 0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0, 179 "class-opt-ipv4-udp", "class_opt_ipv4_udp"}, 180 181 {hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS, 182 0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0, 183 "class-opt-ipv4-ah", "class_opt_ipv4_ah"}, 184 185 {hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS, 186 0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0, 187 "class-opt-ipv4-sctp", "class_opt_ipv4_sctp"}, 188 189 {hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS, 190 0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0, 191 "class-opt-ipv6-tcp", "class_opt_ipv6_tcp"}, 192 193 {hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS, 194 0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0, 195 "class-opt-ipv6-udp", "class_opt_ipv6_udp"}, 196 197 {hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS, 198 0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0, 199 "class-opt-ipv6-ah", "class_opt_ipv6_ah"}, 200 201 {hxge_param_get_ip_opt, hxge_param_set_ip_opt, HXGE_PARAM_CLASS_RWS, 202 0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0, 203 "class-opt-ipv6-sctp", "class_opt_ipv6_sctp"}, 204 205 {hxge_param_get_debug_flag, hxge_param_set_hxge_debug_flag, 206 HXGE_PARAM_RW | HXGE_PARAM_DONT_SHOW, 207 0ULL, ALL_FF_64, 0ULL, 0ULL, 208 "hxge-debug-flag", "hxge_debug_flag"}, 209 210 {hxge_param_get_debug_flag, hxge_param_set_hpi_debug_flag, 211 HXGE_PARAM_RW | HXGE_PARAM_DONT_SHOW, 212 0ULL, ALL_FF_64, 0ULL, 0ULL, 213 "hpi-debug-flag", "hpi_debug_flag"}, 214 215 {hxge_param_dump_ptrs, NULL, HXGE_PARAM_READ | HXGE_PARAM_DONT_SHOW, 216 0, 0x0fffffff, 0x0fffffff, 0, "dump-ptrs", "dump_ptrs"}, 217 218 {NULL, NULL, HXGE_PARAM_READ | HXGE_PARAM_DONT_SHOW, 219 0, 0x0fffffff, 0x0fffffff, 0, "end", "end"}, 220 }; 221 222 extern void *hxge_list; 223 224 /* 225 * Update the NDD array from the soft properties. 226 */ 227 void 228 hxge_get_param_soft_properties(p_hxge_t hxgep) 229 { 230 p_hxge_param_t param_arr; 231 uint_t prop_len; 232 int i, j; 233 uint32_t param_count; 234 uint32_t *int_prop_val; 235 236 HXGE_DEBUG_MSG((hxgep, DDI_CTL, " ==> hxge_get_param_soft_properties")); 237 238 param_arr = hxgep->param_arr; 239 param_count = hxgep->param_count; 240 for (i = 0; i < param_count; i++) { 241 242 if ((param_arr[i].type & HXGE_PARAM_READ_PROP) == 0) 243 continue; 244 245 if ((param_arr[i].type & HXGE_PARAM_PROP_STR)) 246 continue; 247 248 if ((param_arr[i].type & HXGE_PARAM_PROP_ARR32) || 249 (param_arr[i].type & HXGE_PARAM_PROP_ARR64)) { 250 251 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, 252 hxgep->dip, 0, param_arr[i].fcode_name, 253 (int **)&int_prop_val, (uint_t *)&prop_len) == 254 DDI_PROP_SUCCESS) { 255 uint64_t *cfg_value; 256 uint64_t prop_count; 257 258 if (prop_len > HXGE_PARAM_ARRAY_INIT_SIZE) 259 prop_len = HXGE_PARAM_ARRAY_INIT_SIZE; 260 cfg_value = (uint64_t *)param_arr[i].value; 261 for (j = 0; j < prop_len; j++) { 262 cfg_value[j] = int_prop_val[j]; 263 } 264 prop_count = prop_len; 265 param_arr[i].type |= 266 (prop_count << HXGE_PARAM_ARRAY_CNT_SHIFT); 267 268 ddi_prop_free(int_prop_val); 269 } 270 continue; 271 } 272 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0, 273 param_arr[i].fcode_name, (int **)&int_prop_val, 274 &prop_len) == DDI_PROP_SUCCESS) { 275 if ((*int_prop_val >= param_arr[i].minimum) && 276 (*int_prop_val <= param_arr[i].maximum)) 277 param_arr[i].value = *int_prop_val; 278 ddi_prop_free(int_prop_val); 279 } 280 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0, 281 param_arr[i].name, (int **)&int_prop_val, &prop_len) == 282 DDI_PROP_SUCCESS) { 283 if ((*int_prop_val >= param_arr[i].minimum) && 284 (*int_prop_val <= param_arr[i].maximum)) 285 param_arr[i].value = *int_prop_val; 286 ddi_prop_free(int_prop_val); 287 } 288 } 289 } 290 291 static int 292 hxge_private_param_register(p_hxge_t hxgep, p_hxge_param_t param_arr) 293 { 294 int status = B_TRUE; 295 int channel; 296 char *prop_name; 297 char *end; 298 uint32_t name_chars; 299 300 HXGE_DEBUG_MSG((hxgep, NDD2_CTL, " hxge_private_param_register %s", 301 param_arr->name)); 302 303 if ((param_arr->type & HXGE_PARAM_PRIV) != HXGE_PARAM_PRIV) 304 return (B_TRUE); 305 prop_name = param_arr->name; 306 if (param_arr->type & HXGE_PARAM_RXDMA) { 307 if (strncmp("rxdma_intr", prop_name, 10) == 0) 308 return (B_TRUE); 309 else 310 return (B_FALSE); 311 } 312 313 if (param_arr->type & HXGE_PARAM_TXDMA) { 314 name_chars = strlen("txdma"); 315 if (strncmp("txdma", prop_name, name_chars) == 0) { 316 prop_name += name_chars; 317 channel = mi_strtol(prop_name, &end, 10); 318 /* now check if this rdc is in config */ 319 HXGE_DEBUG_MSG((hxgep, NDD2_CTL, 320 " hxge_private_param_register: %d", channel)); 321 return (hxge_check_txdma_port_member(hxgep, channel)); 322 } 323 return (B_FALSE); 324 } 325 326 status = B_FALSE; 327 HXGE_DEBUG_MSG((hxgep, NDD2_CTL, "<== hxge_private_param_register")); 328 329 return (status); 330 } 331 332 void 333 hxge_setup_param(p_hxge_t hxgep) 334 { 335 p_hxge_param_t param_arr; 336 int i; 337 pfi_t set_pfi; 338 339 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_setup_param")); 340 /* 341 * Make sure the param_instance is set to a valid device instance. 342 */ 343 if (hxge_param_arr[param_instance].value == 1000) 344 hxge_param_arr[param_instance].value = hxgep->instance; 345 346 param_arr = hxgep->param_arr; 347 param_arr[param_instance].value = hxgep->instance; 348 349 for (i = 0; i < hxgep->param_count; i++) { 350 if ((param_arr[i].type & HXGE_PARAM_PRIV) && 351 (hxge_private_param_register(hxgep, ¶m_arr[i]) == 352 B_FALSE)) { 353 param_arr[i].setf = NULL; 354 param_arr[i].getf = NULL; 355 } 356 if (param_arr[i].type & HXGE_PARAM_CMPLX) 357 param_arr[i].setf = NULL; 358 359 if (param_arr[i].type & HXGE_PARAM_DONT_SHOW) { 360 param_arr[i].setf = NULL; 361 param_arr[i].getf = NULL; 362 } 363 set_pfi = (pfi_t)param_arr[i].setf; 364 365 if ((set_pfi) && (param_arr[i].type & HXGE_PARAM_INIT_ONLY)) { 366 set_pfi = NULL; 367 } 368 if (!hxge_nd_load(&hxgep->param_list, param_arr[i].name, 369 (pfi_t)param_arr[i].getf, set_pfi, 370 (caddr_t)¶m_arr[i])) { 371 (void) hxge_nd_free(&hxgep->param_list); 372 break; 373 } 374 } 375 376 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_setup_param")); 377 } 378 379 /* 380 * Called from the attached function, it allocates memory for 381 * the parameter array and some members. 382 */ 383 void 384 hxge_init_param(p_hxge_t hxgep) 385 { 386 p_hxge_param_t param_arr; 387 int i, alloc_size; 388 uint64_t alloc_count; 389 390 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_init_param")); 391 /* 392 * Make sure the param_instance is set to a valid device instance. 393 */ 394 if (hxge_param_arr[param_instance].value == 1000) 395 hxge_param_arr[param_instance].value = hxgep->instance; 396 397 param_arr = hxgep->param_arr; 398 if (param_arr == NULL) { 399 param_arr = (p_hxge_param_t)KMEM_ZALLOC( 400 sizeof (hxge_param_arr), KM_SLEEP); 401 } 402 for (i = 0; i < sizeof (hxge_param_arr) / sizeof (hxge_param_t); i++) { 403 param_arr[i] = hxge_param_arr[i]; 404 if ((param_arr[i].type & HXGE_PARAM_PROP_ARR32) || 405 (param_arr[i].type & HXGE_PARAM_PROP_ARR64)) { 406 alloc_count = HXGE_PARAM_ARRAY_INIT_SIZE; 407 alloc_size = alloc_count * sizeof (uint64_t); 408 param_arr[i].value = 409 (uint64_t)KMEM_ZALLOC(alloc_size, KM_SLEEP); 410 param_arr[i].old_value = 411 (uint64_t)KMEM_ZALLOC(alloc_size, KM_SLEEP); 412 param_arr[i].type |= 413 (alloc_count << HXGE_PARAM_ARRAY_ALLOC_SHIFT); 414 } 415 } 416 417 hxgep->param_arr = param_arr; 418 hxgep->param_count = sizeof (hxge_param_arr) / sizeof (hxge_param_t); 419 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_init_param: count %d", 420 hxgep->param_count)); 421 } 422 423 /* 424 * Called from the attached functions, it frees memory for the parameter array 425 */ 426 void 427 hxge_destroy_param(p_hxge_t hxgep) 428 { 429 int i; 430 uint64_t free_size, free_count; 431 432 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_param")); 433 /* 434 * Make sure the param_instance is set to a valid device instance. 435 */ 436 if (hxge_param_arr[param_instance].value == hxgep->instance) { 437 for (i = 0; i <= hxge_param_arr[param_instance].maximum; i++) { 438 if ((ddi_get_soft_state(hxge_list, i) != NULL) && 439 (i != hxgep->instance)) 440 break; 441 } 442 hxge_param_arr[param_instance].value = i; 443 } 444 if (hxgep->param_list) 445 hxge_nd_free(&hxgep->param_list); 446 for (i = 0; i < hxgep->param_count; i++) { 447 if ((hxgep->param_arr[i].type & HXGE_PARAM_PROP_ARR32) || 448 (hxgep->param_arr[i].type & HXGE_PARAM_PROP_ARR64)) { 449 free_count = ((hxgep->param_arr[i].type & 450 HXGE_PARAM_ARRAY_ALLOC_MASK) >> 451 HXGE_PARAM_ARRAY_ALLOC_SHIFT); 452 free_count = HXGE_PARAM_ARRAY_INIT_SIZE; 453 free_size = sizeof (uint64_t) * free_count; 454 KMEM_FREE((void *) hxgep->param_arr[i].value, 455 free_size); 456 KMEM_FREE((void *) hxgep->param_arr[i].old_value, 457 free_size); 458 } 459 } 460 461 KMEM_FREE(hxgep->param_arr, sizeof (hxge_param_arr)); 462 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_param")); 463 } 464 465 /* 466 * Extracts the value from the 'hxge' parameter array and prints the 467 * parameter value. cp points to the required parameter. 468 */ 469 /* ARGSUSED */ 470 int 471 hxge_param_get_generic(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, caddr_t cp) 472 { 473 p_hxge_param_t pa = (p_hxge_param_t)cp; 474 475 HXGE_DEBUG_MSG((hxgep, NDD_CTL, " ==> hxge_param_get_generic name %s ", 476 pa->name)); 477 478 if (pa->value > 0xffffffff) 479 (void) mi_mpprintf(mp, "%x%x", (int)(pa->value >> 32), 480 (int)(pa->value & 0xffffffff)); 481 else 482 (void) mi_mpprintf(mp, "%x", (int)pa->value); 483 484 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_get_generic")); 485 return (0); 486 } 487 488 /* ARGSUSED */ 489 static int 490 hxge_param_get_mac(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, caddr_t cp) 491 { 492 p_hxge_param_t pa = (p_hxge_param_t)cp; 493 494 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_get_mac")); 495 496 (void) mi_mpprintf(mp, "%d", (uint32_t)pa->value); 497 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_get_mac")); 498 return (0); 499 } 500 501 /* ARGSUSED */ 502 int 503 hxge_param_get_rxdma_info(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, caddr_t cp) 504 { 505 uint_t print_len, buf_len; 506 p_mblk_t np; 507 int rdc; 508 p_hxge_dma_pt_cfg_t p_dma_cfgp; 509 p_hxge_hw_pt_cfg_t p_cfgp; 510 int buff_alloc_size = HXGE_NDD_INFODUMP_BUFF_SIZE; 511 512 p_rx_rcr_rings_t rx_rcr_rings; 513 p_rx_rcr_ring_t *rcr_rings; 514 p_rx_rbr_rings_t rx_rbr_rings; 515 p_rx_rbr_ring_t *rbr_rings; 516 517 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_get_rxdma_info")); 518 519 (void) mi_mpprintf(mp, "RXDMA Information\n"); 520 521 if ((np = allocb(buff_alloc_size, BPRI_HI)) == NULL) { 522 /* The following may work even if we cannot get a large buf. */ 523 (void) mi_mpprintf(mp, "%s\n", "out of buffer"); 524 return (0); 525 } 526 buf_len = buff_alloc_size; 527 528 mp->b_cont = np; 529 530 p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 531 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 532 533 rx_rcr_rings = hxgep->rx_rcr_rings; 534 rcr_rings = rx_rcr_rings->rcr_rings; 535 rx_rbr_rings = hxgep->rx_rbr_rings; 536 rbr_rings = rx_rbr_rings->rbr_rings; 537 538 print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len, 539 "Total RDCs\t %d\n", p_cfgp->max_rdcs); 540 ((mblk_t *)np)->b_wptr += print_len; 541 buf_len -= print_len; 542 print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len, 543 "RDC\t HW RDC\t Timeout\t Packets RBR ptr \t" 544 "chunks\t RCR ptr\n"); 545 ((mblk_t *)np)->b_wptr += print_len; 546 buf_len -= print_len; 547 for (rdc = 0; rdc < p_cfgp->max_rdcs; rdc++) { 548 print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len, 549 " %d\t %d\t $%p\t 0x%x\t $%p\n", 550 rdc, hxgep->rdc[rdc], (void *)rbr_rings[rdc], 551 rbr_rings[rdc]->num_blocks, (void *)rcr_rings[rdc]); 552 ((mblk_t *)np)->b_wptr += print_len; 553 buf_len -= print_len; 554 } 555 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_get_rxdma_info")); 556 return (0); 557 } 558 559 int 560 hxge_mk_mblk_tail_space(p_mblk_t mp, p_mblk_t *nmp, size_t size) 561 { 562 p_mblk_t tmp; 563 564 tmp = mp; 565 while (tmp->b_cont) 566 tmp = tmp->b_cont; 567 if ((tmp->b_wptr + size) >= tmp->b_datap->db_lim) { 568 tmp->b_cont = allocb(1024, BPRI_HI); 569 tmp = tmp->b_cont; 570 if (!tmp) 571 return (ENOMEM); 572 } 573 *nmp = tmp; 574 return (0); 575 } 576 577 /* 578 * Sets the ge parameter to the value in the hxge_param_register using 579 * hxge_nd_load(). 580 */ 581 /* ARGSUSED */ 582 int 583 hxge_param_set_generic(p_hxge_t hxgep, queue_t *q, mblk_t *mp, 584 char *value, caddr_t cp) 585 { 586 char *end; 587 uint32_t new_value; 588 p_hxge_param_t pa = (p_hxge_param_t)cp; 589 590 HXGE_DEBUG_MSG((hxgep, IOC_CTL, " ==> hxge_param_set_generic")); 591 new_value = (uint32_t)mi_strtol(value, &end, 10); 592 if (end == value || new_value < pa->minimum || 593 new_value > pa->maximum) { 594 return (EINVAL); 595 } 596 pa->value = new_value; 597 HXGE_DEBUG_MSG((hxgep, IOC_CTL, " <== hxge_param_set_generic")); 598 return (0); 599 } 600 601 /* ARGSUSED */ 602 int 603 hxge_param_set_mac(p_hxge_t hxgep, queue_t *q, mblk_t *mp, 604 char *value, caddr_t cp) 605 { 606 char *end; 607 uint32_t new_value; 608 int status = 0; 609 p_hxge_param_t pa = (p_hxge_param_t)cp; 610 611 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_set_mac")); 612 new_value = (uint32_t)mi_strtol(value, &end, BASE_DECIMAL); 613 if (PARAM_OUTOF_RANGE(value, end, new_value, pa)) { 614 return (EINVAL); 615 } 616 617 if (pa->value != new_value) { 618 pa->old_value = pa->value; 619 pa->value = new_value; 620 } 621 622 if (pa->value != pa->old_value) { 623 RW_ENTER_WRITER(&hxgep->filter_lock); 624 (void) hxge_rx_vmac_disable(hxgep); 625 (void) hxge_tx_vmac_disable(hxgep); 626 627 /* 628 * Apply the new jumbo parameter here. 629 * The order of the following two calls is important. 630 */ 631 (void) hxge_tx_vmac_enable(hxgep); 632 (void) hxge_rx_vmac_enable(hxgep); 633 RW_EXIT(&hxgep->filter_lock); 634 } 635 636 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_set_mac")); 637 return (status); 638 } 639 640 /* ARGSUSED */ 641 int 642 hxge_param_rx_intr_pkts(p_hxge_t hxgep, queue_t *q, 643 mblk_t *mp, char *value, caddr_t cp) 644 { 645 char *end; 646 uint32_t cfg_value; 647 p_hxge_param_t pa = (p_hxge_param_t)cp; 648 649 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_rx_intr_pkts")); 650 651 if (strncasecmp(value, "0x", 2) == 0) 652 value += 2; 653 654 cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX); 655 656 if ((cfg_value > HXGE_RDC_RCR_THRESHOLD_MAX) || 657 (cfg_value < HXGE_RDC_RCR_THRESHOLD_MIN)) { 658 return (EINVAL); 659 } 660 661 if ((pa->value != cfg_value)) { 662 pa->old_value = pa->value; 663 pa->value = cfg_value; 664 hxgep->intr_threshold = pa->value; 665 } 666 667 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_rx_intr_pkts")); 668 return (0); 669 } 670 671 /* ARGSUSED */ 672 int 673 hxge_param_rx_intr_time(p_hxge_t hxgep, queue_t *q, 674 mblk_t *mp, char *value, caddr_t cp) 675 { 676 char *end; 677 uint32_t cfg_value; 678 p_hxge_param_t pa = (p_hxge_param_t)cp; 679 680 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_rx_intr_time")); 681 682 if (strncasecmp(value, "0x", 2) == 0) 683 value += 2; 684 685 cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX); 686 687 if ((cfg_value > HXGE_RDC_RCR_TIMEOUT_MAX) || 688 (cfg_value < HXGE_RDC_RCR_TIMEOUT_MIN)) { 689 return (EINVAL); 690 } 691 692 if ((pa->value != cfg_value)) { 693 pa->old_value = pa->value; 694 pa->value = cfg_value; 695 hxgep->intr_timeout = pa->value; 696 } 697 698 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_rx_intr_time")); 699 return (0); 700 } 701 702 /* ARGSUSED */ 703 static int 704 hxge_param_set_vlan_ids(p_hxge_t hxgep, queue_t *q, mblk_t *mp, char *value, 705 caddr_t cp) 706 { 707 char *end; 708 uint32_t status = 0, cfg_value; 709 p_hxge_param_t pa = (p_hxge_param_t)cp; 710 uint32_t cfg_it = B_FALSE; 711 uint32_t *val_ptr, *old_val_ptr; 712 hxge_param_map_t *vmap, *old_map; 713 p_hxge_class_pt_cfg_t p_class_cfgp; 714 uint64_t cfgd_vlans; 715 int i, inc = 0, cfg_position; 716 hxge_mv_cfg_t *vlan_tbl; 717 hpi_handle_t handle; 718 719 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_set_vlan_ids ")); 720 721 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config; 722 vlan_tbl = (hxge_mv_cfg_t *)&p_class_cfgp->vlan_tbl[0]; 723 handle = hxgep->hpi_reg_handle; 724 725 if (strncasecmp(value, "0x", 2) == 0) 726 value += 2; 727 728 cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX); 729 730 /* now do decoding */ 731 cfgd_vlans = ((pa->type & HXGE_PARAM_ARRAY_CNT_MASK) >> 732 HXGE_PARAM_ARRAY_CNT_SHIFT); 733 734 if (cfgd_vlans >= HXGE_PARAM_ARRAY_INIT_SIZE) { 735 /* 736 * for now, we process only upto HXGE_PARAM_ARRAY_INIT_SIZE 737 * parameters In the future, we may want to expand 738 * the storage array and continue 739 */ 740 return (EINVAL); 741 } 742 743 vmap = (hxge_param_map_t *)&cfg_value; 744 if ((vmap->param_id == 0) || (vmap->param_id > VLAN_ID_MAX)) { 745 return (EINVAL); 746 } 747 748 HXGE_DEBUG_MSG((hxgep, NDD_CTL, " hxge_param_set_vlan_ids id %d", 749 vmap->param_id)); 750 val_ptr = (uint32_t *)pa->value; 751 old_val_ptr = (uint32_t *)pa->old_value; 752 753 /* Search to see if this vlan id is already configured */ 754 for (i = 0; i < cfgd_vlans; i++) { 755 old_map = (hxge_param_map_t *)&val_ptr[i]; 756 if ((old_map->param_id == 0) || 757 (vmap->param_id == old_map->param_id) || 758 (vlan_tbl[vmap->param_id].flag)) { 759 cfg_position = i; 760 break; 761 } 762 } 763 764 if (cfgd_vlans == 0) { 765 cfg_position = 0; 766 inc++; 767 } 768 769 if (i == cfgd_vlans) { 770 cfg_position = i; 771 inc++; 772 } 773 774 HXGE_DEBUG_MSG((hxgep, NDD2_CTL, 775 " set_vlan_ids mapping i %d cfgd_vlans %llx position %d ", 776 i, cfgd_vlans, cfg_position)); 777 778 if (val_ptr[cfg_position] != cfg_value) { 779 old_val_ptr[cfg_position] = val_ptr[cfg_position]; 780 val_ptr[cfg_position] = cfg_value; 781 vlan_tbl[vmap->param_id].flag = 1; 782 cfg_it = B_TRUE; 783 if (inc) { 784 cfgd_vlans++; 785 pa->type &= ~HXGE_PARAM_ARRAY_CNT_MASK; 786 pa->type |= (cfgd_vlans << HXGE_PARAM_ARRAY_CNT_SHIFT); 787 788 } 789 790 HXGE_DEBUG_MSG((hxgep, NDD2_CTL, 791 " after: param_set_vlan_ids cfg_vlans %llx position %d \n", 792 cfgd_vlans, cfg_position)); 793 } 794 795 if (cfg_it == B_TRUE) { 796 status = hpi_pfc_cfg_vlan_table_entry_set(handle, 797 (vlan_id_t)vmap->param_id); 798 if (status != HPI_SUCCESS) 799 return (EINVAL); 800 } 801 802 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_set_vlan_ids")); 803 804 return (0); 805 } 806 807 808 /* ARGSUSED */ 809 static int 810 hxge_param_get_vlan_ids(p_hxge_t hxgep, queue_t *q, mblk_t *mp, caddr_t cp) 811 { 812 uint_t print_len, buf_len; 813 p_mblk_t np; 814 int i; 815 uint32_t *val_ptr; 816 hxge_param_map_t *vmap; 817 p_hxge_param_t pa = (p_hxge_param_t)cp; 818 p_hxge_class_pt_cfg_t p_class_cfgp; 819 uint64_t cfgd_vlans = 0; 820 int buff_alloc_size = HXGE_NDD_INFODUMP_BUFF_SIZE * 32; 821 822 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_set_vlan_ids ")); 823 (void) mi_mpprintf(mp, "VLAN Information\n"); 824 825 if ((np = allocb(buff_alloc_size, BPRI_HI)) == NULL) { 826 (void) mi_mpprintf(mp, "%s\n", "out of buffer"); 827 return (0); 828 } 829 830 buf_len = buff_alloc_size; 831 mp->b_cont = np; 832 cfgd_vlans = (pa->type & HXGE_PARAM_ARRAY_CNT_MASK) >> 833 HXGE_PARAM_ARRAY_CNT_SHIFT; 834 835 i = (int)cfgd_vlans; 836 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config; 837 print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len, 838 "Configured VLANs %d\n VLAN ID\n", i); 839 ((mblk_t *)np)->b_wptr += print_len; 840 buf_len -= print_len; 841 842 val_ptr = (uint32_t *)pa->value; 843 844 for (i = 0; i < cfgd_vlans; i++) { 845 vmap = (hxge_param_map_t *)&val_ptr[i]; 846 if (p_class_cfgp->vlan_tbl[vmap->param_id].flag) { 847 print_len = snprintf((char *)((mblk_t *)np)->b_wptr, 848 buf_len, " %d\n", vmap->param_id); 849 ((mblk_t *)np)->b_wptr += print_len; 850 buf_len -= print_len; 851 } 852 } 853 854 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_get_vlan_ids")); 855 856 return (0); 857 } 858 859 /* ARGSUSED */ 860 static int 861 hxge_param_tcam_enable(p_hxge_t hxgep, queue_t *q, 862 mblk_t *mp, char *value, caddr_t cp) 863 { 864 uint32_t status = 0, cfg_value; 865 p_hxge_param_t pa = (p_hxge_param_t)cp; 866 uint32_t cfg_it = B_FALSE; 867 char *end; 868 869 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_tcam_enable")); 870 871 cfg_value = (uint32_t)mi_strtol(value, &end, BASE_BINARY); 872 if (pa->value != cfg_value) { 873 pa->old_value = pa->value; 874 pa->value = cfg_value; 875 cfg_it = B_TRUE; 876 } 877 if (cfg_it == B_TRUE) { 878 if (pa->value) 879 status = hxge_pfc_config_tcam_enable(hxgep); 880 else 881 status = hxge_pfc_config_tcam_disable(hxgep); 882 if (status != HXGE_OK) 883 return (EINVAL); 884 } 885 HXGE_DEBUG_MSG((hxgep, NDD_CTL, " <== hxge_param_tcam_enable")); 886 return (0); 887 } 888 889 /* ARGSUSED */ 890 static int 891 hxge_param_set_ether_usr(p_hxge_t hxgep, queue_t *q, 892 mblk_t *mp, char *value, caddr_t cp) 893 { 894 char *end; 895 uint32_t status = 0, cfg_value; 896 p_hxge_param_t pa = (p_hxge_param_t)cp; 897 898 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_set_ether_usr")); 899 900 if (strncasecmp(value, "0x", 2) == 0) 901 value += 2; 902 903 cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX); 904 if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) { 905 return (EINVAL); 906 } 907 if (pa->value != cfg_value) { 908 pa->old_value = pa->value; 909 pa->value = cfg_value; 910 } 911 912 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_set_ether_usr")); 913 return (status); 914 } 915 916 static int 917 hxge_class_name_2value(p_hxge_t hxgep, char *name) 918 { 919 int i; 920 int class_instance = param_class_opt_ipv4_tcp; 921 p_hxge_param_t param_arr; 922 923 param_arr = hxgep->param_arr; 924 for (i = TCAM_CLASS_TCP_IPV4; i <= TCAM_CLASS_SCTP_IPV6; i++) { 925 if (strcmp(param_arr[class_instance].name, name) == 0) 926 return (i); 927 class_instance++; 928 } 929 return (-1); 930 } 931 932 /* ARGSUSED */ 933 int 934 hxge_param_set_ip_opt(p_hxge_t hxgep, queue_t *q, 935 mblk_t *mp, char *value, caddr_t cp) 936 { 937 char *end; 938 uint32_t status, cfg_value; 939 p_hxge_param_t pa = (p_hxge_param_t)cp; 940 tcam_class_t class; 941 uint32_t cfg_it = B_FALSE; 942 943 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_set_ip_opt")); 944 945 if (strncasecmp(value, "0x", 2) == 0) 946 value += 2; 947 948 cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX); 949 if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) { 950 return (EINVAL); 951 } 952 if (pa->value != cfg_value) { 953 pa->old_value = pa->value; 954 pa->value = cfg_value; 955 cfg_it = B_TRUE; 956 } 957 if (cfg_it == B_TRUE) { 958 /* do the actual hw setup */ 959 class = hxge_class_name_2value(hxgep, pa->name); 960 if (class == -1) 961 return (EINVAL); 962 963 status = hxge_pfc_ip_class_config(hxgep, class, pa->value); 964 if (status != HXGE_OK) 965 return (EINVAL); 966 } 967 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_set_ip_opt")); 968 return (0); 969 } 970 971 /* ARGSUSED */ 972 int 973 hxge_param_get_ip_opt(p_hxge_t hxgep, queue_t *q, mblk_t *mp, caddr_t cp) 974 { 975 uint32_t status, cfg_value; 976 p_hxge_param_t pa = (p_hxge_param_t)cp; 977 tcam_class_t class; 978 979 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_get_ip_opt")); 980 981 /* do the actual hw setup */ 982 class = hxge_class_name_2value(hxgep, pa->name); 983 if (class == -1) 984 return (EINVAL); 985 cfg_value = 0; 986 status = hxge_pfc_ip_class_config_get(hxgep, class, &cfg_value); 987 if (status != HXGE_OK) 988 return (EINVAL); 989 HXGE_DEBUG_MSG((hxgep, NDD_CTL, 990 "hxge_param_get_ip_opt_get %x ", cfg_value)); 991 pa->value = cfg_value; 992 993 if (mp != NULL) 994 (void) mi_mpprintf(mp, "%x", cfg_value); 995 996 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_get_ip_opt status ")); 997 return (0); 998 } 999 1000 /* ARGSUSED */ 1001 static int 1002 hxge_param_pfc_hash_init(p_hxge_t hxgep, queue_t *q, mblk_t *mp, 1003 char *value, caddr_t cp) 1004 { 1005 char *end; 1006 uint32_t status, cfg_value; 1007 p_hxge_param_t pa = (p_hxge_param_t)cp; 1008 uint32_t cfg_it = B_FALSE; 1009 1010 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_pfc_hash_init")); 1011 1012 if (strncasecmp(value, "0x", 2) == 0) 1013 value += 2; 1014 1015 cfg_value = (uint32_t)mi_strtol(value, &end, BASE_HEX); 1016 if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) { 1017 return (EINVAL); 1018 } 1019 1020 HXGE_DEBUG_MSG((hxgep, NDD_CTL, 1021 " hxge_param_pfc_hash_init value %x", cfg_value)); 1022 if (pa->value != cfg_value) { 1023 pa->old_value = pa->value; 1024 pa->value = cfg_value; 1025 cfg_it = B_TRUE; 1026 } 1027 1028 if (cfg_it == B_TRUE) { 1029 status = hxge_pfc_set_hash(hxgep, (uint32_t)pa->value); 1030 if (status != HXGE_OK) 1031 return (EINVAL); 1032 } 1033 HXGE_DEBUG_MSG((hxgep, NDD_CTL, " <== hxge_param_pfc_hash_init")); 1034 return (0); 1035 } 1036 1037 /* ARGSUSED */ 1038 static int 1039 hxge_param_set_hxge_debug_flag(p_hxge_t hxgep, queue_t *q, 1040 mblk_t *mp, char *value, caddr_t cp) 1041 { 1042 char *end; 1043 uint32_t status = 0; 1044 uint64_t cfg_value = 0; 1045 p_hxge_param_t pa = (p_hxge_param_t)cp; 1046 uint32_t cfg_it = B_FALSE; 1047 1048 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_set_hxge_debug_flag")); 1049 1050 if (strncasecmp(value, "0x", 2) == 0) 1051 value += 2; 1052 1053 cfg_value = mi_strtol(value, &end, BASE_HEX); 1054 1055 if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) { 1056 HXGE_DEBUG_MSG((hxgep, NDD_CTL, 1057 " hxge_param_set_hxge_debug_flag" 1058 " outof range %llx", cfg_value)); 1059 return (EINVAL); 1060 } 1061 if (pa->value != cfg_value) { 1062 pa->old_value = pa->value; 1063 pa->value = cfg_value; 1064 cfg_it = B_TRUE; 1065 } 1066 if (cfg_it == B_TRUE) 1067 hxgep->hxge_debug_level = pa->value; 1068 1069 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_set_hxge_debug_flag")); 1070 return (status); 1071 } 1072 1073 /* ARGSUSED */ 1074 static int 1075 hxge_param_get_debug_flag(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, caddr_t cp) 1076 { 1077 int status = 0; 1078 p_hxge_param_t pa = (p_hxge_param_t)cp; 1079 1080 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_get_debug_flag")); 1081 1082 if (pa->value > 0xffffffff) 1083 (void) mi_mpprintf(mp, "%x%x", (int)(pa->value >> 32), 1084 (int)(pa->value & 0xffffffff)); 1085 else 1086 (void) mi_mpprintf(mp, "%x", (int)pa->value); 1087 1088 1089 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_get_debug_flag")); 1090 return (status); 1091 } 1092 1093 /* ARGSUSED */ 1094 static int 1095 hxge_param_set_hpi_debug_flag(p_hxge_t hxgep, queue_t *q, 1096 mblk_t *mp, char *value, caddr_t cp) 1097 { 1098 char *end; 1099 uint32_t status = 0; 1100 uint64_t cfg_value = 0; 1101 p_hxge_param_t pa = (p_hxge_param_t)cp; 1102 uint32_t cfg_it = B_FALSE; 1103 1104 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_param_set_hpi_debug_flag")); 1105 1106 if (strncasecmp(value, "0x", 2) == 0) 1107 value += 2; 1108 1109 cfg_value = mi_strtol(value, &end, BASE_HEX); 1110 1111 if (PARAM_OUTOF_RANGE(value, end, cfg_value, pa)) { 1112 HXGE_DEBUG_MSG((hxgep, NDD_CTL, " hxge_param_set_hpi_debug_flag" 1113 " outof range %llx", cfg_value)); 1114 return (EINVAL); 1115 } 1116 if (pa->value != cfg_value) { 1117 pa->old_value = pa->value; 1118 pa->value = cfg_value; 1119 cfg_it = B_TRUE; 1120 } 1121 if (cfg_it == B_TRUE) { 1122 hpi_debug_level = pa->value; 1123 } 1124 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_param_set_debug_flag")); 1125 return (status); 1126 } 1127 1128 typedef struct block_info { 1129 char *name; 1130 uint32_t offset; 1131 } block_info_t; 1132 1133 block_info_t reg_block[] = { 1134 {"PIO", PIO_BASE_ADDR}, 1135 {"PIO_LDSV", PIO_LDSV_BASE_ADDR}, 1136 {"PIO_LDMASK", PIO_LDMASK_BASE_ADDR}, 1137 {"PFC", PFC_BASE_ADDR}, 1138 {"RDC", RDC_BASE_ADDR}, 1139 {"TDC", TDC_BASE_ADDR}, 1140 {"VMAC", VMAC_BASE_ADDR}, 1141 {"END", ALL_FF_32}, 1142 }; 1143 1144 /* ARGSUSED */ 1145 static int 1146 hxge_param_dump_ptrs(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, caddr_t cp) 1147 { 1148 uint_t print_len, buf_len; 1149 p_mblk_t np; 1150 int rdc, tdc, block; 1151 uint64_t base; 1152 p_hxge_dma_pt_cfg_t p_dma_cfgp; 1153 p_hxge_hw_pt_cfg_t p_cfgp; 1154 int buff_alloc_size = HXGE_NDD_INFODUMP_BUFF_8K; 1155 p_tx_ring_t *tx_rings; 1156 p_rx_rcr_rings_t rx_rcr_rings; 1157 p_rx_rcr_ring_t *rcr_rings; 1158 p_rx_rbr_rings_t rx_rbr_rings; 1159 p_rx_rbr_ring_t *rbr_rings; 1160 1161 HXGE_DEBUG_MSG((hxgep, IOC_CTL, "==> hxge_param_dump_ptrs")); 1162 1163 (void) mi_mpprintf(mp, "ptr information\n"); 1164 1165 if ((np = allocb(buff_alloc_size, BPRI_HI)) == NULL) { 1166 /* The following may work even if we cannot get a large buf. */ 1167 (void) mi_mpprintf(mp, "%s\n", "out of buffer"); 1168 return (0); 1169 } 1170 buf_len = buff_alloc_size; 1171 1172 mp->b_cont = np; 1173 p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 1174 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 1175 1176 rx_rcr_rings = hxgep->rx_rcr_rings; 1177 rcr_rings = rx_rcr_rings->rcr_rings; 1178 rx_rbr_rings = hxgep->rx_rbr_rings; 1179 rbr_rings = rx_rbr_rings->rbr_rings; 1180 print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len, 1181 "hxgep (hxge_t) $%p\n dev_regs (dev_regs_t) $%p\n", 1182 (void *)hxgep, (void *)hxgep->dev_regs); 1183 1184 ADVANCE_PRINT_BUFFER(np, print_len, buf_len); 1185 /* do register pointers */ 1186 print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len, 1187 "reg base (hpi_reg_ptr_t) $%p\t pci reg (hpi_reg_ptr_t) $%p\n", 1188 (void *)hxgep->dev_regs->hxge_regp, 1189 (void *)hxgep->dev_regs->hxge_pciregp); 1190 1191 ADVANCE_PRINT_BUFFER(np, print_len, buf_len); 1192 1193 print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len, 1194 "\nBlock \t Offset \n"); 1195 1196 ADVANCE_PRINT_BUFFER(np, print_len, buf_len); 1197 block = 0; 1198 base = (uint64_t)hxgep->dev_regs->hxge_regp; 1199 while (reg_block[block].offset != ALL_FF_32) { 1200 print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len, 1201 "%9s\t 0x%llx\n", reg_block[block].name, 1202 (unsigned long long) (reg_block[block].offset + base)); 1203 ADVANCE_PRINT_BUFFER(np, print_len, buf_len); 1204 block++; 1205 } 1206 1207 print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len, 1208 "\nRDC\t rcrp (rx_rcr_ring_t)\t rbrp (rx_rbr_ring_t)\n"); 1209 1210 ADVANCE_PRINT_BUFFER(np, print_len, buf_len); 1211 1212 for (rdc = 0; rdc < p_cfgp->max_rdcs; rdc++) { 1213 print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len, 1214 " %d\t $%p\t\t $%p\n", 1215 rdc, (void *)rcr_rings[rdc], (void *)rbr_rings[rdc]); 1216 ADVANCE_PRINT_BUFFER(np, print_len, buf_len); 1217 } 1218 1219 print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len, 1220 "\nTDC\t tdcp (tx_ring_t)\n"); 1221 1222 ADVANCE_PRINT_BUFFER(np, print_len, buf_len); 1223 tx_rings = hxgep->tx_rings->rings; 1224 for (tdc = 0; tdc < p_cfgp->max_tdcs; tdc++) { 1225 print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len, 1226 " %d\t $%p\n", tdc, (void *)tx_rings[tdc]); 1227 ADVANCE_PRINT_BUFFER(np, print_len, buf_len); 1228 } 1229 1230 print_len = snprintf((char *)((mblk_t *)np)->b_wptr, buf_len, "\n\n"); 1231 1232 ADVANCE_PRINT_BUFFER(np, print_len, buf_len); 1233 HXGE_DEBUG_MSG((hxgep, IOC_CTL, "<== hxge_param_dump_ptrs")); 1234 return (0); 1235 } 1236 1237 /* 1238 * Load 'name' into the named dispatch table pointed to by 'ndp'. 1239 * 'ndp' should be the address of a char pointer cell. If the table 1240 * does not exist (*ndp == 0), a new table is allocated and 'ndp' 1241 * is stuffed. If there is not enough space in the table for a new 1242 * entry, more space is allocated. 1243 */ 1244 boolean_t 1245 hxge_nd_load(caddr_t *pparam, char *name, 1246 pfi_t get_pfi, pfi_t set_pfi, caddr_t data) 1247 { 1248 ND *nd; 1249 NDE *nde; 1250 1251 HXGE_DEBUG_MSG((NULL, NDD2_CTL, " ==> hxge_nd_load: %s", name)); 1252 if (!pparam) 1253 return (B_FALSE); 1254 if ((nd = (ND *) * pparam) == NULL) { 1255 if ((nd = (ND *) KMEM_ZALLOC(sizeof (ND), KM_NOSLEEP)) == NULL) 1256 return (B_FALSE); 1257 *pparam = (caddr_t)nd; 1258 } 1259 if (nd->nd_tbl) { 1260 for (nde = nd->nd_tbl; nde->nde_name; nde++) { 1261 if (strcmp(name, nde->nde_name) == 0) 1262 goto fill_it; 1263 } 1264 } 1265 if (nd->nd_free_count <= 1) { 1266 if ((nde = (NDE *) KMEM_ZALLOC(nd->nd_size + 1267 NDE_ALLOC_SIZE, KM_NOSLEEP)) == NULL) 1268 return (B_FALSE); 1269 nd->nd_free_count += NDE_ALLOC_COUNT; 1270 if (nd->nd_tbl) { 1271 bcopy((char *)nd->nd_tbl, (char *)nde, nd->nd_size); 1272 KMEM_FREE((char *)nd->nd_tbl, nd->nd_size); 1273 } else { 1274 nd->nd_free_count--; 1275 nde->nde_name = "?"; 1276 nde->nde_get_pfi = hxge_nd_get_names; 1277 nde->nde_set_pfi = hxge_set_default; 1278 } 1279 nde->nde_data = (caddr_t)nd; 1280 nd->nd_tbl = nde; 1281 nd->nd_size += NDE_ALLOC_SIZE; 1282 } 1283 for (nde = nd->nd_tbl; nde->nde_name; nde++) 1284 noop; 1285 nd->nd_free_count--; 1286 fill_it: 1287 nde->nde_name = name; 1288 nde->nde_get_pfi = get_pfi; 1289 nde->nde_set_pfi = set_pfi; 1290 nde->nde_data = data; 1291 HXGE_DEBUG_MSG((NULL, NDD2_CTL, " <== hxge_nd_load")); 1292 1293 return (B_TRUE); 1294 } 1295 1296 /* 1297 * Free the table pointed to by 'pparam' 1298 */ 1299 void 1300 hxge_nd_free(caddr_t *pparam) 1301 { 1302 ND *nd; 1303 1304 if ((nd = (ND *)*pparam) != NULL) { 1305 if (nd->nd_tbl) 1306 KMEM_FREE((char *)nd->nd_tbl, nd->nd_size); 1307 KMEM_FREE((char *)nd, sizeof (ND)); 1308 *pparam = nil(caddr_t); 1309 } 1310 } 1311 1312 int 1313 hxge_nd_getset(p_hxge_t hxgep, queue_t *q, caddr_t param, p_mblk_t mp) 1314 { 1315 int err; 1316 IOCP iocp; 1317 p_mblk_t mp1, mp2; 1318 ND *nd; 1319 NDE *nde; 1320 char *valp; 1321 1322 size_t avail; 1323 1324 if (!param) { 1325 return (B_FALSE); 1326 } 1327 nd = (ND *) param; 1328 iocp = (IOCP) mp->b_rptr; 1329 if ((iocp->ioc_count == 0) || !(mp1 = mp->b_cont)) { 1330 mp->b_datap->db_type = M_IOCACK; 1331 iocp->ioc_count = 0; 1332 iocp->ioc_error = EINVAL; 1333 return (B_FALSE); 1334 } 1335 /* 1336 * NOTE - logic throughout nd_xxx assumes single data block for ioctl. 1337 * However, existing code sends in some big buffers. 1338 */ 1339 avail = iocp->ioc_count; 1340 if (mp1->b_cont) { 1341 freemsg(mp1->b_cont); 1342 mp1->b_cont = NULL; 1343 } 1344 mp1->b_datap->db_lim[-1] = '\0'; /* Force null termination */ 1345 for (valp = (char *)mp1->b_rptr; *valp != '\0'; valp++) { 1346 if (*valp == '-') 1347 *valp = '_'; 1348 } 1349 1350 valp = (char *)mp1->b_rptr; 1351 1352 for (nde = nd->nd_tbl; /* */; nde++) { 1353 if (!nde->nde_name) 1354 return (B_FALSE); 1355 if (strcmp(nde->nde_name, valp) == 0) 1356 break; 1357 } 1358 err = EINVAL; 1359 while (*valp++) 1360 noop; 1361 if (!*valp || valp >= (char *)mp1->b_wptr) 1362 valp = nilp(char); 1363 switch (iocp->ioc_cmd) { 1364 case ND_GET: 1365 if (*nde->nde_get_pfi == NULL) 1366 return (B_FALSE); 1367 1368 /* 1369 * (temporary) hack: "*valp" is size of user buffer for 1370 * copyout. If result of action routine is too big, free excess 1371 * and return ioc_rval as buffer size needed. Return as many 1372 * mblocks as will fit, free the rest. For backward 1373 * compatibility, assume size of original ioctl buffer if 1374 * "*valp" bad or not given. 1375 */ 1376 if (valp) 1377 avail = mi_strtol(valp, (char **)0, 10); 1378 /* 1379 * We overwrite the name/value with the reply data 1380 */ 1381 mp2 = mp1; 1382 while (mp2) { 1383 mp2->b_wptr = mp2->b_rptr; 1384 mp2 = mp2->b_cont; 1385 } 1386 1387 err = (*nde->nde_get_pfi) (hxgep, q, mp1, nde->nde_data); 1388 1389 if (!err) { 1390 size_t size_out = 0; 1391 ssize_t excess; 1392 1393 iocp->ioc_rval = 0; 1394 1395 /* Tack on the null */ 1396 err = hxge_mk_mblk_tail_space(mp1, &mp2, 1); 1397 if (!err) { 1398 *mp2->b_wptr++ = '\0'; 1399 size_out = msgdsize(mp1); 1400 excess = size_out - avail; 1401 if (excess > 0) { 1402 iocp->ioc_rval = (int)size_out; 1403 size_out -= excess; 1404 (void) adjmsg(mp1, -(excess + 1)); 1405 err = hxge_mk_mblk_tail_space( 1406 mp1, &mp2, 1); 1407 if (!err) 1408 *mp2->b_wptr++ = '\0'; 1409 else 1410 size_out = 0; 1411 } 1412 } else 1413 size_out = 0; 1414 iocp->ioc_count = size_out; 1415 } 1416 break; 1417 1418 case ND_SET: 1419 if (valp) { 1420 if (nde->nde_set_pfi) { 1421 err = (*nde->nde_set_pfi) (hxgep, q, mp1, valp, 1422 nde->nde_data); 1423 iocp->ioc_count = 0; 1424 freemsg(mp1); 1425 mp->b_cont = NULL; 1426 } 1427 } 1428 break; 1429 1430 default: 1431 break; 1432 } 1433 iocp->ioc_error = err; 1434 mp->b_datap->db_type = M_IOCACK; 1435 return (B_TRUE); 1436 } 1437 1438 /* ARGSUSED */ 1439 int 1440 hxge_nd_get_names(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, caddr_t param) 1441 { 1442 ND *nd; 1443 NDE *nde; 1444 char *rwtag; 1445 boolean_t get_ok, set_ok; 1446 size_t param_len; 1447 int status = 0; 1448 1449 nd = (ND *) param; 1450 if (!nd) 1451 return (ENOENT); 1452 1453 for (nde = nd->nd_tbl; nde->nde_name; nde++) { 1454 get_ok = (nde->nde_get_pfi != hxge_get_default) && 1455 (nde->nde_get_pfi != NULL); 1456 set_ok = (nde->nde_set_pfi != hxge_set_default) && 1457 (nde->nde_set_pfi != NULL); 1458 if (get_ok) { 1459 if (set_ok) 1460 rwtag = "read and write"; 1461 else 1462 rwtag = "read only"; 1463 } else if (set_ok) 1464 rwtag = "write only"; 1465 else { 1466 continue; 1467 } 1468 param_len = strlen(rwtag); 1469 param_len += strlen(nde->nde_name); 1470 param_len += 4; 1471 1472 (void) mi_mpprintf(mp, "%s (%s)", nde->nde_name, rwtag); 1473 } 1474 return (status); 1475 } 1476 1477 /* ARGSUSED */ 1478 int 1479 hxge_get_default(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, caddr_t data) 1480 { 1481 return (EACCES); 1482 } 1483 1484 /* ARGSUSED */ 1485 int 1486 hxge_set_default(p_hxge_t hxgep, queue_t *q, p_mblk_t mp, char *value, 1487 caddr_t data) 1488 { 1489 return (EACCES); 1490 } 1491 1492 void 1493 hxge_param_ioctl(p_hxge_t hxgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp) 1494 { 1495 int cmd; 1496 int status = B_FALSE; 1497 1498 HXGE_DEBUG_MSG((hxgep, IOC_CTL, "==> hxge_param_ioctl")); 1499 cmd = iocp->ioc_cmd; 1500 switch (cmd) { 1501 default: 1502 HXGE_DEBUG_MSG((hxgep, IOC_CTL, 1503 "hxge_param_ioctl: bad cmd 0x%0x", cmd)); 1504 break; 1505 1506 case ND_GET: 1507 case ND_SET: 1508 HXGE_DEBUG_MSG((hxgep, IOC_CTL, 1509 "hxge_param_ioctl: cmd 0x%0x", cmd)); 1510 if (!hxge_nd_getset(hxgep, wq, hxgep->param_list, mp)) { 1511 HXGE_DEBUG_MSG((hxgep, IOC_CTL, 1512 "false ret from hxge_nd_getset")); 1513 break; 1514 } 1515 status = B_TRUE; 1516 break; 1517 } 1518 1519 if (status) { 1520 qreply(wq, mp); 1521 } else { 1522 miocnak(wq, mp, 0, EINVAL); 1523 } 1524 HXGE_DEBUG_MSG((hxgep, IOC_CTL, "<== hxge_param_ioctl")); 1525 } 1526