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