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 p_dma_cfgp->rcr_size = hxge_rcr_size; 330 331 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_set_hw_dma_config")); 332 } 333 334 335 boolean_t 336 hxge_check_rxdma_port_member(p_hxge_t hxgep, uint8_t rdc) 337 { 338 p_hxge_dma_pt_cfg_t p_dma_cfgp; 339 p_hxge_hw_pt_cfg_t p_cfgp; 340 int status = B_TRUE; 341 342 HXGE_DEBUG_MSG((hxgep, CFG2_CTL, "==> hxge_check_rxdma_port_member")); 343 344 p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 345 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 346 347 /* Receive DMA Channels */ 348 if (rdc < p_cfgp->max_rdcs) 349 status = B_TRUE; 350 HXGE_DEBUG_MSG((hxgep, CFG2_CTL, " <== hxge_check_rxdma_port_member")); 351 352 return (status); 353 } 354 355 boolean_t 356 hxge_check_txdma_port_member(p_hxge_t hxgep, uint8_t tdc) 357 { 358 p_hxge_dma_pt_cfg_t p_dma_cfgp; 359 p_hxge_hw_pt_cfg_t p_cfgp; 360 int status = B_FALSE; 361 362 HXGE_DEBUG_MSG((hxgep, CFG2_CTL, "==> hxge_check_txdma_port_member")); 363 364 p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 365 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 366 367 /* Receive DMA Channels */ 368 if (tdc < p_cfgp->max_tdcs) 369 status = B_TRUE; 370 HXGE_DEBUG_MSG((hxgep, CFG2_CTL, " <== hxge_check_txdma_port_member")); 371 372 return (status); 373 } 374 375 376 /* 377 * Read the L2 classes, L3 classes, and initial hash from either hxge.conf 378 * or OBP. Populate these properties into the hxge data structure for latter 379 * use. Note that we are not updating these soft properties. 380 */ 381 static void 382 hxge_set_hw_class_config(p_hxge_t hxgep) 383 { 384 int i, j; 385 p_hxge_param_t param_arr; 386 int *int_prop_val; 387 uint32_t cfg_value; 388 char *prop; 389 p_hxge_class_pt_cfg_t p_class_cfgp; 390 int start_prop, end_prop; 391 uint_t prop_cnt; 392 393 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_set_hw_class_config")); 394 395 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config; 396 397 param_arr = hxgep->param_arr; 398 399 /* 400 * L2 class configuration. User configurable ether types 401 */ 402 start_prop = param_class_cfg_ether_usr1; 403 end_prop = param_class_cfg_ether_usr2; 404 405 for (i = start_prop; i <= end_prop; i++) { 406 prop = param_arr[i].fcode_name; 407 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 408 0, prop, &int_prop_val, &prop_cnt) == DDI_PROP_SUCCESS) { 409 cfg_value = (uint32_t)*int_prop_val; 410 ddi_prop_free(int_prop_val); 411 } else { 412 cfg_value = (uint32_t)param_arr[i].value; 413 } 414 415 j = (i - start_prop) + TCAM_CLASS_ETYPE_1; 416 p_class_cfgp->class_cfg[j] = cfg_value; 417 } 418 419 /* 420 * Use properties from either .conf or the NDD param array. Only bits 421 * 2 and 3 are significant 422 */ 423 start_prop = param_class_opt_ipv4_tcp; 424 end_prop = param_class_opt_ipv6_sctp; 425 426 for (i = start_prop; i <= end_prop; i++) { 427 prop = param_arr[i].fcode_name; 428 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 429 0, prop, &int_prop_val, &prop_cnt) == DDI_PROP_SUCCESS) { 430 cfg_value = (uint32_t)*int_prop_val; 431 ddi_prop_free(int_prop_val); 432 } else { 433 cfg_value = (uint32_t)param_arr[i].value; 434 } 435 436 j = (i - start_prop) + TCAM_CLASS_TCP_IPV4; 437 p_class_cfgp->class_cfg[j] = cfg_value; 438 } 439 440 prop = param_arr[param_hash_init_value].fcode_name; 441 442 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0, prop, 443 &int_prop_val, &prop_cnt) == DDI_PROP_SUCCESS) { 444 cfg_value = (uint32_t)*int_prop_val; 445 ddi_prop_free(int_prop_val); 446 } else { 447 cfg_value = (uint32_t)param_arr[param_hash_init_value].value; 448 } 449 450 p_class_cfgp->init_hash = (uint32_t)cfg_value; 451 452 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_set_hw_class_config")); 453 } 454 455 456 /* 457 * Interrupts related interface functions. 458 */ 459 hxge_status_t 460 hxge_ldgv_init(p_hxge_t hxgep, int *navail_p, int *nrequired_p) 461 { 462 uint8_t ldv, i, maxldvs, maxldgs, start, end, nldvs; 463 int ldg, endldg, ngrps; 464 uint8_t channel; 465 p_hxge_dma_pt_cfg_t p_dma_cfgp; 466 p_hxge_hw_pt_cfg_t p_cfgp; 467 p_hxge_ldgv_t ldgvp; 468 p_hxge_ldg_t ldgp, ptr; 469 p_hxge_ldv_t ldvp; 470 hxge_status_t status = HXGE_OK; 471 472 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_ldgv_init")); 473 if (!*navail_p) { 474 *nrequired_p = 0; 475 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 476 "<== hxge_ldgv_init:no avail")); 477 return (HXGE_ERROR); 478 } 479 p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 480 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 481 482 /* each DMA channels */ 483 nldvs = p_cfgp->max_tdcs + p_cfgp->max_rdcs; 484 485 /* vmac */ 486 nldvs++; 487 488 /* pfc */ 489 nldvs++; 490 491 /* system error interrupts. */ 492 nldvs++; 493 494 maxldvs = nldvs; 495 maxldgs = p_cfgp->max_ldgs; 496 497 if (!maxldvs || !maxldgs) { 498 /* No devices configured. */ 499 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_ldgv_init: " 500 "no logical devices or groups configured.")); 501 return (HXGE_ERROR); 502 } 503 ldgvp = hxgep->ldgvp; 504 if (ldgvp == NULL) { 505 ldgvp = KMEM_ZALLOC(sizeof (hxge_ldgv_t), KM_SLEEP); 506 hxgep->ldgvp = ldgvp; 507 ldgvp->maxldgs = maxldgs; 508 ldgvp->maxldvs = maxldvs; 509 ldgp = ldgvp->ldgp = 510 KMEM_ZALLOC(sizeof (hxge_ldg_t) * maxldgs, KM_SLEEP); 511 ldvp = ldgvp->ldvp = 512 KMEM_ZALLOC(sizeof (hxge_ldv_t) * maxldvs, KM_SLEEP); 513 } 514 515 ldgvp->ndma_ldvs = p_cfgp->max_tdcs + p_cfgp->max_rdcs; 516 ldgvp->tmres = HXGE_TIMER_RESO; 517 518 HXGE_DEBUG_MSG((hxgep, INT_CTL, 519 "==> hxge_ldgv_init: maxldvs %d maxldgs %d nldvs %d", 520 maxldvs, maxldgs, nldvs)); 521 522 ldg = p_cfgp->start_ldg; 523 ptr = ldgp; 524 for (i = 0; i < maxldgs; i++) { 525 ptr->arm = B_TRUE; 526 ptr->vldg_index = i; 527 ptr->ldg_timer = HXGE_TIMER_LDG; 528 ptr->ldg = ldg++; 529 ptr->sys_intr_handler = hxge_intr; 530 ptr->nldvs = 0; 531 ptr->hxgep = hxgep; 532 HXGE_DEBUG_MSG((hxgep, INT_CTL, 533 "==> hxge_ldgv_init: maxldvs %d maxldgs %d ldg %d", 534 maxldvs, maxldgs, ptr->ldg)); 535 HXGE_DEBUG_MSG((hxgep, INT_CTL, 536 "==> hxge_ldv_init: timer %d", ptr->ldg_timer)); 537 ptr++; 538 } 539 540 ldg = p_cfgp->start_ldg; 541 if (maxldgs > *navail_p) { 542 ngrps = *navail_p; 543 } else { 544 ngrps = maxldgs; 545 } 546 endldg = ldg + ngrps; 547 548 /* 549 * Receive DMA channels. 550 */ 551 channel = p_cfgp->start_rdc; 552 start = p_cfgp->start_rdc + HXGE_RDMA_LD_START; 553 end = start + p_cfgp->max_rdcs; 554 nldvs = 0; 555 ldgvp->nldvs = 0; 556 ldgp->ldvp = NULL; 557 *nrequired_p = 0; 558 ptr = ldgp; 559 560 /* 561 * Start with RDC to configure logical devices for each group. 562 */ 563 for (i = 0, ldv = start; ldv < end; i++, ldv++) { 564 ldvp->is_rxdma = B_TRUE; 565 ldvp->ldv = ldv; 566 567 /* 568 * If non-seq needs to change the following code 569 */ 570 ldvp->channel = channel++; 571 ldvp->vdma_index = i; 572 ldvp->ldv_intr_handler = hxge_rx_intr; 573 ldvp->ldv_ldf_masks = 0; 574 ldvp->use_timer = B_FALSE; 575 ldvp->hxgep = hxgep; 576 hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p); 577 nldvs++; 578 } 579 580 /* 581 * Transmit DMA channels. 582 */ 583 channel = p_cfgp->start_tdc; 584 start = p_cfgp->start_tdc + HXGE_TDMA_LD_START; 585 end = start + p_cfgp->max_tdcs; 586 for (i = 0, ldv = start; ldv < end; i++, ldv++) { 587 ldvp->is_txdma = B_TRUE; 588 ldvp->ldv = ldv; 589 ldvp->channel = channel++; 590 ldvp->vdma_index = i; 591 ldvp->ldv_intr_handler = hxge_tx_intr; 592 ldvp->ldv_ldf_masks = 0; 593 ldvp->use_timer = B_FALSE; 594 ldvp->hxgep = hxgep; 595 hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p); 596 nldvs++; 597 } 598 599 /* 600 * VMAC 601 */ 602 ldvp->is_vmac = B_TRUE; 603 ldvp->ldv_intr_handler = hxge_vmac_intr; 604 ldvp->ldv_ldf_masks = 0; 605 ldv = HXGE_VMAC_LD; 606 ldvp->ldv = ldv; 607 ldvp->use_timer = B_FALSE; 608 ldvp->hxgep = hxgep; 609 hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p); 610 nldvs++; 611 612 HXGE_DEBUG_MSG((hxgep, INT_CTL, 613 "==> hxge_ldgv_init: nldvs %d navail %d nrequired %d", 614 nldvs, *navail_p, *nrequired_p)); 615 616 /* 617 * PFC 618 */ 619 ldvp->is_pfc = B_TRUE; 620 ldvp->ldv_intr_handler = hxge_pfc_intr; 621 ldvp->ldv_ldf_masks = 0; 622 ldv = HXGE_PFC_LD; 623 ldvp->ldv = ldv; 624 ldvp->use_timer = B_FALSE; 625 ldvp->hxgep = hxgep; 626 hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p); 627 nldvs++; 628 629 HXGE_DEBUG_MSG((hxgep, INT_CTL, 630 "==> hxge_ldgv_init: nldvs %d navail %d nrequired %d", 631 nldvs, *navail_p, *nrequired_p)); 632 633 /* 634 * System error interrupts. 635 */ 636 ldv = HXGE_SYS_ERROR_LD; 637 ldvp->ldv = ldv; 638 ldvp->is_syserr = B_TRUE; 639 ldvp->ldv_intr_handler = hxge_syserr_intr; 640 ldvp->ldv_ldf_masks = 0; 641 ldvp->hxgep = hxgep; 642 ldvp->use_timer = B_FALSE; 643 ldgvp->ldvp_syserr = ldvp; 644 645 /* Reset PEU error mask to allow PEU error interrupts */ 646 HXGE_REG_WR32(hxgep->hpi_handle, PEU_INTR_MASK, 0x0); 647 648 /* 649 * Unmask the system interrupt states. 650 */ 651 (void) hxge_fzc_sys_err_mask_set(hxgep, B_FALSE); 652 (void) hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p); 653 nldvs++; 654 655 ldgvp->ldg_intrs = *nrequired_p; 656 657 HXGE_DEBUG_MSG((hxgep, INT_CTL, 658 "==> hxge_ldgv_init: nldvs %d navail %d nrequired %d", 659 nldvs, *navail_p, *nrequired_p)); 660 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_ldgv_init")); 661 return (status); 662 } 663 664 hxge_status_t 665 hxge_ldgv_uninit(p_hxge_t hxgep) 666 { 667 p_hxge_ldgv_t ldgvp; 668 669 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_ldgv_uninit")); 670 ldgvp = hxgep->ldgvp; 671 if (ldgvp == NULL) { 672 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 673 "<== hxge_ldgv_uninit: no logical group configured.")); 674 return (HXGE_OK); 675 } 676 677 if (ldgvp->ldgp) { 678 KMEM_FREE(ldgvp->ldgp, sizeof (hxge_ldg_t) * ldgvp->maxldgs); 679 } 680 if (ldgvp->ldvp) { 681 KMEM_FREE(ldgvp->ldvp, sizeof (hxge_ldv_t) * ldgvp->maxldvs); 682 } 683 684 KMEM_FREE(ldgvp, sizeof (hxge_ldgv_t)); 685 hxgep->ldgvp = NULL; 686 687 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_ldgv_uninit")); 688 return (HXGE_OK); 689 } 690 691 hxge_status_t 692 hxge_intr_ldgv_init(p_hxge_t hxgep) 693 { 694 hxge_status_t status = HXGE_OK; 695 696 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intr_ldgv_init")); 697 /* 698 * Configure the logical device group numbers, state vectors 699 * and interrupt masks for each logical device. 700 */ 701 status = hxge_fzc_intr_init(hxgep); 702 703 /* 704 * Configure logical device masks and timers. 705 */ 706 status = hxge_intr_mask_mgmt(hxgep); 707 708 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intr_ldgv_init")); 709 return (status); 710 } 711 712 hxge_status_t 713 hxge_intr_mask_mgmt(p_hxge_t hxgep) 714 { 715 p_hxge_ldgv_t ldgvp; 716 p_hxge_ldg_t ldgp; 717 p_hxge_ldv_t ldvp; 718 hpi_handle_t handle; 719 int i, j; 720 hpi_status_t rs = HPI_SUCCESS; 721 722 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intr_mask_mgmt")); 723 724 if ((ldgvp = hxgep->ldgvp) == NULL) { 725 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 726 "<== hxge_intr_mask_mgmt: Null ldgvp")); 727 return (HXGE_ERROR); 728 } 729 handle = HXGE_DEV_HPI_HANDLE(hxgep); 730 ldgp = ldgvp->ldgp; 731 ldvp = ldgvp->ldvp; 732 if (ldgp == NULL || ldvp == NULL) { 733 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 734 "<== hxge_intr_mask_mgmt: Null ldgp or ldvp")); 735 return (HXGE_ERROR); 736 } 737 738 HXGE_DEBUG_MSG((hxgep, INT_CTL, 739 "==> hxge_intr_mask_mgmt: # of intrs %d ", ldgvp->ldg_intrs)); 740 /* Initialize masks. */ 741 HXGE_DEBUG_MSG((hxgep, INT_CTL, 742 "==> hxge_intr_mask_mgmt(Hydra): # intrs %d ", ldgvp->ldg_intrs)); 743 for (i = 0; i < ldgvp->ldg_intrs; i++, ldgp++) { 744 HXGE_DEBUG_MSG((hxgep, INT_CTL, 745 "==> hxge_intr_mask_mgmt(Hydra): # ldv %d in group %d", 746 ldgp->nldvs, ldgp->ldg)); 747 for (j = 0; j < ldgp->nldvs; j++, ldvp++) { 748 HXGE_DEBUG_MSG((hxgep, INT_CTL, 749 "==> hxge_intr_mask_mgmt: set ldv # %d " 750 "for ldg %d", ldvp->ldv, ldgp->ldg)); 751 rs = hpi_intr_mask_set(handle, ldvp->ldv, 752 ldvp->ldv_ldf_masks); 753 if (rs != HPI_SUCCESS) { 754 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 755 "<== hxge_intr_mask_mgmt: set mask failed " 756 " rs 0x%x ldv %d mask 0x%x", 757 rs, ldvp->ldv, ldvp->ldv_ldf_masks)); 758 return (HXGE_ERROR | rs); 759 } 760 HXGE_DEBUG_MSG((hxgep, INT_CTL, 761 "==> hxge_intr_mask_mgmt: set mask OK " 762 " rs 0x%x ldv %d mask 0x%x", 763 rs, ldvp->ldv, ldvp->ldv_ldf_masks)); 764 } 765 } 766 767 ldgp = ldgvp->ldgp; 768 /* Configure timer and arm bit */ 769 for (i = 0; i < hxgep->ldgvp->ldg_intrs; i++, ldgp++) { 770 rs = hpi_intr_ldg_mgmt_set(handle, ldgp->ldg, 771 ldgp->arm, ldgp->ldg_timer); 772 if (rs != HPI_SUCCESS) { 773 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 774 "<== hxge_intr_mask_mgmt: set timer failed " 775 " rs 0x%x dg %d timer 0x%x", 776 rs, ldgp->ldg, ldgp->ldg_timer)); 777 return (HXGE_ERROR | rs); 778 } 779 HXGE_DEBUG_MSG((hxgep, INT_CTL, 780 "==> hxge_intr_mask_mgmt: set timer OK " 781 " rs 0x%x ldg %d timer 0x%x", 782 rs, ldgp->ldg, ldgp->ldg_timer)); 783 } 784 785 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_fzc_intr_mask_mgmt")); 786 return (HXGE_OK); 787 } 788 789 hxge_status_t 790 hxge_intr_mask_mgmt_set(p_hxge_t hxgep, boolean_t on) 791 { 792 p_hxge_ldgv_t ldgvp; 793 p_hxge_ldg_t ldgp; 794 p_hxge_ldv_t ldvp; 795 hpi_handle_t handle; 796 int i, j; 797 hpi_status_t rs = HPI_SUCCESS; 798 799 HXGE_DEBUG_MSG((hxgep, INT_CTL, 800 "==> hxge_intr_mask_mgmt_set (%d)", on)); 801 802 if ((ldgvp = hxgep->ldgvp) == NULL) { 803 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 804 "==> hxge_intr_mask_mgmt_set: Null ldgvp")); 805 return (HXGE_ERROR); 806 } 807 handle = HXGE_DEV_HPI_HANDLE(hxgep); 808 ldgp = ldgvp->ldgp; 809 ldvp = ldgvp->ldvp; 810 if (ldgp == NULL || ldvp == NULL) { 811 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 812 "<== hxge_intr_mask_mgmt_set: Null ldgp or ldvp")); 813 return (HXGE_ERROR); 814 } 815 816 /* set masks. */ 817 for (i = 0; i < ldgvp->ldg_intrs; i++, ldgp++) { 818 HXGE_DEBUG_MSG((hxgep, INT_CTL, 819 "==> hxge_intr_mask_mgmt_set: flag %d ldg %d" 820 "set mask nldvs %d", on, ldgp->ldg, ldgp->nldvs)); 821 for (j = 0; j < ldgp->nldvs; j++, ldvp++) { 822 HXGE_DEBUG_MSG((hxgep, INT_CTL, 823 "==> hxge_intr_mask_mgmt_set: " 824 "for %d %d flag %d", i, j, on)); 825 if (on) { 826 ldvp->ldv_ldf_masks = 0; 827 HXGE_DEBUG_MSG((hxgep, INT_CTL, 828 "==> hxge_intr_mask_mgmt_set: " 829 "ON mask off")); 830 } else { 831 ldvp->ldv_ldf_masks = (uint8_t)LD_IM_MASK; 832 HXGE_DEBUG_MSG((hxgep, INT_CTL, 833 "==> hxge_intr_mask_mgmt_set:mask on")); 834 } 835 836 rs = hpi_intr_mask_set(handle, ldvp->ldv, 837 ldvp->ldv_ldf_masks); 838 if (rs != HPI_SUCCESS) { 839 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 840 "==> hxge_intr_mask_mgmt_set: " 841 "set mask failed rs 0x%x ldv %d mask 0x%x", 842 rs, ldvp->ldv, ldvp->ldv_ldf_masks)); 843 return (HXGE_ERROR | rs); 844 } 845 HXGE_DEBUG_MSG((hxgep, INT_CTL, 846 "==> hxge_intr_mask_mgmt_set: flag %d" 847 "set mask OK ldv %d mask 0x%x", 848 on, ldvp->ldv, ldvp->ldv_ldf_masks)); 849 } 850 } 851 852 ldgp = ldgvp->ldgp; 853 /* set the arm bit */ 854 for (i = 0; i < hxgep->ldgvp->ldg_intrs; i++, ldgp++) { 855 if (on && !ldgp->arm) { 856 ldgp->arm = B_TRUE; 857 } else if (!on && ldgp->arm) { 858 ldgp->arm = B_FALSE; 859 } 860 rs = hpi_intr_ldg_mgmt_set(handle, ldgp->ldg, 861 ldgp->arm, ldgp->ldg_timer); 862 if (rs != HPI_SUCCESS) { 863 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 864 "<== hxge_intr_mask_mgmt_set: " 865 "set timer failed rs 0x%x ldg %d timer 0x%x", 866 rs, ldgp->ldg, ldgp->ldg_timer)); 867 return (HXGE_ERROR | rs); 868 } 869 HXGE_DEBUG_MSG((hxgep, INT_CTL, 870 "==> hxge_intr_mask_mgmt_set: OK (flag %d) " 871 "set timer ldg %d timer 0x%x", 872 on, ldgp->ldg, ldgp->ldg_timer)); 873 } 874 875 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intr_mask_mgmt_set")); 876 return (HXGE_OK); 877 } 878 879 /* 880 * For Big Endian systems, the mac address will be from OBP. For Little 881 * Endian (x64) systems, it will be retrieved from the card since it cannot 882 * be programmed into PXE. 883 * This function also populates the MMAC parameters. 884 */ 885 static hxge_status_t 886 hxge_get_mac_addr_properties(p_hxge_t hxgep) 887 { 888 uint32_t num_macs; 889 hxge_status_t status; 890 891 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_get_mac_addr_properties ")); 892 893 (void) hxge_pfc_mac_addrs_get(hxgep); 894 hxgep->ouraddr = hxgep->factaddr; 895 896 /* 897 * Get the number of MAC addresses the Hydra supports per blade. 898 */ 899 if (hxge_pfc_num_macs_get(hxgep, &num_macs) == HXGE_OK) { 900 hxgep->hxge_mmac_info.num_mmac = (uint8_t)num_macs; 901 } else { 902 HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, 903 "hxge_get_mac_addr_properties: get macs failed")); 904 return (HXGE_ERROR); 905 } 906 907 /* 908 * Initialize alt. mac addr. in the mac pool 909 */ 910 status = hxge_mmac_init(hxgep); 911 if (status != HXGE_OK) { 912 HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, 913 "hxge_get_mac_addr_properties: init mmac failed")); 914 return (HXGE_ERROR); 915 } 916 917 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_get_mac_addr_properties ")); 918 return (HXGE_OK); 919 } 920 921 static void 922 hxge_ldgv_setup(p_hxge_ldg_t *ldgp, p_hxge_ldv_t *ldvp, uint8_t ldv, 923 uint8_t endldg, int *ngrps) 924 { 925 HXGE_DEBUG_MSG((NULL, INT_CTL, "==> hxge_ldgv_setup")); 926 /* Assign the group number for each device. */ 927 (*ldvp)->ldg_assigned = (*ldgp)->ldg; 928 (*ldvp)->ldgp = *ldgp; 929 (*ldvp)->ldv = ldv; 930 931 HXGE_DEBUG_MSG((NULL, INT_CTL, 932 "==> hxge_ldgv_setup: ldv %d endldg %d ldg %d, ldvp $%p", 933 ldv, endldg, (*ldgp)->ldg, (*ldgp)->ldvp)); 934 935 (*ldgp)->nldvs++; 936 if ((*ldgp)->ldg == (endldg - 1)) { 937 if ((*ldgp)->ldvp == NULL) { 938 (*ldgp)->ldvp = *ldvp; 939 *ngrps += 1; 940 HXGE_DEBUG_MSG((NULL, INT_CTL, 941 "==> hxge_ldgv_setup: ngrps %d", *ngrps)); 942 } 943 HXGE_DEBUG_MSG((NULL, INT_CTL, 944 "==> hxge_ldgv_setup: ldvp $%p ngrps %d", 945 *ldvp, *ngrps)); 946 ++*ldvp; 947 } else { 948 (*ldgp)->ldvp = *ldvp; 949 *ngrps += 1; 950 HXGE_DEBUG_MSG((NULL, INT_CTL, "==> hxge_ldgv_setup(done): " 951 "ldv %d endldg %d ldg %d, ldvp $%p", 952 ldv, endldg, (*ldgp)->ldg, (*ldgp)->ldvp)); 953 (*ldvp) = ++*ldvp; 954 (*ldgp) = ++*ldgp; 955 HXGE_DEBUG_MSG((NULL, INT_CTL, 956 "==> hxge_ldgv_setup: new ngrps %d", *ngrps)); 957 } 958 959 HXGE_DEBUG_MSG((NULL, INT_CTL, "==> hxge_ldgv_setup: " 960 "ldg %d nldvs %d ldv %d ldvp $%p endldg %d ngrps %d", 961 (*ldgp)->ldg, (*ldgp)->nldvs, ldv, ldvp, endldg, *ngrps)); 962 963 HXGE_DEBUG_MSG((NULL, INT_CTL, "<== hxge_ldgv_setup")); 964 } 965 966 /* 967 * Note: This function assumes the following distribution of mac 968 * addresses for a hydra blade: 969 * 970 * ------------- 971 * 0| |0 - local-mac-address for blade 972 * ------------- 973 * | |1 - Start of alt. mac addr. for blade 974 * | | 975 * | | 976 * | |15 977 * -------------- 978 */ 979 980 static hxge_status_t 981 hxge_mmac_init(p_hxge_t hxgep) 982 { 983 int slot; 984 hxge_mmac_t *mmac_info; 985 986 mmac_info = (hxge_mmac_t *)&hxgep->hxge_mmac_info; 987 988 /* Set flags for unique MAC */ 989 mmac_info->mac_pool[0].flags |= MMAC_SLOT_USED | MMAC_VENDOR_ADDR; 990 mmac_info->num_factory_mmac = 1; 991 992 /* 993 * Skip the factory/default address which is in slot 0. 994 * Initialze all other mac addr. to "AVAILABLE" state. 995 * Clear flags of all alternate MAC slots. 996 */ 997 for (slot = 1; slot < mmac_info->num_mmac; slot++) { 998 (void) hpi_pfc_clear_mac_address(hxgep->hpi_handle, slot); 999 mmac_info->mac_pool[slot].flags = 0; 1000 } 1001 1002 /* Exclude the factory mac address */ 1003 mmac_info->naddrfree = mmac_info->num_mmac - 1; 1004 1005 /* Initialize the first two parameters for mmac kstat */ 1006 hxgep->statsp->mmac_stats.mmac_max_cnt = mmac_info->num_mmac; 1007 hxgep->statsp->mmac_stats.mmac_avail_cnt = mmac_info->naddrfree; 1008 1009 return (HXGE_OK); 1010 } 1011