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 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 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 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 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 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 306 hxge_use_cfg_class_config(p_hxge_t hxgep) 307 { 308 hxge_set_hw_class_config(hxgep); 309 } 310 311 static void 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 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 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 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 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 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 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 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 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 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 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) = ++*ldvp; 939 (*ldgp) = ++*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