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