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
hxge_get_param_soft_properties(p_hxge_t hxgep)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
hxge_private_param_register(p_hxge_t hxgep,p_hxge_param_t param_arr)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
hxge_setup_param(p_hxge_t hxgep)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
hxge_init_param(p_hxge_t hxgep)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
hxge_destroy_param(p_hxge_t hxgep)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
hxge_param_get_generic(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,caddr_t cp)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
hxge_param_get_mac(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,caddr_t cp)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
hxge_param_get_rxdma_info(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,caddr_t cp)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
hxge_mk_mblk_tail_space(p_mblk_t mp,p_mblk_t * nmp,size_t size)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
hxge_param_set_generic(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)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
hxge_param_set_mac(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)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
hxge_param_rx_intr_pkts(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)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
hxge_param_rx_intr_time(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)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
hxge_param_set_vlan_ids(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)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
hxge_param_get_vlan_ids(p_hxge_t hxgep,queue_t * q,mblk_t * mp,caddr_t cp)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
hxge_param_tcam_enable(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)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
hxge_param_set_ether_usr(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)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
hxge_class_name_2value(p_hxge_t hxgep,char * name)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
hxge_param_set_ip_opt(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)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
hxge_param_get_ip_opt(p_hxge_t hxgep,queue_t * q,mblk_t * mp,caddr_t cp)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
hxge_param_pfc_hash_init(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)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
hxge_param_set_hxge_debug_flag(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)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
hxge_param_get_debug_flag(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,caddr_t cp)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
hxge_param_set_hpi_debug_flag(p_hxge_t hxgep,queue_t * q,mblk_t * mp,char * value,caddr_t cp)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
hxge_param_dump_ptrs(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,caddr_t cp)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
hxge_nd_load(caddr_t * pparam,char * name,pfi_t get_pfi,pfi_t set_pfi,caddr_t data)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
hxge_nd_free(caddr_t * pparam)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
hxge_nd_getset(p_hxge_t hxgep,queue_t * q,caddr_t param,p_mblk_t mp)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
hxge_nd_get_names(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,caddr_t param)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
hxge_get_default(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,caddr_t data)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
hxge_set_default(p_hxge_t hxgep,queue_t * q,p_mblk_t mp,char * value,caddr_t data)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
hxge_param_ioctl(p_hxge_t hxgep,queue_t * wq,mblk_t * mp,struct iocblk * iocp)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