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