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 static hxge_status_t hxge_mmac_init(p_hxge_t); 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(); 48 extern uint_t hxge_tx_intr(); 49 extern uint_t hxge_vmac_intr(); 50 extern uint_t hxge_syserr_intr(); 51 extern uint_t hxge_pfc_intr(); 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 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 HXGE_REG_WR32(hxgep->hpi_handle, PEU_INTR_MASK, 0x0); 649 650 /* 651 * Unmask the system interrupt states. 652 */ 653 (void) hxge_fzc_sys_err_mask_set(hxgep, B_FALSE); 654 (void) hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p); 655 nldvs++; 656 657 ldgvp->ldg_intrs = *nrequired_p; 658 659 HXGE_DEBUG_MSG((hxgep, INT_CTL, 660 "==> hxge_ldgv_init: nldvs %d navail %d nrequired %d", 661 nldvs, *navail_p, *nrequired_p)); 662 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_ldgv_init")); 663 return (status); 664 } 665 666 hxge_status_t 667 hxge_ldgv_uninit(p_hxge_t hxgep) 668 { 669 p_hxge_ldgv_t ldgvp; 670 671 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_ldgv_uninit")); 672 ldgvp = hxgep->ldgvp; 673 if (ldgvp == NULL) { 674 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 675 "<== hxge_ldgv_uninit: no logical group configured.")); 676 return (HXGE_OK); 677 } 678 679 if (ldgvp->ldgp) { 680 KMEM_FREE(ldgvp->ldgp, sizeof (hxge_ldg_t) * ldgvp->maxldgs); 681 } 682 if (ldgvp->ldvp) { 683 KMEM_FREE(ldgvp->ldvp, sizeof (hxge_ldv_t) * ldgvp->maxldvs); 684 } 685 686 KMEM_FREE(ldgvp, sizeof (hxge_ldgv_t)); 687 hxgep->ldgvp = NULL; 688 689 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_ldgv_uninit")); 690 return (HXGE_OK); 691 } 692 693 hxge_status_t 694 hxge_intr_ldgv_init(p_hxge_t hxgep) 695 { 696 hxge_status_t status = HXGE_OK; 697 698 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intr_ldgv_init")); 699 /* 700 * Configure the logical device group numbers, state vectors 701 * and interrupt masks for each logical device. 702 */ 703 status = hxge_fzc_intr_init(hxgep); 704 705 /* 706 * Configure logical device masks and timers. 707 */ 708 status = hxge_intr_mask_mgmt(hxgep); 709 710 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intr_ldgv_init")); 711 return (status); 712 } 713 714 hxge_status_t 715 hxge_intr_mask_mgmt(p_hxge_t hxgep) 716 { 717 p_hxge_ldgv_t ldgvp; 718 p_hxge_ldg_t ldgp; 719 p_hxge_ldv_t ldvp; 720 hpi_handle_t handle; 721 int i, j; 722 hpi_status_t rs = HPI_SUCCESS; 723 724 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intr_mask_mgmt")); 725 726 if ((ldgvp = hxgep->ldgvp) == NULL) { 727 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 728 "<== hxge_intr_mask_mgmt: Null ldgvp")); 729 return (HXGE_ERROR); 730 } 731 handle = HXGE_DEV_HPI_HANDLE(hxgep); 732 ldgp = ldgvp->ldgp; 733 ldvp = ldgvp->ldvp; 734 if (ldgp == NULL || ldvp == NULL) { 735 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 736 "<== hxge_intr_mask_mgmt: Null ldgp or ldvp")); 737 return (HXGE_ERROR); 738 } 739 740 HXGE_DEBUG_MSG((hxgep, INT_CTL, 741 "==> hxge_intr_mask_mgmt: # of intrs %d ", ldgvp->ldg_intrs)); 742 /* Initialize masks. */ 743 HXGE_DEBUG_MSG((hxgep, INT_CTL, 744 "==> hxge_intr_mask_mgmt(Hydra): # intrs %d ", ldgvp->ldg_intrs)); 745 for (i = 0; i < ldgvp->ldg_intrs; i++, ldgp++) { 746 HXGE_DEBUG_MSG((hxgep, INT_CTL, 747 "==> hxge_intr_mask_mgmt(Hydra): # ldv %d in group %d", 748 ldgp->nldvs, ldgp->ldg)); 749 for (j = 0; j < ldgp->nldvs; j++, ldvp++) { 750 HXGE_DEBUG_MSG((hxgep, INT_CTL, 751 "==> hxge_intr_mask_mgmt: set ldv # %d " 752 "for ldg %d", ldvp->ldv, ldgp->ldg)); 753 rs = hpi_intr_mask_set(handle, ldvp->ldv, 754 ldvp->ldv_ldf_masks); 755 if (rs != HPI_SUCCESS) { 756 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 757 "<== hxge_intr_mask_mgmt: set mask failed " 758 " rs 0x%x ldv %d mask 0x%x", 759 rs, ldvp->ldv, ldvp->ldv_ldf_masks)); 760 return (HXGE_ERROR | rs); 761 } 762 HXGE_DEBUG_MSG((hxgep, INT_CTL, 763 "==> hxge_intr_mask_mgmt: set mask OK " 764 " rs 0x%x ldv %d mask 0x%x", 765 rs, ldvp->ldv, ldvp->ldv_ldf_masks)); 766 } 767 } 768 769 ldgp = ldgvp->ldgp; 770 /* Configure timer and arm bit */ 771 for (i = 0; i < hxgep->ldgvp->ldg_intrs; i++, ldgp++) { 772 rs = hpi_intr_ldg_mgmt_set(handle, ldgp->ldg, 773 ldgp->arm, ldgp->ldg_timer); 774 if (rs != HPI_SUCCESS) { 775 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 776 "<== hxge_intr_mask_mgmt: set timer failed " 777 " rs 0x%x dg %d timer 0x%x", 778 rs, ldgp->ldg, ldgp->ldg_timer)); 779 return (HXGE_ERROR | rs); 780 } 781 HXGE_DEBUG_MSG((hxgep, INT_CTL, 782 "==> hxge_intr_mask_mgmt: set timer OK " 783 " rs 0x%x ldg %d timer 0x%x", 784 rs, ldgp->ldg, ldgp->ldg_timer)); 785 } 786 787 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_fzc_intr_mask_mgmt")); 788 return (HXGE_OK); 789 } 790 791 hxge_status_t 792 hxge_intr_mask_mgmt_set(p_hxge_t hxgep, boolean_t on) 793 { 794 p_hxge_ldgv_t ldgvp; 795 p_hxge_ldg_t ldgp; 796 p_hxge_ldv_t ldvp; 797 hpi_handle_t handle; 798 int i, j; 799 hpi_status_t rs = HPI_SUCCESS; 800 801 HXGE_DEBUG_MSG((hxgep, INT_CTL, 802 "==> hxge_intr_mask_mgmt_set (%d)", on)); 803 804 if ((ldgvp = hxgep->ldgvp) == NULL) { 805 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 806 "==> hxge_intr_mask_mgmt_set: Null ldgvp")); 807 return (HXGE_ERROR); 808 } 809 handle = HXGE_DEV_HPI_HANDLE(hxgep); 810 ldgp = ldgvp->ldgp; 811 ldvp = ldgvp->ldvp; 812 if (ldgp == NULL || ldvp == NULL) { 813 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 814 "<== hxge_intr_mask_mgmt_set: Null ldgp or ldvp")); 815 return (HXGE_ERROR); 816 } 817 818 /* set masks. */ 819 for (i = 0; i < ldgvp->ldg_intrs; i++, ldgp++) { 820 HXGE_DEBUG_MSG((hxgep, INT_CTL, 821 "==> hxge_intr_mask_mgmt_set: flag %d ldg %d" 822 "set mask nldvs %d", on, ldgp->ldg, ldgp->nldvs)); 823 for (j = 0; j < ldgp->nldvs; j++, ldvp++) { 824 HXGE_DEBUG_MSG((hxgep, INT_CTL, 825 "==> hxge_intr_mask_mgmt_set: " 826 "for %d %d flag %d", i, j, on)); 827 if (on) { 828 ldvp->ldv_ldf_masks = 0; 829 HXGE_DEBUG_MSG((hxgep, INT_CTL, 830 "==> hxge_intr_mask_mgmt_set: " 831 "ON mask off")); 832 } else { 833 ldvp->ldv_ldf_masks = (uint8_t)LD_IM_MASK; 834 HXGE_DEBUG_MSG((hxgep, INT_CTL, 835 "==> hxge_intr_mask_mgmt_set:mask on")); 836 } 837 838 rs = hpi_intr_mask_set(handle, ldvp->ldv, 839 ldvp->ldv_ldf_masks); 840 if (rs != HPI_SUCCESS) { 841 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 842 "==> hxge_intr_mask_mgmt_set: " 843 "set mask failed rs 0x%x ldv %d mask 0x%x", 844 rs, ldvp->ldv, ldvp->ldv_ldf_masks)); 845 return (HXGE_ERROR | rs); 846 } 847 HXGE_DEBUG_MSG((hxgep, INT_CTL, 848 "==> hxge_intr_mask_mgmt_set: flag %d" 849 "set mask OK ldv %d mask 0x%x", 850 on, ldvp->ldv, ldvp->ldv_ldf_masks)); 851 } 852 } 853 854 ldgp = ldgvp->ldgp; 855 /* set the arm bit */ 856 for (i = 0; i < hxgep->ldgvp->ldg_intrs; i++, ldgp++) { 857 if (on && !ldgp->arm) { 858 ldgp->arm = B_TRUE; 859 } else if (!on && ldgp->arm) { 860 ldgp->arm = B_FALSE; 861 } 862 rs = hpi_intr_ldg_mgmt_set(handle, ldgp->ldg, 863 ldgp->arm, ldgp->ldg_timer); 864 if (rs != HPI_SUCCESS) { 865 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 866 "<== hxge_intr_mask_mgmt_set: " 867 "set timer failed rs 0x%x ldg %d timer 0x%x", 868 rs, ldgp->ldg, ldgp->ldg_timer)); 869 return (HXGE_ERROR | rs); 870 } 871 HXGE_DEBUG_MSG((hxgep, INT_CTL, 872 "==> hxge_intr_mask_mgmt_set: OK (flag %d) " 873 "set timer ldg %d timer 0x%x", 874 on, ldgp->ldg, ldgp->ldg_timer)); 875 } 876 877 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intr_mask_mgmt_set")); 878 return (HXGE_OK); 879 } 880 881 /* 882 * For Big Endian systems, the mac address will be from OBP. For Little 883 * Endian (x64) systems, it will be retrieved from the card since it cannot 884 * be programmed into PXE. 885 * This function also populates the MMAC parameters. 886 */ 887 static hxge_status_t 888 hxge_get_mac_addr_properties(p_hxge_t hxgep) 889 { 890 uint32_t num_macs; 891 hxge_status_t status; 892 893 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_get_mac_addr_properties ")); 894 895 (void) hxge_pfc_mac_addrs_get(hxgep); 896 hxgep->ouraddr = hxgep->factaddr; 897 898 /* 899 * Get the number of MAC addresses the Hydra supports per blade. 900 */ 901 if (hxge_pfc_num_macs_get(hxgep, &num_macs) == HXGE_OK) { 902 hxgep->hxge_mmac_info.num_mmac = (uint8_t)num_macs; 903 } else { 904 HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, 905 "hxge_get_mac_addr_properties: get macs failed")); 906 return (HXGE_ERROR); 907 } 908 909 /* 910 * Initialize alt. mac addr. in the mac pool 911 */ 912 status = hxge_mmac_init(hxgep); 913 if (status != HXGE_OK) { 914 HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, 915 "hxge_get_mac_addr_properties: init mmac failed")); 916 return (HXGE_ERROR); 917 } 918 919 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_get_mac_addr_properties ")); 920 return (HXGE_OK); 921 } 922 923 static void 924 hxge_ldgv_setup(p_hxge_ldg_t *ldgp, p_hxge_ldv_t *ldvp, uint8_t ldv, 925 uint8_t endldg, int *ngrps) 926 { 927 HXGE_DEBUG_MSG((NULL, INT_CTL, "==> hxge_ldgv_setup")); 928 /* Assign the group number for each device. */ 929 (*ldvp)->ldg_assigned = (*ldgp)->ldg; 930 (*ldvp)->ldgp = *ldgp; 931 (*ldvp)->ldv = ldv; 932 933 HXGE_DEBUG_MSG((NULL, INT_CTL, 934 "==> hxge_ldgv_setup: ldv %d endldg %d ldg %d, ldvp $%p", 935 ldv, endldg, (*ldgp)->ldg, (*ldgp)->ldvp)); 936 937 (*ldgp)->nldvs++; 938 if ((*ldgp)->ldg == (endldg - 1)) { 939 if ((*ldgp)->ldvp == NULL) { 940 (*ldgp)->ldvp = *ldvp; 941 *ngrps += 1; 942 HXGE_DEBUG_MSG((NULL, INT_CTL, 943 "==> hxge_ldgv_setup: ngrps %d", *ngrps)); 944 } 945 HXGE_DEBUG_MSG((NULL, INT_CTL, 946 "==> hxge_ldgv_setup: ldvp $%p ngrps %d", 947 *ldvp, *ngrps)); 948 ++*ldvp; 949 } else { 950 (*ldgp)->ldvp = *ldvp; 951 *ngrps += 1; 952 HXGE_DEBUG_MSG((NULL, INT_CTL, "==> hxge_ldgv_setup(done): " 953 "ldv %d endldg %d ldg %d, ldvp $%p", 954 ldv, endldg, (*ldgp)->ldg, (*ldgp)->ldvp)); 955 (*ldvp) = ++*ldvp; 956 (*ldgp) = ++*ldgp; 957 HXGE_DEBUG_MSG((NULL, INT_CTL, 958 "==> hxge_ldgv_setup: new ngrps %d", *ngrps)); 959 } 960 961 HXGE_DEBUG_MSG((NULL, INT_CTL, "==> hxge_ldgv_setup: " 962 "ldg %d nldvs %d ldv %d ldvp $%p endldg %d ngrps %d", 963 (*ldgp)->ldg, (*ldgp)->nldvs, ldv, ldvp, endldg, *ngrps)); 964 965 HXGE_DEBUG_MSG((NULL, INT_CTL, "<== hxge_ldgv_setup")); 966 } 967 968 /* 969 * Note: This function assumes the following distribution of mac 970 * addresses for a hydra blade: 971 * 972 * ------------- 973 * 0| |0 - local-mac-address for blade 974 * ------------- 975 * | |1 - Start of alt. mac addr. for blade 976 * | | 977 * | | 978 * | |15 979 * -------------- 980 */ 981 982 static hxge_status_t 983 hxge_mmac_init(p_hxge_t hxgep) 984 { 985 int slot; 986 hxge_mmac_t *mmac_info; 987 988 mmac_info = (hxge_mmac_t *)&hxgep->hxge_mmac_info; 989 990 /* Set flags for unique MAC */ 991 mmac_info->mac_pool[0].flags |= MMAC_SLOT_USED | MMAC_VENDOR_ADDR; 992 mmac_info->num_factory_mmac = 1; 993 994 /* 995 * Skip the factory/default address which is in slot 0. 996 * Initialze all other mac addr. to "AVAILABLE" state. 997 * Clear flags of all alternate MAC slots. 998 */ 999 for (slot = 1; slot < mmac_info->num_mmac; slot++) { 1000 (void) hpi_pfc_clear_mac_address(hxgep->hpi_handle, slot); 1001 mmac_info->mac_pool[slot].flags = 0; 1002 } 1003 1004 /* Exclude the factory mac address */ 1005 mmac_info->naddrfree = mmac_info->num_mmac - 1; 1006 1007 /* Initialize the first two parameters for mmac kstat */ 1008 hxgep->statsp->mmac_stats.mmac_max_cnt = mmac_info->num_mmac; 1009 hxgep->statsp->mmac_stats.mmac_avail_cnt = mmac_info->naddrfree; 1010 1011 return (HXGE_OK); 1012 } 1013