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 * Copyright 2012 Milan Jurik. All rights reserved.
25 */
26
27 #include <hxge_impl.h>
28 #include <hxge_vmac.h>
29 #include <hxge_pfc.h>
30 #include <hpi_pfc.h>
31
32 static hxge_status_t hxge_get_mac_addr_properties(p_hxge_t);
33 static void hxge_use_cfg_hydra_properties(p_hxge_t);
34 static void hxge_use_cfg_dma_config(p_hxge_t);
35 static void hxge_use_cfg_class_config(p_hxge_t);
36 static void hxge_set_hw_dma_config(p_hxge_t);
37 static void hxge_set_hw_class_config(p_hxge_t);
38 static void hxge_ldgv_setup(p_hxge_ldg_t *ldgp, p_hxge_ldv_t *ldvp, uint8_t ldv,
39 uint8_t endldg, int *ngrps);
40
41 extern uint16_t hxge_rcr_timeout;
42 extern uint16_t hxge_rcr_threshold;
43
44 extern uint32_t hxge_rbr_size;
45 extern uint32_t hxge_rcr_size;
46
47 extern uint_t hxge_rx_intr(caddr_t, caddr_t);
48 extern uint_t hxge_tx_intr(caddr_t, caddr_t);
49 extern uint_t hxge_vmac_intr(caddr_t, caddr_t);
50 extern uint_t hxge_syserr_intr(caddr_t, caddr_t);
51 extern uint_t hxge_pfc_intr(caddr_t, caddr_t);
52
53 /*
54 * Entry point to populate configuration parameters into the master hxge
55 * data structure and to update the NDD parameter list.
56 */
57 hxge_status_t
hxge_get_config_properties(p_hxge_t hxgep)58 hxge_get_config_properties(p_hxge_t hxgep)
59 {
60 hxge_status_t status = HXGE_OK;
61
62 HXGE_DEBUG_MSG((hxgep, VPD_CTL, " ==> hxge_get_config_properties"));
63
64 if (hxgep->hxge_hw_p == NULL) {
65 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
66 " hxge_get_config_properties: common hardware not set"));
67 return (HXGE_ERROR);
68 }
69
70 hxgep->classifier.tcam_size = TCAM_HXGE_TCAM_MAX_ENTRY;
71
72 status = hxge_get_mac_addr_properties(hxgep);
73 if (status != HXGE_OK) {
74 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
75 " hxge_get_config_properties: mac addr properties failed"));
76 return (status);
77 }
78
79 HXGE_DEBUG_MSG((hxgep, VPD_CTL,
80 " ==> hxge_get_config_properties: Hydra"));
81
82 hxge_use_cfg_hydra_properties(hxgep);
83
84 HXGE_DEBUG_MSG((hxgep, VPD_CTL, " <== hxge_get_config_properties"));
85 return (HXGE_OK);
86 }
87
88
89 static void
hxge_set_hw_vlan_class_config(p_hxge_t hxgep)90 hxge_set_hw_vlan_class_config(p_hxge_t hxgep)
91 {
92 int i;
93 p_hxge_param_t param_arr;
94 uint_t vlan_cnt;
95 int *vlan_cfg_val;
96 hxge_param_map_t *vmap;
97 char *prop;
98 p_hxge_class_pt_cfg_t p_class_cfgp;
99 uint32_t good_cfg[32];
100 int good_count = 0;
101 hxge_mv_cfg_t *vlan_tbl;
102
103 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_set_hw_vlan_config"));
104 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
105
106 param_arr = hxgep->param_arr;
107 prop = param_arr[param_vlan_ids].fcode_name;
108
109 /*
110 * uint32_t array, each array entry specifying a VLAN id
111 */
112 for (i = 0; i <= VLAN_ID_MAX; i++) {
113 p_class_cfgp->vlan_tbl[i].flag = 0;
114 }
115
116 vlan_tbl = (hxge_mv_cfg_t *)&p_class_cfgp->vlan_tbl[0];
117 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0, prop,
118 &vlan_cfg_val, &vlan_cnt) != DDI_PROP_SUCCESS) {
119 return;
120 }
121
122 for (i = 0; i < vlan_cnt; i++) {
123 vmap = (hxge_param_map_t *)&vlan_cfg_val[i];
124 if ((vmap->param_id) && (vmap->param_id <= VLAN_ID_MAX)) {
125 HXGE_DEBUG_MSG((hxgep, CFG2_CTL,
126 " hxge_vlan_config vlan id %d", vmap->param_id));
127
128 good_cfg[good_count] = vlan_cfg_val[i];
129 if (vlan_tbl[vmap->param_id].flag == 0)
130 good_count++;
131
132 vlan_tbl[vmap->param_id].flag = 1;
133 }
134 }
135
136 ddi_prop_free(vlan_cfg_val);
137 if (good_count != vlan_cnt) {
138 (void) ddi_prop_update_int_array(DDI_DEV_T_NONE,
139 hxgep->dip, prop, (int *)good_cfg, good_count);
140 }
141
142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_set_hw_vlan_config"));
143 }
144
145
146 /*
147 * Read param_vlan_ids and param_implicit_vlan_id properties from either
148 * hxge.conf or OBP. Update the soft properties. Populate these
149 * properties into the hxge data structure.
150 */
151 static void
hxge_use_cfg_vlan_class_config(p_hxge_t hxgep)152 hxge_use_cfg_vlan_class_config(p_hxge_t hxgep)
153 {
154 uint_t vlan_cnt;
155 int *vlan_cfg_val;
156 int status;
157 p_hxge_param_t param_arr;
158 char *prop;
159 uint32_t implicit_vlan_id = 0;
160 int *int_prop_val;
161 uint_t prop_len;
162 p_hxge_param_t pa;
163
164 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_use_cfg_vlan_config"));
165 param_arr = hxgep->param_arr;
166 prop = param_arr[param_vlan_ids].fcode_name;
167
168 status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0, prop,
169 &vlan_cfg_val, &vlan_cnt);
170 if (status == DDI_PROP_SUCCESS) {
171 status = ddi_prop_update_int_array(DDI_DEV_T_NONE,
172 hxgep->dip, prop, vlan_cfg_val, vlan_cnt);
173 ddi_prop_free(vlan_cfg_val);
174 }
175
176 pa = ¶m_arr[param_implicit_vlan_id];
177 prop = pa->fcode_name;
178 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0, prop,
179 &int_prop_val, &prop_len) == DDI_PROP_SUCCESS) {
180 implicit_vlan_id = (uint32_t)*int_prop_val;
181 if ((implicit_vlan_id >= pa->minimum) ||
182 (implicit_vlan_id <= pa->maximum)) {
183 status = ddi_prop_update_int(DDI_DEV_T_NONE, hxgep->dip,
184 prop, (int)implicit_vlan_id);
185 }
186 ddi_prop_free(int_prop_val);
187 }
188
189 hxge_set_hw_vlan_class_config(hxgep);
190
191 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_use_cfg_vlan_config"));
192 }
193
194 /*
195 * Read in the configuration parameters from either hxge.conf or OBP and
196 * populate the master data structure hxge.
197 * Use these parameters to update the soft properties and the ndd array.
198 */
199 static void
hxge_use_cfg_hydra_properties(p_hxge_t hxgep)200 hxge_use_cfg_hydra_properties(p_hxge_t hxgep)
201 {
202 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_use_cfg_hydra_properties"));
203
204 (void) hxge_use_cfg_dma_config(hxgep);
205 (void) hxge_use_cfg_vlan_class_config(hxgep);
206 (void) hxge_use_cfg_class_config(hxgep);
207
208 /*
209 * Read in the hardware (fcode) properties and use these properties
210 * to update the ndd array.
211 */
212 (void) hxge_get_param_soft_properties(hxgep);
213 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_use_cfg_hydra_properties"));
214 }
215
216
217 /*
218 * Read param_accept_jumbo, param_rxdma_intr_time, and param_rxdma_intr_pkts
219 * from either hxge.conf or OBP.
220 * Update the soft properties.
221 * Populate these properties into the hxge data structure for latter use.
222 */
223 static void
hxge_use_cfg_dma_config(p_hxge_t hxgep)224 hxge_use_cfg_dma_config(p_hxge_t hxgep)
225 {
226 int tx_ndmas, rx_ndmas;
227 p_hxge_dma_pt_cfg_t p_dma_cfgp;
228 p_hxge_hw_pt_cfg_t p_cfgp;
229 dev_info_t *dip;
230 p_hxge_param_t param_arr;
231 char *prop;
232 int *prop_val;
233 uint_t prop_len;
234
235 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_use_cfg_dma_config"));
236 param_arr = hxgep->param_arr;
237
238 p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
239 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
240 dip = hxgep->dip;
241
242 tx_ndmas = 4;
243 p_cfgp->start_tdc = 0;
244 p_cfgp->max_tdcs = hxgep->max_tdcs = tx_ndmas;
245 hxgep->tdc_mask = (tx_ndmas - 1);
246 HXGE_DEBUG_MSG((hxgep, CFG_CTL, "==> hxge_use_cfg_dma_config: "
247 "p_cfgp 0x%llx max_tdcs %d hxgep->max_tdcs %d",
248 p_cfgp, p_cfgp->max_tdcs, hxgep->max_tdcs));
249
250 rx_ndmas = 4;
251 p_cfgp->start_rdc = 0;
252 p_cfgp->max_rdcs = hxgep->max_rdcs = rx_ndmas;
253
254 p_cfgp->start_ldg = 0;
255 p_cfgp->max_ldgs = HXGE_INT_MAX_LDG;
256
257 HXGE_DEBUG_MSG((hxgep, CFG_CTL, "==> hxge_use_default_dma_config: "
258 "p_cfgp 0x%llx max_rdcs %d hxgep->max_rdcs %d",
259 p_cfgp, p_cfgp->max_rdcs, hxgep->max_rdcs));
260
261 HXGE_DEBUG_MSG((hxgep, CFG_CTL, "==> hxge_use_cfg_dma_config: "
262 "p_cfgp 0x%016llx start_ldg %d hxgep->max_ldgs %d ",
263 p_cfgp, p_cfgp->start_ldg, p_cfgp->max_ldgs));
264
265 /*
266 * add code for individual rdc properties
267 */
268 prop = param_arr[param_accept_jumbo].fcode_name;
269
270 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
271 &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
272 if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) {
273 (void) ddi_prop_update_int_array(DDI_DEV_T_NONE,
274 hxgep->dip, prop, prop_val, prop_len);
275 }
276 ddi_prop_free(prop_val);
277 }
278
279 prop = param_arr[param_rxdma_intr_time].fcode_name;
280
281 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
282 &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
283 if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) {
284 (void) ddi_prop_update_int_array(DDI_DEV_T_NONE,
285 hxgep->dip, prop, prop_val, prop_len);
286 }
287 ddi_prop_free(prop_val);
288 }
289
290 prop = param_arr[param_rxdma_intr_pkts].fcode_name;
291
292 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
293 &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
294 if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) {
295 (void) ddi_prop_update_int_array(DDI_DEV_T_NONE,
296 hxgep->dip, prop, prop_val, prop_len);
297 }
298 ddi_prop_free(prop_val);
299 }
300
301 hxge_set_hw_dma_config(hxgep);
302 HXGE_DEBUG_MSG((hxgep, CFG_CTL, "<== hxge_use_cfg_dma_config"));
303 }
304
305 static void
hxge_use_cfg_class_config(p_hxge_t hxgep)306 hxge_use_cfg_class_config(p_hxge_t hxgep)
307 {
308 hxge_set_hw_class_config(hxgep);
309 }
310
311 static void
hxge_set_hw_dma_config(p_hxge_t hxgep)312 hxge_set_hw_dma_config(p_hxge_t hxgep)
313 {
314 p_hxge_dma_pt_cfg_t p_dma_cfgp;
315 p_hxge_hw_pt_cfg_t p_cfgp;
316
317 HXGE_DEBUG_MSG((hxgep, CFG_CTL, "==> hxge_set_hw_dma_config"));
318
319 p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
320 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
321
322 /* Transmit DMA Channels */
323 hxgep->ntdc = p_cfgp->max_tdcs;
324
325 /* Receive DMA Channels */
326 hxgep->nrdc = p_cfgp->max_rdcs;
327
328 p_dma_cfgp->rbr_size = hxge_rbr_size;
329 if (hxge_rcr_size > HXGE_RCR_MAX)
330 hxge_rcr_size = HXGE_RCR_MAX;
331 p_dma_cfgp->rcr_size = hxge_rcr_size;
332
333 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_set_hw_dma_config"));
334 }
335
336
337 boolean_t
hxge_check_rxdma_port_member(p_hxge_t hxgep,uint8_t rdc)338 hxge_check_rxdma_port_member(p_hxge_t hxgep, uint8_t rdc)
339 {
340 p_hxge_dma_pt_cfg_t p_dma_cfgp;
341 p_hxge_hw_pt_cfg_t p_cfgp;
342 int status = B_TRUE;
343
344 HXGE_DEBUG_MSG((hxgep, CFG2_CTL, "==> hxge_check_rxdma_port_member"));
345
346 p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
347 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
348
349 /* Receive DMA Channels */
350 if (rdc < p_cfgp->max_rdcs)
351 status = B_TRUE;
352 HXGE_DEBUG_MSG((hxgep, CFG2_CTL, " <== hxge_check_rxdma_port_member"));
353
354 return (status);
355 }
356
357 boolean_t
hxge_check_txdma_port_member(p_hxge_t hxgep,uint8_t tdc)358 hxge_check_txdma_port_member(p_hxge_t hxgep, uint8_t tdc)
359 {
360 p_hxge_dma_pt_cfg_t p_dma_cfgp;
361 p_hxge_hw_pt_cfg_t p_cfgp;
362 int status = B_FALSE;
363
364 HXGE_DEBUG_MSG((hxgep, CFG2_CTL, "==> hxge_check_txdma_port_member"));
365
366 p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
367 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
368
369 /* Receive DMA Channels */
370 if (tdc < p_cfgp->max_tdcs)
371 status = B_TRUE;
372 HXGE_DEBUG_MSG((hxgep, CFG2_CTL, " <== hxge_check_txdma_port_member"));
373
374 return (status);
375 }
376
377
378 /*
379 * Read the L2 classes, L3 classes, and initial hash from either hxge.conf
380 * or OBP. Populate these properties into the hxge data structure for latter
381 * use. Note that we are not updating these soft properties.
382 */
383 static void
hxge_set_hw_class_config(p_hxge_t hxgep)384 hxge_set_hw_class_config(p_hxge_t hxgep)
385 {
386 int i, j;
387 p_hxge_param_t param_arr;
388 int *int_prop_val;
389 uint32_t cfg_value;
390 char *prop;
391 p_hxge_class_pt_cfg_t p_class_cfgp;
392 int start_prop, end_prop;
393 uint_t prop_cnt;
394
395 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_set_hw_class_config"));
396
397 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
398
399 param_arr = hxgep->param_arr;
400
401 /*
402 * L2 class configuration. User configurable ether types
403 */
404 start_prop = param_class_cfg_ether_usr1;
405 end_prop = param_class_cfg_ether_usr2;
406
407 for (i = start_prop; i <= end_prop; i++) {
408 prop = param_arr[i].fcode_name;
409 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip,
410 0, prop, &int_prop_val, &prop_cnt) == DDI_PROP_SUCCESS) {
411 cfg_value = (uint32_t)*int_prop_val;
412 ddi_prop_free(int_prop_val);
413 } else {
414 cfg_value = (uint32_t)param_arr[i].value;
415 }
416
417 j = (i - start_prop) + TCAM_CLASS_ETYPE_1;
418 p_class_cfgp->class_cfg[j] = cfg_value;
419 }
420
421 /*
422 * Use properties from either .conf or the NDD param array. Only bits
423 * 2 and 3 are significant
424 */
425 start_prop = param_class_opt_ipv4_tcp;
426 end_prop = param_class_opt_ipv6_sctp;
427
428 for (i = start_prop; i <= end_prop; i++) {
429 prop = param_arr[i].fcode_name;
430 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip,
431 0, prop, &int_prop_val, &prop_cnt) == DDI_PROP_SUCCESS) {
432 cfg_value = (uint32_t)*int_prop_val;
433 ddi_prop_free(int_prop_val);
434 } else {
435 cfg_value = (uint32_t)param_arr[i].value;
436 }
437
438 j = (i - start_prop) + TCAM_CLASS_TCP_IPV4;
439 p_class_cfgp->class_cfg[j] = cfg_value;
440 }
441
442 prop = param_arr[param_hash_init_value].fcode_name;
443
444 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0, prop,
445 &int_prop_val, &prop_cnt) == DDI_PROP_SUCCESS) {
446 cfg_value = (uint32_t)*int_prop_val;
447 ddi_prop_free(int_prop_val);
448 } else {
449 cfg_value = (uint32_t)param_arr[param_hash_init_value].value;
450 }
451
452 p_class_cfgp->init_hash = (uint32_t)cfg_value;
453
454 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_set_hw_class_config"));
455 }
456
457
458 /*
459 * Interrupts related interface functions.
460 */
461 hxge_status_t
hxge_ldgv_init(p_hxge_t hxgep,int * navail_p,int * nrequired_p)462 hxge_ldgv_init(p_hxge_t hxgep, int *navail_p, int *nrequired_p)
463 {
464 uint8_t ldv, i, maxldvs, maxldgs, start, end, nldvs;
465 int ldg, endldg, ngrps;
466 uint8_t channel;
467 p_hxge_dma_pt_cfg_t p_dma_cfgp;
468 p_hxge_hw_pt_cfg_t p_cfgp;
469 p_hxge_ldgv_t ldgvp;
470 p_hxge_ldg_t ldgp, ptr;
471 p_hxge_ldv_t ldvp;
472 hxge_status_t status = HXGE_OK;
473 peu_intr_mask_t parity_err_mask;
474
475 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_ldgv_init"));
476 if (!*navail_p) {
477 *nrequired_p = 0;
478 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
479 "<== hxge_ldgv_init:no avail"));
480 return (HXGE_ERROR);
481 }
482 p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
483 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
484
485 /* each DMA channels */
486 nldvs = p_cfgp->max_tdcs + p_cfgp->max_rdcs;
487
488 /* vmac */
489 nldvs++;
490
491 /* pfc */
492 nldvs++;
493
494 /* system error interrupts. */
495 nldvs++;
496
497 maxldvs = nldvs;
498 maxldgs = p_cfgp->max_ldgs;
499
500 if (!maxldvs || !maxldgs) {
501 /* No devices configured. */
502 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_ldgv_init: "
503 "no logical devices or groups configured."));
504 return (HXGE_ERROR);
505 }
506 ldgvp = hxgep->ldgvp;
507 if (ldgvp == NULL) {
508 ldgvp = KMEM_ZALLOC(sizeof (hxge_ldgv_t), KM_SLEEP);
509 hxgep->ldgvp = ldgvp;
510 ldgvp->maxldgs = maxldgs;
511 ldgvp->maxldvs = maxldvs;
512 ldgp = ldgvp->ldgp =
513 KMEM_ZALLOC(sizeof (hxge_ldg_t) * maxldgs, KM_SLEEP);
514 ldvp = ldgvp->ldvp =
515 KMEM_ZALLOC(sizeof (hxge_ldv_t) * maxldvs, KM_SLEEP);
516 }
517
518 ldgvp->ndma_ldvs = p_cfgp->max_tdcs + p_cfgp->max_rdcs;
519 ldgvp->tmres = HXGE_TIMER_RESO;
520
521 HXGE_DEBUG_MSG((hxgep, INT_CTL,
522 "==> hxge_ldgv_init: maxldvs %d maxldgs %d nldvs %d",
523 maxldvs, maxldgs, nldvs));
524
525 ldg = p_cfgp->start_ldg;
526 ptr = ldgp;
527 for (i = 0; i < maxldgs; i++) {
528 ptr->arm = B_TRUE;
529 ptr->vldg_index = i;
530 ptr->ldg_timer = HXGE_TIMER_LDG;
531 ptr->ldg = ldg++;
532 ptr->sys_intr_handler = hxge_intr;
533 ptr->nldvs = 0;
534 ptr->hxgep = hxgep;
535 HXGE_DEBUG_MSG((hxgep, INT_CTL,
536 "==> hxge_ldgv_init: maxldvs %d maxldgs %d ldg %d",
537 maxldvs, maxldgs, ptr->ldg));
538 HXGE_DEBUG_MSG((hxgep, INT_CTL,
539 "==> hxge_ldv_init: timer %d", ptr->ldg_timer));
540 ptr++;
541 }
542
543 ldg = p_cfgp->start_ldg;
544 if (maxldgs > *navail_p) {
545 ngrps = *navail_p;
546 } else {
547 ngrps = maxldgs;
548 }
549 endldg = ldg + ngrps;
550
551 /*
552 * Receive DMA channels.
553 */
554 channel = p_cfgp->start_rdc;
555 start = p_cfgp->start_rdc + HXGE_RDMA_LD_START;
556 end = start + p_cfgp->max_rdcs;
557 nldvs = 0;
558 ldgvp->nldvs = 0;
559 ldgp->ldvp = NULL;
560 *nrequired_p = 0;
561 ptr = ldgp;
562
563 /*
564 * Start with RDC to configure logical devices for each group.
565 */
566 for (i = 0, ldv = start; ldv < end; i++, ldv++) {
567 ldvp->is_rxdma = B_TRUE;
568 ldvp->ldv = ldv;
569
570 /*
571 * If non-seq needs to change the following code
572 */
573 ldvp->channel = channel++;
574 ldvp->vdma_index = i;
575 ldvp->ldv_intr_handler = hxge_rx_intr;
576 ldvp->ldv_ldf_masks = 0;
577 ldvp->use_timer = B_FALSE;
578 ldvp->hxgep = hxgep;
579 hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p);
580 nldvs++;
581 }
582
583 /*
584 * Transmit DMA channels.
585 */
586 channel = p_cfgp->start_tdc;
587 start = p_cfgp->start_tdc + HXGE_TDMA_LD_START;
588 end = start + p_cfgp->max_tdcs;
589 for (i = 0, ldv = start; ldv < end; i++, ldv++) {
590 ldvp->is_txdma = B_TRUE;
591 ldvp->ldv = ldv;
592 ldvp->channel = channel++;
593 ldvp->vdma_index = i;
594 ldvp->ldv_intr_handler = hxge_tx_intr;
595 ldvp->ldv_ldf_masks = 0;
596 ldvp->use_timer = B_FALSE;
597 ldvp->hxgep = hxgep;
598 hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p);
599 nldvs++;
600 }
601
602 /*
603 * VMAC
604 */
605 ldvp->is_vmac = B_TRUE;
606 ldvp->ldv_intr_handler = hxge_vmac_intr;
607 ldvp->ldv_ldf_masks = 0;
608 ldv = HXGE_VMAC_LD;
609 ldvp->ldv = ldv;
610 ldvp->use_timer = B_FALSE;
611 ldvp->hxgep = hxgep;
612 hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p);
613 nldvs++;
614
615 HXGE_DEBUG_MSG((hxgep, INT_CTL,
616 "==> hxge_ldgv_init: nldvs %d navail %d nrequired %d",
617 nldvs, *navail_p, *nrequired_p));
618
619 /*
620 * PFC
621 */
622 ldvp->is_pfc = B_TRUE;
623 ldvp->ldv_intr_handler = hxge_pfc_intr;
624 ldvp->ldv_ldf_masks = 0;
625 ldv = HXGE_PFC_LD;
626 ldvp->ldv = ldv;
627 ldvp->use_timer = B_FALSE;
628 ldvp->hxgep = hxgep;
629 hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p);
630 nldvs++;
631
632 HXGE_DEBUG_MSG((hxgep, INT_CTL,
633 "==> hxge_ldgv_init: nldvs %d navail %d nrequired %d",
634 nldvs, *navail_p, *nrequired_p));
635
636 /*
637 * System error interrupts.
638 */
639 ldv = HXGE_SYS_ERROR_LD;
640 ldvp->ldv = ldv;
641 ldvp->is_syserr = B_TRUE;
642 ldvp->ldv_intr_handler = hxge_syserr_intr;
643 ldvp->ldv_ldf_masks = 0;
644 ldvp->hxgep = hxgep;
645 ldvp->use_timer = B_FALSE;
646 ldgvp->ldvp_syserr = ldvp;
647
648 /* Reset PEU error mask to allow PEU error interrupts */
649 /*
650 * Keep the msix parity error mask here and remove it
651 * after ddi_intr_enable call to avoid a msix par err
652 */
653 parity_err_mask.value = 0;
654 parity_err_mask.bits.eic_msix_parerr_mask = 1;
655 HXGE_REG_WR32(hxgep->hpi_handle, PEU_INTR_MASK, parity_err_mask.value);
656
657 /*
658 * Unmask the system interrupt states.
659 */
660 (void) hxge_fzc_sys_err_mask_set(hxgep, B_FALSE);
661 (void) hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p);
662 nldvs++;
663
664 ldgvp->ldg_intrs = *nrequired_p;
665
666 HXGE_DEBUG_MSG((hxgep, INT_CTL,
667 "==> hxge_ldgv_init: nldvs %d navail %d nrequired %d",
668 nldvs, *navail_p, *nrequired_p));
669 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_ldgv_init"));
670 return (status);
671 }
672
673 hxge_status_t
hxge_ldgv_uninit(p_hxge_t hxgep)674 hxge_ldgv_uninit(p_hxge_t hxgep)
675 {
676 p_hxge_ldgv_t ldgvp;
677
678 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_ldgv_uninit"));
679 ldgvp = hxgep->ldgvp;
680 if (ldgvp == NULL) {
681 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
682 "<== hxge_ldgv_uninit: no logical group configured."));
683 return (HXGE_OK);
684 }
685
686 if (ldgvp->ldgp) {
687 KMEM_FREE(ldgvp->ldgp, sizeof (hxge_ldg_t) * ldgvp->maxldgs);
688 }
689 if (ldgvp->ldvp) {
690 KMEM_FREE(ldgvp->ldvp, sizeof (hxge_ldv_t) * ldgvp->maxldvs);
691 }
692
693 KMEM_FREE(ldgvp, sizeof (hxge_ldgv_t));
694 hxgep->ldgvp = NULL;
695
696 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_ldgv_uninit"));
697 return (HXGE_OK);
698 }
699
700 hxge_status_t
hxge_intr_ldgv_init(p_hxge_t hxgep)701 hxge_intr_ldgv_init(p_hxge_t hxgep)
702 {
703 hxge_status_t status = HXGE_OK;
704
705 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intr_ldgv_init"));
706 /*
707 * Configure the logical device group numbers, state vectors
708 * and interrupt masks for each logical device.
709 */
710 status = hxge_fzc_intr_init(hxgep);
711
712 /*
713 * Configure logical device masks and timers.
714 */
715 status = hxge_intr_mask_mgmt(hxgep);
716
717 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intr_ldgv_init"));
718 return (status);
719 }
720
721 hxge_status_t
hxge_intr_mask_mgmt(p_hxge_t hxgep)722 hxge_intr_mask_mgmt(p_hxge_t hxgep)
723 {
724 p_hxge_ldgv_t ldgvp;
725 p_hxge_ldg_t ldgp;
726 p_hxge_ldv_t ldvp;
727 hpi_handle_t handle;
728 int i, j;
729 hpi_status_t rs = HPI_SUCCESS;
730
731 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intr_mask_mgmt"));
732
733 if ((ldgvp = hxgep->ldgvp) == NULL) {
734 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
735 "<== hxge_intr_mask_mgmt: Null ldgvp"));
736 return (HXGE_ERROR);
737 }
738 handle = HXGE_DEV_HPI_HANDLE(hxgep);
739 ldgp = ldgvp->ldgp;
740 ldvp = ldgvp->ldvp;
741 if (ldgp == NULL || ldvp == NULL) {
742 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
743 "<== hxge_intr_mask_mgmt: Null ldgp or ldvp"));
744 return (HXGE_ERROR);
745 }
746
747 HXGE_DEBUG_MSG((hxgep, INT_CTL,
748 "==> hxge_intr_mask_mgmt: # of intrs %d ", ldgvp->ldg_intrs));
749 /* Initialize masks. */
750 HXGE_DEBUG_MSG((hxgep, INT_CTL,
751 "==> hxge_intr_mask_mgmt(Hydra): # intrs %d ", ldgvp->ldg_intrs));
752 for (i = 0; i < ldgvp->ldg_intrs; i++, ldgp++) {
753 HXGE_DEBUG_MSG((hxgep, INT_CTL,
754 "==> hxge_intr_mask_mgmt(Hydra): # ldv %d in group %d",
755 ldgp->nldvs, ldgp->ldg));
756 for (j = 0; j < ldgp->nldvs; j++, ldvp++) {
757 HXGE_DEBUG_MSG((hxgep, INT_CTL,
758 "==> hxge_intr_mask_mgmt: set ldv # %d "
759 "for ldg %d", ldvp->ldv, ldgp->ldg));
760 rs = hpi_intr_mask_set(handle, ldvp->ldv,
761 ldvp->ldv_ldf_masks);
762 if (rs != HPI_SUCCESS) {
763 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
764 "<== hxge_intr_mask_mgmt: set mask failed "
765 " rs 0x%x ldv %d mask 0x%x",
766 rs, ldvp->ldv, ldvp->ldv_ldf_masks));
767 return (HXGE_ERROR | rs);
768 }
769 HXGE_DEBUG_MSG((hxgep, INT_CTL,
770 "==> hxge_intr_mask_mgmt: set mask OK "
771 " rs 0x%x ldv %d mask 0x%x",
772 rs, ldvp->ldv, ldvp->ldv_ldf_masks));
773 }
774 }
775
776 ldgp = ldgvp->ldgp;
777 /* Configure timer and arm bit */
778 for (i = 0; i < hxgep->ldgvp->ldg_intrs; i++, ldgp++) {
779 rs = hpi_intr_ldg_mgmt_set(handle, ldgp->ldg,
780 ldgp->arm, ldgp->ldg_timer);
781 if (rs != HPI_SUCCESS) {
782 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
783 "<== hxge_intr_mask_mgmt: set timer failed "
784 " rs 0x%x dg %d timer 0x%x",
785 rs, ldgp->ldg, ldgp->ldg_timer));
786 return (HXGE_ERROR | rs);
787 }
788 HXGE_DEBUG_MSG((hxgep, INT_CTL,
789 "==> hxge_intr_mask_mgmt: set timer OK "
790 " rs 0x%x ldg %d timer 0x%x",
791 rs, ldgp->ldg, ldgp->ldg_timer));
792 }
793
794 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_fzc_intr_mask_mgmt"));
795 return (HXGE_OK);
796 }
797
798 hxge_status_t
hxge_intr_mask_mgmt_set(p_hxge_t hxgep,boolean_t on)799 hxge_intr_mask_mgmt_set(p_hxge_t hxgep, boolean_t on)
800 {
801 p_hxge_ldgv_t ldgvp;
802 p_hxge_ldg_t ldgp;
803 p_hxge_ldv_t ldvp;
804 hpi_handle_t handle;
805 int i, j;
806 hpi_status_t rs = HPI_SUCCESS;
807
808 HXGE_DEBUG_MSG((hxgep, INT_CTL,
809 "==> hxge_intr_mask_mgmt_set (%d)", on));
810
811 if ((ldgvp = hxgep->ldgvp) == NULL) {
812 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
813 "==> hxge_intr_mask_mgmt_set: Null ldgvp"));
814 return (HXGE_ERROR);
815 }
816 handle = HXGE_DEV_HPI_HANDLE(hxgep);
817 ldgp = ldgvp->ldgp;
818 ldvp = ldgvp->ldvp;
819 if (ldgp == NULL || ldvp == NULL) {
820 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
821 "<== hxge_intr_mask_mgmt_set: Null ldgp or ldvp"));
822 return (HXGE_ERROR);
823 }
824
825 /* set masks. */
826 for (i = 0; i < ldgvp->ldg_intrs; i++, ldgp++) {
827 HXGE_DEBUG_MSG((hxgep, INT_CTL,
828 "==> hxge_intr_mask_mgmt_set: flag %d ldg %d"
829 "set mask nldvs %d", on, ldgp->ldg, ldgp->nldvs));
830 for (j = 0; j < ldgp->nldvs; j++, ldvp++) {
831 HXGE_DEBUG_MSG((hxgep, INT_CTL,
832 "==> hxge_intr_mask_mgmt_set: "
833 "for %d %d flag %d", i, j, on));
834 if (on) {
835 ldvp->ldv_ldf_masks = 0;
836 HXGE_DEBUG_MSG((hxgep, INT_CTL,
837 "==> hxge_intr_mask_mgmt_set: "
838 "ON mask off"));
839 } else {
840 ldvp->ldv_ldf_masks = (uint8_t)LD_IM_MASK;
841 HXGE_DEBUG_MSG((hxgep, INT_CTL,
842 "==> hxge_intr_mask_mgmt_set:mask on"));
843 }
844
845 rs = hpi_intr_mask_set(handle, ldvp->ldv,
846 ldvp->ldv_ldf_masks);
847 if (rs != HPI_SUCCESS) {
848 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
849 "==> hxge_intr_mask_mgmt_set: "
850 "set mask failed rs 0x%x ldv %d mask 0x%x",
851 rs, ldvp->ldv, ldvp->ldv_ldf_masks));
852 return (HXGE_ERROR | rs);
853 }
854 HXGE_DEBUG_MSG((hxgep, INT_CTL,
855 "==> hxge_intr_mask_mgmt_set: flag %d"
856 "set mask OK ldv %d mask 0x%x",
857 on, ldvp->ldv, ldvp->ldv_ldf_masks));
858 }
859 }
860
861 ldgp = ldgvp->ldgp;
862 /* set the arm bit */
863 for (i = 0; i < hxgep->ldgvp->ldg_intrs; i++, ldgp++) {
864 if (on && !ldgp->arm) {
865 ldgp->arm = B_TRUE;
866 } else if (!on && ldgp->arm) {
867 ldgp->arm = B_FALSE;
868 }
869 rs = hpi_intr_ldg_mgmt_set(handle, ldgp->ldg,
870 ldgp->arm, ldgp->ldg_timer);
871 if (rs != HPI_SUCCESS) {
872 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
873 "<== hxge_intr_mask_mgmt_set: "
874 "set timer failed rs 0x%x ldg %d timer 0x%x",
875 rs, ldgp->ldg, ldgp->ldg_timer));
876 return (HXGE_ERROR | rs);
877 }
878 HXGE_DEBUG_MSG((hxgep, INT_CTL,
879 "==> hxge_intr_mask_mgmt_set: OK (flag %d) "
880 "set timer ldg %d timer 0x%x",
881 on, ldgp->ldg, ldgp->ldg_timer));
882 }
883
884 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intr_mask_mgmt_set"));
885 return (HXGE_OK);
886 }
887
888 /*
889 * For Big Endian systems, the mac address will be from OBP. For Little
890 * Endian (x64) systems, it will be retrieved from the card since it cannot
891 * be programmed into PXE.
892 * This function also populates the MMAC parameters.
893 */
894 static hxge_status_t
hxge_get_mac_addr_properties(p_hxge_t hxgep)895 hxge_get_mac_addr_properties(p_hxge_t hxgep)
896 {
897 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_get_mac_addr_properties "));
898
899 (void) hxge_pfc_mac_addrs_get(hxgep);
900 hxgep->ouraddr = hxgep->factaddr;
901
902 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_get_mac_addr_properties "));
903 return (HXGE_OK);
904 }
905
906 static void
hxge_ldgv_setup(p_hxge_ldg_t * ldgp,p_hxge_ldv_t * ldvp,uint8_t ldv,uint8_t endldg,int * ngrps)907 hxge_ldgv_setup(p_hxge_ldg_t *ldgp, p_hxge_ldv_t *ldvp, uint8_t ldv,
908 uint8_t endldg, int *ngrps)
909 {
910 HXGE_DEBUG_MSG((NULL, INT_CTL, "==> hxge_ldgv_setup"));
911 /* Assign the group number for each device. */
912 (*ldvp)->ldg_assigned = (*ldgp)->ldg;
913 (*ldvp)->ldgp = *ldgp;
914 (*ldvp)->ldv = ldv;
915
916 HXGE_DEBUG_MSG((NULL, INT_CTL,
917 "==> hxge_ldgv_setup: ldv %d endldg %d ldg %d, ldvp $%p",
918 ldv, endldg, (*ldgp)->ldg, (*ldgp)->ldvp));
919
920 (*ldgp)->nldvs++;
921 if ((*ldgp)->ldg == (endldg - 1)) {
922 if ((*ldgp)->ldvp == NULL) {
923 (*ldgp)->ldvp = *ldvp;
924 *ngrps += 1;
925 HXGE_DEBUG_MSG((NULL, INT_CTL,
926 "==> hxge_ldgv_setup: ngrps %d", *ngrps));
927 }
928 HXGE_DEBUG_MSG((NULL, INT_CTL,
929 "==> hxge_ldgv_setup: ldvp $%p ngrps %d",
930 *ldvp, *ngrps));
931 ++*ldvp;
932 } else {
933 (*ldgp)->ldvp = *ldvp;
934 *ngrps += 1;
935 HXGE_DEBUG_MSG((NULL, INT_CTL, "==> hxge_ldgv_setup(done): "
936 "ldv %d endldg %d ldg %d, ldvp $%p",
937 ldv, endldg, (*ldgp)->ldg, (*ldgp)->ldvp));
938 ++*ldvp;
939 ++*ldgp;
940 HXGE_DEBUG_MSG((NULL, INT_CTL,
941 "==> hxge_ldgv_setup: new ngrps %d", *ngrps));
942 }
943
944 HXGE_DEBUG_MSG((NULL, INT_CTL, "==> hxge_ldgv_setup: "
945 "ldg %d nldvs %d ldv %d ldvp $%p endldg %d ngrps %d",
946 (*ldgp)->ldg, (*ldgp)->nldvs, ldv, ldvp, endldg, *ngrps));
947
948 HXGE_DEBUG_MSG((NULL, INT_CTL, "<== hxge_ldgv_setup"));
949 }
950