13dec9fcdSqs148142 /* 23dec9fcdSqs148142 * CDDL HEADER START 33dec9fcdSqs148142 * 43dec9fcdSqs148142 * The contents of this file are subject to the terms of the 53dec9fcdSqs148142 * Common Development and Distribution License (the "License"). 63dec9fcdSqs148142 * You may not use this file except in compliance with the License. 73dec9fcdSqs148142 * 83dec9fcdSqs148142 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93dec9fcdSqs148142 * or http://www.opensolaris.org/os/licensing. 103dec9fcdSqs148142 * See the License for the specific language governing permissions 113dec9fcdSqs148142 * and limitations under the License. 123dec9fcdSqs148142 * 133dec9fcdSqs148142 * When distributing Covered Code, include this CDDL HEADER in each 143dec9fcdSqs148142 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153dec9fcdSqs148142 * If applicable, add the following below this CDDL HEADER, with the 163dec9fcdSqs148142 * fields enclosed by brackets "[]" replaced with your own identifying 173dec9fcdSqs148142 * information: Portions Copyright [yyyy] [name of copyright owner] 183dec9fcdSqs148142 * 193dec9fcdSqs148142 * CDDL HEADER END 203dec9fcdSqs148142 */ 213dec9fcdSqs148142 /* 223dec9fcdSqs148142 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 233dec9fcdSqs148142 * Use is subject to license terms. 24b97d6ca7SMilan Jurik * Copyright 2012 Milan Jurik. All rights reserved. 253dec9fcdSqs148142 */ 263dec9fcdSqs148142 273dec9fcdSqs148142 #include <hxge_impl.h> 283dec9fcdSqs148142 #include <hxge_vmac.h> 293dec9fcdSqs148142 #include <hxge_pfc.h> 303dec9fcdSqs148142 #include <hpi_pfc.h> 313dec9fcdSqs148142 323dec9fcdSqs148142 static hxge_status_t hxge_get_mac_addr_properties(p_hxge_t); 333dec9fcdSqs148142 static void hxge_use_cfg_hydra_properties(p_hxge_t); 343dec9fcdSqs148142 static void hxge_use_cfg_dma_config(p_hxge_t); 353dec9fcdSqs148142 static void hxge_use_cfg_class_config(p_hxge_t); 363dec9fcdSqs148142 static void hxge_set_hw_dma_config(p_hxge_t); 373dec9fcdSqs148142 static void hxge_set_hw_class_config(p_hxge_t); 383dec9fcdSqs148142 static void hxge_ldgv_setup(p_hxge_ldg_t *ldgp, p_hxge_ldv_t *ldvp, uint8_t ldv, 393dec9fcdSqs148142 uint8_t endldg, int *ngrps); 403dec9fcdSqs148142 413dec9fcdSqs148142 extern uint16_t hxge_rcr_timeout; 423dec9fcdSqs148142 extern uint16_t hxge_rcr_threshold; 433dec9fcdSqs148142 443dec9fcdSqs148142 extern uint32_t hxge_rbr_size; 453dec9fcdSqs148142 extern uint32_t hxge_rcr_size; 463dec9fcdSqs148142 47b97d6ca7SMilan Jurik extern uint_t hxge_rx_intr(caddr_t, caddr_t); 48b97d6ca7SMilan Jurik extern uint_t hxge_tx_intr(caddr_t, caddr_t); 49b97d6ca7SMilan Jurik extern uint_t hxge_vmac_intr(caddr_t, caddr_t); 50b97d6ca7SMilan Jurik extern uint_t hxge_syserr_intr(caddr_t, caddr_t); 51b97d6ca7SMilan Jurik extern uint_t hxge_pfc_intr(caddr_t, caddr_t); 523dec9fcdSqs148142 533dec9fcdSqs148142 /* 543dec9fcdSqs148142 * Entry point to populate configuration parameters into the master hxge 553dec9fcdSqs148142 * data structure and to update the NDD parameter list. 563dec9fcdSqs148142 */ 573dec9fcdSqs148142 hxge_status_t 583dec9fcdSqs148142 hxge_get_config_properties(p_hxge_t hxgep) 593dec9fcdSqs148142 { 603dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 613dec9fcdSqs148142 623dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, VPD_CTL, " ==> hxge_get_config_properties")); 633dec9fcdSqs148142 643dec9fcdSqs148142 if (hxgep->hxge_hw_p == NULL) { 653dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 663dec9fcdSqs148142 " hxge_get_config_properties: common hardware not set")); 673dec9fcdSqs148142 return (HXGE_ERROR); 683dec9fcdSqs148142 } 693dec9fcdSqs148142 703dec9fcdSqs148142 hxgep->classifier.tcam_size = TCAM_HXGE_TCAM_MAX_ENTRY; 713dec9fcdSqs148142 723dec9fcdSqs148142 status = hxge_get_mac_addr_properties(hxgep); 733dec9fcdSqs148142 if (status != HXGE_OK) { 743dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 753dec9fcdSqs148142 " hxge_get_config_properties: mac addr properties failed")); 763dec9fcdSqs148142 return (status); 773dec9fcdSqs148142 } 783dec9fcdSqs148142 793dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, VPD_CTL, 803dec9fcdSqs148142 " ==> hxge_get_config_properties: Hydra")); 813dec9fcdSqs148142 823dec9fcdSqs148142 hxge_use_cfg_hydra_properties(hxgep); 833dec9fcdSqs148142 843dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, VPD_CTL, " <== hxge_get_config_properties")); 853dec9fcdSqs148142 return (HXGE_OK); 863dec9fcdSqs148142 } 873dec9fcdSqs148142 883dec9fcdSqs148142 893dec9fcdSqs148142 static void 903dec9fcdSqs148142 hxge_set_hw_vlan_class_config(p_hxge_t hxgep) 913dec9fcdSqs148142 { 923dec9fcdSqs148142 int i; 933dec9fcdSqs148142 p_hxge_param_t param_arr; 943dec9fcdSqs148142 uint_t vlan_cnt; 953dec9fcdSqs148142 int *vlan_cfg_val; 963dec9fcdSqs148142 hxge_param_map_t *vmap; 973dec9fcdSqs148142 char *prop; 983dec9fcdSqs148142 p_hxge_class_pt_cfg_t p_class_cfgp; 993dec9fcdSqs148142 uint32_t good_cfg[32]; 1003dec9fcdSqs148142 int good_count = 0; 1013dec9fcdSqs148142 hxge_mv_cfg_t *vlan_tbl; 1023dec9fcdSqs148142 1033dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_set_hw_vlan_config")); 1043dec9fcdSqs148142 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config; 1053dec9fcdSqs148142 1063dec9fcdSqs148142 param_arr = hxgep->param_arr; 1073dec9fcdSqs148142 prop = param_arr[param_vlan_ids].fcode_name; 1083dec9fcdSqs148142 1093dec9fcdSqs148142 /* 1103dec9fcdSqs148142 * uint32_t array, each array entry specifying a VLAN id 1113dec9fcdSqs148142 */ 1123dec9fcdSqs148142 for (i = 0; i <= VLAN_ID_MAX; i++) { 1133dec9fcdSqs148142 p_class_cfgp->vlan_tbl[i].flag = 0; 1143dec9fcdSqs148142 } 1153dec9fcdSqs148142 1163dec9fcdSqs148142 vlan_tbl = (hxge_mv_cfg_t *)&p_class_cfgp->vlan_tbl[0]; 1173dec9fcdSqs148142 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0, prop, 1183dec9fcdSqs148142 &vlan_cfg_val, &vlan_cnt) != DDI_PROP_SUCCESS) { 1193dec9fcdSqs148142 return; 1203dec9fcdSqs148142 } 1213dec9fcdSqs148142 1223dec9fcdSqs148142 for (i = 0; i < vlan_cnt; i++) { 1233dec9fcdSqs148142 vmap = (hxge_param_map_t *)&vlan_cfg_val[i]; 1243dec9fcdSqs148142 if ((vmap->param_id) && (vmap->param_id <= VLAN_ID_MAX)) { 1253dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG2_CTL, 1263dec9fcdSqs148142 " hxge_vlan_config vlan id %d", vmap->param_id)); 1273dec9fcdSqs148142 1283dec9fcdSqs148142 good_cfg[good_count] = vlan_cfg_val[i]; 1293dec9fcdSqs148142 if (vlan_tbl[vmap->param_id].flag == 0) 1303dec9fcdSqs148142 good_count++; 1313dec9fcdSqs148142 1323dec9fcdSqs148142 vlan_tbl[vmap->param_id].flag = 1; 1333dec9fcdSqs148142 } 1343dec9fcdSqs148142 } 1353dec9fcdSqs148142 1363dec9fcdSqs148142 ddi_prop_free(vlan_cfg_val); 1373dec9fcdSqs148142 if (good_count != vlan_cnt) { 1383dec9fcdSqs148142 (void) ddi_prop_update_int_array(DDI_DEV_T_NONE, 1393dec9fcdSqs148142 hxgep->dip, prop, (int *)good_cfg, good_count); 1403dec9fcdSqs148142 } 1413dec9fcdSqs148142 1423dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_set_hw_vlan_config")); 1433dec9fcdSqs148142 } 1443dec9fcdSqs148142 1453dec9fcdSqs148142 1463dec9fcdSqs148142 /* 1473dec9fcdSqs148142 * Read param_vlan_ids and param_implicit_vlan_id properties from either 1483dec9fcdSqs148142 * hxge.conf or OBP. Update the soft properties. Populate these 1493dec9fcdSqs148142 * properties into the hxge data structure. 1503dec9fcdSqs148142 */ 1513dec9fcdSqs148142 static void 1523dec9fcdSqs148142 hxge_use_cfg_vlan_class_config(p_hxge_t hxgep) 1533dec9fcdSqs148142 { 1543dec9fcdSqs148142 uint_t vlan_cnt; 1553dec9fcdSqs148142 int *vlan_cfg_val; 1563dec9fcdSqs148142 int status; 1573dec9fcdSqs148142 p_hxge_param_t param_arr; 1583dec9fcdSqs148142 char *prop; 1593dec9fcdSqs148142 uint32_t implicit_vlan_id = 0; 1603dec9fcdSqs148142 int *int_prop_val; 1613dec9fcdSqs148142 uint_t prop_len; 1623dec9fcdSqs148142 p_hxge_param_t pa; 1633dec9fcdSqs148142 1643dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_use_cfg_vlan_config")); 1653dec9fcdSqs148142 param_arr = hxgep->param_arr; 1663dec9fcdSqs148142 prop = param_arr[param_vlan_ids].fcode_name; 1673dec9fcdSqs148142 1683dec9fcdSqs148142 status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0, prop, 1693dec9fcdSqs148142 &vlan_cfg_val, &vlan_cnt); 1703dec9fcdSqs148142 if (status == DDI_PROP_SUCCESS) { 1713dec9fcdSqs148142 status = ddi_prop_update_int_array(DDI_DEV_T_NONE, 1723dec9fcdSqs148142 hxgep->dip, prop, vlan_cfg_val, vlan_cnt); 1733dec9fcdSqs148142 ddi_prop_free(vlan_cfg_val); 1743dec9fcdSqs148142 } 1753dec9fcdSqs148142 1763dec9fcdSqs148142 pa = ¶m_arr[param_implicit_vlan_id]; 1773dec9fcdSqs148142 prop = pa->fcode_name; 1783dec9fcdSqs148142 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0, prop, 1793dec9fcdSqs148142 &int_prop_val, &prop_len) == DDI_PROP_SUCCESS) { 1803dec9fcdSqs148142 implicit_vlan_id = (uint32_t)*int_prop_val; 1813dec9fcdSqs148142 if ((implicit_vlan_id >= pa->minimum) || 1823dec9fcdSqs148142 (implicit_vlan_id <= pa->maximum)) { 1833dec9fcdSqs148142 status = ddi_prop_update_int(DDI_DEV_T_NONE, hxgep->dip, 1843dec9fcdSqs148142 prop, (int)implicit_vlan_id); 1853dec9fcdSqs148142 } 1863dec9fcdSqs148142 ddi_prop_free(int_prop_val); 1873dec9fcdSqs148142 } 1883dec9fcdSqs148142 1893dec9fcdSqs148142 hxge_set_hw_vlan_class_config(hxgep); 1903dec9fcdSqs148142 1913dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_use_cfg_vlan_config")); 1923dec9fcdSqs148142 } 1933dec9fcdSqs148142 1943dec9fcdSqs148142 /* 1953dec9fcdSqs148142 * Read in the configuration parameters from either hxge.conf or OBP and 1963dec9fcdSqs148142 * populate the master data structure hxge. 1973dec9fcdSqs148142 * Use these parameters to update the soft properties and the ndd array. 1983dec9fcdSqs148142 */ 1993dec9fcdSqs148142 static void 2003dec9fcdSqs148142 hxge_use_cfg_hydra_properties(p_hxge_t hxgep) 2013dec9fcdSqs148142 { 2023dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_use_cfg_hydra_properties")); 2033dec9fcdSqs148142 2043dec9fcdSqs148142 (void) hxge_use_cfg_dma_config(hxgep); 2053dec9fcdSqs148142 (void) hxge_use_cfg_vlan_class_config(hxgep); 2063dec9fcdSqs148142 (void) hxge_use_cfg_class_config(hxgep); 2073dec9fcdSqs148142 2083dec9fcdSqs148142 /* 2093dec9fcdSqs148142 * Read in the hardware (fcode) properties and use these properties 2103dec9fcdSqs148142 * to update the ndd array. 2113dec9fcdSqs148142 */ 2123dec9fcdSqs148142 (void) hxge_get_param_soft_properties(hxgep); 2133dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_use_cfg_hydra_properties")); 2143dec9fcdSqs148142 } 2153dec9fcdSqs148142 2163dec9fcdSqs148142 2173dec9fcdSqs148142 /* 2183dec9fcdSqs148142 * Read param_accept_jumbo, param_rxdma_intr_time, and param_rxdma_intr_pkts 2193dec9fcdSqs148142 * from either hxge.conf or OBP. 2203dec9fcdSqs148142 * Update the soft properties. 2213dec9fcdSqs148142 * Populate these properties into the hxge data structure for latter use. 2223dec9fcdSqs148142 */ 2233dec9fcdSqs148142 static void 2243dec9fcdSqs148142 hxge_use_cfg_dma_config(p_hxge_t hxgep) 2253dec9fcdSqs148142 { 2263dec9fcdSqs148142 int tx_ndmas, rx_ndmas; 2273dec9fcdSqs148142 p_hxge_dma_pt_cfg_t p_dma_cfgp; 2283dec9fcdSqs148142 p_hxge_hw_pt_cfg_t p_cfgp; 2293dec9fcdSqs148142 dev_info_t *dip; 2303dec9fcdSqs148142 p_hxge_param_t param_arr; 2313dec9fcdSqs148142 char *prop; 2323dec9fcdSqs148142 int *prop_val; 2333dec9fcdSqs148142 uint_t prop_len; 2343dec9fcdSqs148142 2353dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_use_cfg_dma_config")); 2363dec9fcdSqs148142 param_arr = hxgep->param_arr; 2373dec9fcdSqs148142 2383dec9fcdSqs148142 p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 2393dec9fcdSqs148142 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 2403dec9fcdSqs148142 dip = hxgep->dip; 2413dec9fcdSqs148142 2423dec9fcdSqs148142 tx_ndmas = 4; 2433dec9fcdSqs148142 p_cfgp->start_tdc = 0; 2443dec9fcdSqs148142 p_cfgp->max_tdcs = hxgep->max_tdcs = tx_ndmas; 2453dec9fcdSqs148142 hxgep->tdc_mask = (tx_ndmas - 1); 2463dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, "==> hxge_use_cfg_dma_config: " 2473dec9fcdSqs148142 "p_cfgp 0x%llx max_tdcs %d hxgep->max_tdcs %d", 2483dec9fcdSqs148142 p_cfgp, p_cfgp->max_tdcs, hxgep->max_tdcs)); 2493dec9fcdSqs148142 2503dec9fcdSqs148142 rx_ndmas = 4; 2513dec9fcdSqs148142 p_cfgp->start_rdc = 0; 2523dec9fcdSqs148142 p_cfgp->max_rdcs = hxgep->max_rdcs = rx_ndmas; 2533dec9fcdSqs148142 2543dec9fcdSqs148142 p_cfgp->start_ldg = 0; 2553dec9fcdSqs148142 p_cfgp->max_ldgs = HXGE_INT_MAX_LDG; 2563dec9fcdSqs148142 2573dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, "==> hxge_use_default_dma_config: " 2583dec9fcdSqs148142 "p_cfgp 0x%llx max_rdcs %d hxgep->max_rdcs %d", 2593dec9fcdSqs148142 p_cfgp, p_cfgp->max_rdcs, hxgep->max_rdcs)); 2603dec9fcdSqs148142 2613dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, "==> hxge_use_cfg_dma_config: " 2623dec9fcdSqs148142 "p_cfgp 0x%016llx start_ldg %d hxgep->max_ldgs %d ", 2633dec9fcdSqs148142 p_cfgp, p_cfgp->start_ldg, p_cfgp->max_ldgs)); 2643dec9fcdSqs148142 2653dec9fcdSqs148142 /* 2663dec9fcdSqs148142 * add code for individual rdc properties 2673dec9fcdSqs148142 */ 2683dec9fcdSqs148142 prop = param_arr[param_accept_jumbo].fcode_name; 2693dec9fcdSqs148142 2703dec9fcdSqs148142 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop, 2713dec9fcdSqs148142 &prop_val, &prop_len) == DDI_PROP_SUCCESS) { 2723dec9fcdSqs148142 if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) { 2733dec9fcdSqs148142 (void) ddi_prop_update_int_array(DDI_DEV_T_NONE, 2743dec9fcdSqs148142 hxgep->dip, prop, prop_val, prop_len); 2753dec9fcdSqs148142 } 2763dec9fcdSqs148142 ddi_prop_free(prop_val); 2773dec9fcdSqs148142 } 2783dec9fcdSqs148142 2793dec9fcdSqs148142 prop = param_arr[param_rxdma_intr_time].fcode_name; 2803dec9fcdSqs148142 2813dec9fcdSqs148142 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop, 2823dec9fcdSqs148142 &prop_val, &prop_len) == DDI_PROP_SUCCESS) { 2833dec9fcdSqs148142 if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) { 2843dec9fcdSqs148142 (void) ddi_prop_update_int_array(DDI_DEV_T_NONE, 2853dec9fcdSqs148142 hxgep->dip, prop, prop_val, prop_len); 2863dec9fcdSqs148142 } 2873dec9fcdSqs148142 ddi_prop_free(prop_val); 2883dec9fcdSqs148142 } 2893dec9fcdSqs148142 2903dec9fcdSqs148142 prop = param_arr[param_rxdma_intr_pkts].fcode_name; 2913dec9fcdSqs148142 2923dec9fcdSqs148142 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop, 2933dec9fcdSqs148142 &prop_val, &prop_len) == DDI_PROP_SUCCESS) { 2943dec9fcdSqs148142 if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) { 2953dec9fcdSqs148142 (void) ddi_prop_update_int_array(DDI_DEV_T_NONE, 2963dec9fcdSqs148142 hxgep->dip, prop, prop_val, prop_len); 2973dec9fcdSqs148142 } 2983dec9fcdSqs148142 ddi_prop_free(prop_val); 2993dec9fcdSqs148142 } 3003dec9fcdSqs148142 3013dec9fcdSqs148142 hxge_set_hw_dma_config(hxgep); 3023dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, "<== hxge_use_cfg_dma_config")); 3033dec9fcdSqs148142 } 3043dec9fcdSqs148142 3053dec9fcdSqs148142 static void 3063dec9fcdSqs148142 hxge_use_cfg_class_config(p_hxge_t hxgep) 3073dec9fcdSqs148142 { 3083dec9fcdSqs148142 hxge_set_hw_class_config(hxgep); 3093dec9fcdSqs148142 } 3103dec9fcdSqs148142 3113dec9fcdSqs148142 static void 3123dec9fcdSqs148142 hxge_set_hw_dma_config(p_hxge_t hxgep) 3133dec9fcdSqs148142 { 3143dec9fcdSqs148142 p_hxge_dma_pt_cfg_t p_dma_cfgp; 3153dec9fcdSqs148142 p_hxge_hw_pt_cfg_t p_cfgp; 3163dec9fcdSqs148142 3173dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, "==> hxge_set_hw_dma_config")); 3183dec9fcdSqs148142 3193dec9fcdSqs148142 p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 3203dec9fcdSqs148142 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 3213dec9fcdSqs148142 3223dec9fcdSqs148142 /* Transmit DMA Channels */ 3233dec9fcdSqs148142 hxgep->ntdc = p_cfgp->max_tdcs; 3243dec9fcdSqs148142 3253dec9fcdSqs148142 /* Receive DMA Channels */ 3263dec9fcdSqs148142 hxgep->nrdc = p_cfgp->max_rdcs; 3273dec9fcdSqs148142 3283dec9fcdSqs148142 p_dma_cfgp->rbr_size = hxge_rbr_size; 3298ad8db65SMichael Speer if (hxge_rcr_size > HXGE_RCR_MAX) 3308ad8db65SMichael Speer hxge_rcr_size = HXGE_RCR_MAX; 3313dec9fcdSqs148142 p_dma_cfgp->rcr_size = hxge_rcr_size; 3323dec9fcdSqs148142 3333dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_set_hw_dma_config")); 3343dec9fcdSqs148142 } 3353dec9fcdSqs148142 3363dec9fcdSqs148142 3373dec9fcdSqs148142 boolean_t 3383dec9fcdSqs148142 hxge_check_rxdma_port_member(p_hxge_t hxgep, uint8_t rdc) 3393dec9fcdSqs148142 { 3403dec9fcdSqs148142 p_hxge_dma_pt_cfg_t p_dma_cfgp; 3413dec9fcdSqs148142 p_hxge_hw_pt_cfg_t p_cfgp; 3423dec9fcdSqs148142 int status = B_TRUE; 3433dec9fcdSqs148142 3443dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG2_CTL, "==> hxge_check_rxdma_port_member")); 3453dec9fcdSqs148142 3463dec9fcdSqs148142 p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 3473dec9fcdSqs148142 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 3483dec9fcdSqs148142 3493dec9fcdSqs148142 /* Receive DMA Channels */ 3503dec9fcdSqs148142 if (rdc < p_cfgp->max_rdcs) 3513dec9fcdSqs148142 status = B_TRUE; 3523dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG2_CTL, " <== hxge_check_rxdma_port_member")); 3533dec9fcdSqs148142 3543dec9fcdSqs148142 return (status); 3553dec9fcdSqs148142 } 3563dec9fcdSqs148142 3573dec9fcdSqs148142 boolean_t 3583dec9fcdSqs148142 hxge_check_txdma_port_member(p_hxge_t hxgep, uint8_t tdc) 3593dec9fcdSqs148142 { 3603dec9fcdSqs148142 p_hxge_dma_pt_cfg_t p_dma_cfgp; 3613dec9fcdSqs148142 p_hxge_hw_pt_cfg_t p_cfgp; 3623dec9fcdSqs148142 int status = B_FALSE; 3633dec9fcdSqs148142 3643dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG2_CTL, "==> hxge_check_txdma_port_member")); 3653dec9fcdSqs148142 3663dec9fcdSqs148142 p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 3673dec9fcdSqs148142 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 3683dec9fcdSqs148142 3693dec9fcdSqs148142 /* Receive DMA Channels */ 3703dec9fcdSqs148142 if (tdc < p_cfgp->max_tdcs) 3713dec9fcdSqs148142 status = B_TRUE; 3723dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG2_CTL, " <== hxge_check_txdma_port_member")); 3733dec9fcdSqs148142 3743dec9fcdSqs148142 return (status); 3753dec9fcdSqs148142 } 3763dec9fcdSqs148142 3773dec9fcdSqs148142 3783dec9fcdSqs148142 /* 3793dec9fcdSqs148142 * Read the L2 classes, L3 classes, and initial hash from either hxge.conf 3803dec9fcdSqs148142 * or OBP. Populate these properties into the hxge data structure for latter 3813dec9fcdSqs148142 * use. Note that we are not updating these soft properties. 3823dec9fcdSqs148142 */ 3833dec9fcdSqs148142 static void 3843dec9fcdSqs148142 hxge_set_hw_class_config(p_hxge_t hxgep) 3853dec9fcdSqs148142 { 3863dec9fcdSqs148142 int i, j; 3873dec9fcdSqs148142 p_hxge_param_t param_arr; 3883dec9fcdSqs148142 int *int_prop_val; 3893dec9fcdSqs148142 uint32_t cfg_value; 3903dec9fcdSqs148142 char *prop; 3913dec9fcdSqs148142 p_hxge_class_pt_cfg_t p_class_cfgp; 3923dec9fcdSqs148142 int start_prop, end_prop; 3933dec9fcdSqs148142 uint_t prop_cnt; 3943dec9fcdSqs148142 3953dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_set_hw_class_config")); 3963dec9fcdSqs148142 3973dec9fcdSqs148142 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config; 3983dec9fcdSqs148142 3993dec9fcdSqs148142 param_arr = hxgep->param_arr; 4003dec9fcdSqs148142 4013dec9fcdSqs148142 /* 4023dec9fcdSqs148142 * L2 class configuration. User configurable ether types 4033dec9fcdSqs148142 */ 4043dec9fcdSqs148142 start_prop = param_class_cfg_ether_usr1; 4053dec9fcdSqs148142 end_prop = param_class_cfg_ether_usr2; 4063dec9fcdSqs148142 4073dec9fcdSqs148142 for (i = start_prop; i <= end_prop; i++) { 4083dec9fcdSqs148142 prop = param_arr[i].fcode_name; 4093dec9fcdSqs148142 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 4103dec9fcdSqs148142 0, prop, &int_prop_val, &prop_cnt) == DDI_PROP_SUCCESS) { 4113dec9fcdSqs148142 cfg_value = (uint32_t)*int_prop_val; 4123dec9fcdSqs148142 ddi_prop_free(int_prop_val); 4133dec9fcdSqs148142 } else { 4143dec9fcdSqs148142 cfg_value = (uint32_t)param_arr[i].value; 4153dec9fcdSqs148142 } 4163dec9fcdSqs148142 4173dec9fcdSqs148142 j = (i - start_prop) + TCAM_CLASS_ETYPE_1; 4183dec9fcdSqs148142 p_class_cfgp->class_cfg[j] = cfg_value; 4193dec9fcdSqs148142 } 4203dec9fcdSqs148142 4213dec9fcdSqs148142 /* 4223dec9fcdSqs148142 * Use properties from either .conf or the NDD param array. Only bits 4233dec9fcdSqs148142 * 2 and 3 are significant 4243dec9fcdSqs148142 */ 4253dec9fcdSqs148142 start_prop = param_class_opt_ipv4_tcp; 4263dec9fcdSqs148142 end_prop = param_class_opt_ipv6_sctp; 4273dec9fcdSqs148142 4283dec9fcdSqs148142 for (i = start_prop; i <= end_prop; i++) { 4293dec9fcdSqs148142 prop = param_arr[i].fcode_name; 4303dec9fcdSqs148142 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 4313dec9fcdSqs148142 0, prop, &int_prop_val, &prop_cnt) == DDI_PROP_SUCCESS) { 4323dec9fcdSqs148142 cfg_value = (uint32_t)*int_prop_val; 4333dec9fcdSqs148142 ddi_prop_free(int_prop_val); 4343dec9fcdSqs148142 } else { 4353dec9fcdSqs148142 cfg_value = (uint32_t)param_arr[i].value; 4363dec9fcdSqs148142 } 4373dec9fcdSqs148142 4383dec9fcdSqs148142 j = (i - start_prop) + TCAM_CLASS_TCP_IPV4; 4393dec9fcdSqs148142 p_class_cfgp->class_cfg[j] = cfg_value; 4403dec9fcdSqs148142 } 4413dec9fcdSqs148142 4423dec9fcdSqs148142 prop = param_arr[param_hash_init_value].fcode_name; 4433dec9fcdSqs148142 4443dec9fcdSqs148142 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0, prop, 4453dec9fcdSqs148142 &int_prop_val, &prop_cnt) == DDI_PROP_SUCCESS) { 4463dec9fcdSqs148142 cfg_value = (uint32_t)*int_prop_val; 4473dec9fcdSqs148142 ddi_prop_free(int_prop_val); 4483dec9fcdSqs148142 } else { 4493dec9fcdSqs148142 cfg_value = (uint32_t)param_arr[param_hash_init_value].value; 4503dec9fcdSqs148142 } 4513dec9fcdSqs148142 4523dec9fcdSqs148142 p_class_cfgp->init_hash = (uint32_t)cfg_value; 4533dec9fcdSqs148142 4543dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_set_hw_class_config")); 4553dec9fcdSqs148142 } 4563dec9fcdSqs148142 4573dec9fcdSqs148142 4583dec9fcdSqs148142 /* 4593dec9fcdSqs148142 * Interrupts related interface functions. 4603dec9fcdSqs148142 */ 4613dec9fcdSqs148142 hxge_status_t 4623dec9fcdSqs148142 hxge_ldgv_init(p_hxge_t hxgep, int *navail_p, int *nrequired_p) 4633dec9fcdSqs148142 { 4643dec9fcdSqs148142 uint8_t ldv, i, maxldvs, maxldgs, start, end, nldvs; 4653dec9fcdSqs148142 int ldg, endldg, ngrps; 4663dec9fcdSqs148142 uint8_t channel; 4673dec9fcdSqs148142 p_hxge_dma_pt_cfg_t p_dma_cfgp; 4683dec9fcdSqs148142 p_hxge_hw_pt_cfg_t p_cfgp; 4693dec9fcdSqs148142 p_hxge_ldgv_t ldgvp; 4703dec9fcdSqs148142 p_hxge_ldg_t ldgp, ptr; 4713dec9fcdSqs148142 p_hxge_ldv_t ldvp; 4723dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 473e5d97391SQiyan Sun - Sun Microsystems - San Diego United States peu_intr_mask_t parity_err_mask; 4743dec9fcdSqs148142 4753dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_ldgv_init")); 4763dec9fcdSqs148142 if (!*navail_p) { 4773dec9fcdSqs148142 *nrequired_p = 0; 4783dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 4793dec9fcdSqs148142 "<== hxge_ldgv_init:no avail")); 4803dec9fcdSqs148142 return (HXGE_ERROR); 4813dec9fcdSqs148142 } 4823dec9fcdSqs148142 p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 4833dec9fcdSqs148142 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; 4843dec9fcdSqs148142 4853dec9fcdSqs148142 /* each DMA channels */ 4863dec9fcdSqs148142 nldvs = p_cfgp->max_tdcs + p_cfgp->max_rdcs; 4873dec9fcdSqs148142 4883dec9fcdSqs148142 /* vmac */ 4893dec9fcdSqs148142 nldvs++; 4903dec9fcdSqs148142 4913dec9fcdSqs148142 /* pfc */ 4923dec9fcdSqs148142 nldvs++; 4933dec9fcdSqs148142 4943dec9fcdSqs148142 /* system error interrupts. */ 4953dec9fcdSqs148142 nldvs++; 4963dec9fcdSqs148142 4973dec9fcdSqs148142 maxldvs = nldvs; 4983dec9fcdSqs148142 maxldgs = p_cfgp->max_ldgs; 4993dec9fcdSqs148142 5003dec9fcdSqs148142 if (!maxldvs || !maxldgs) { 5013dec9fcdSqs148142 /* No devices configured. */ 5023dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_ldgv_init: " 5033dec9fcdSqs148142 "no logical devices or groups configured.")); 5043dec9fcdSqs148142 return (HXGE_ERROR); 5053dec9fcdSqs148142 } 5063dec9fcdSqs148142 ldgvp = hxgep->ldgvp; 5073dec9fcdSqs148142 if (ldgvp == NULL) { 5083dec9fcdSqs148142 ldgvp = KMEM_ZALLOC(sizeof (hxge_ldgv_t), KM_SLEEP); 5093dec9fcdSqs148142 hxgep->ldgvp = ldgvp; 5103dec9fcdSqs148142 ldgvp->maxldgs = maxldgs; 5113dec9fcdSqs148142 ldgvp->maxldvs = maxldvs; 5123dec9fcdSqs148142 ldgp = ldgvp->ldgp = 5133dec9fcdSqs148142 KMEM_ZALLOC(sizeof (hxge_ldg_t) * maxldgs, KM_SLEEP); 5143dec9fcdSqs148142 ldvp = ldgvp->ldvp = 5153dec9fcdSqs148142 KMEM_ZALLOC(sizeof (hxge_ldv_t) * maxldvs, KM_SLEEP); 5163dec9fcdSqs148142 } 5173dec9fcdSqs148142 5183dec9fcdSqs148142 ldgvp->ndma_ldvs = p_cfgp->max_tdcs + p_cfgp->max_rdcs; 5193dec9fcdSqs148142 ldgvp->tmres = HXGE_TIMER_RESO; 5203dec9fcdSqs148142 5213dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 5223dec9fcdSqs148142 "==> hxge_ldgv_init: maxldvs %d maxldgs %d nldvs %d", 5233dec9fcdSqs148142 maxldvs, maxldgs, nldvs)); 5243dec9fcdSqs148142 5253dec9fcdSqs148142 ldg = p_cfgp->start_ldg; 5263dec9fcdSqs148142 ptr = ldgp; 5273dec9fcdSqs148142 for (i = 0; i < maxldgs; i++) { 5283dec9fcdSqs148142 ptr->arm = B_TRUE; 5293dec9fcdSqs148142 ptr->vldg_index = i; 5303dec9fcdSqs148142 ptr->ldg_timer = HXGE_TIMER_LDG; 5313dec9fcdSqs148142 ptr->ldg = ldg++; 5323dec9fcdSqs148142 ptr->sys_intr_handler = hxge_intr; 5333dec9fcdSqs148142 ptr->nldvs = 0; 5343dec9fcdSqs148142 ptr->hxgep = hxgep; 5353dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 5363dec9fcdSqs148142 "==> hxge_ldgv_init: maxldvs %d maxldgs %d ldg %d", 5373dec9fcdSqs148142 maxldvs, maxldgs, ptr->ldg)); 5383dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 5393dec9fcdSqs148142 "==> hxge_ldv_init: timer %d", ptr->ldg_timer)); 5403dec9fcdSqs148142 ptr++; 5413dec9fcdSqs148142 } 5423dec9fcdSqs148142 5433dec9fcdSqs148142 ldg = p_cfgp->start_ldg; 5443dec9fcdSqs148142 if (maxldgs > *navail_p) { 5453dec9fcdSqs148142 ngrps = *navail_p; 5463dec9fcdSqs148142 } else { 5473dec9fcdSqs148142 ngrps = maxldgs; 5483dec9fcdSqs148142 } 5493dec9fcdSqs148142 endldg = ldg + ngrps; 5503dec9fcdSqs148142 5513dec9fcdSqs148142 /* 5523dec9fcdSqs148142 * Receive DMA channels. 5533dec9fcdSqs148142 */ 5543dec9fcdSqs148142 channel = p_cfgp->start_rdc; 5553dec9fcdSqs148142 start = p_cfgp->start_rdc + HXGE_RDMA_LD_START; 5563dec9fcdSqs148142 end = start + p_cfgp->max_rdcs; 5573dec9fcdSqs148142 nldvs = 0; 5583dec9fcdSqs148142 ldgvp->nldvs = 0; 5593dec9fcdSqs148142 ldgp->ldvp = NULL; 5603dec9fcdSqs148142 *nrequired_p = 0; 5613dec9fcdSqs148142 ptr = ldgp; 5623dec9fcdSqs148142 5633dec9fcdSqs148142 /* 5643dec9fcdSqs148142 * Start with RDC to configure logical devices for each group. 5653dec9fcdSqs148142 */ 5663dec9fcdSqs148142 for (i = 0, ldv = start; ldv < end; i++, ldv++) { 5673dec9fcdSqs148142 ldvp->is_rxdma = B_TRUE; 5683dec9fcdSqs148142 ldvp->ldv = ldv; 5693dec9fcdSqs148142 5703dec9fcdSqs148142 /* 5713dec9fcdSqs148142 * If non-seq needs to change the following code 5723dec9fcdSqs148142 */ 5733dec9fcdSqs148142 ldvp->channel = channel++; 5743dec9fcdSqs148142 ldvp->vdma_index = i; 5753dec9fcdSqs148142 ldvp->ldv_intr_handler = hxge_rx_intr; 5763dec9fcdSqs148142 ldvp->ldv_ldf_masks = 0; 5773dec9fcdSqs148142 ldvp->use_timer = B_FALSE; 5783dec9fcdSqs148142 ldvp->hxgep = hxgep; 5793dec9fcdSqs148142 hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p); 5803dec9fcdSqs148142 nldvs++; 5813dec9fcdSqs148142 } 5823dec9fcdSqs148142 5833dec9fcdSqs148142 /* 5843dec9fcdSqs148142 * Transmit DMA channels. 5853dec9fcdSqs148142 */ 5863dec9fcdSqs148142 channel = p_cfgp->start_tdc; 5873dec9fcdSqs148142 start = p_cfgp->start_tdc + HXGE_TDMA_LD_START; 5883dec9fcdSqs148142 end = start + p_cfgp->max_tdcs; 5893dec9fcdSqs148142 for (i = 0, ldv = start; ldv < end; i++, ldv++) { 5903dec9fcdSqs148142 ldvp->is_txdma = B_TRUE; 5913dec9fcdSqs148142 ldvp->ldv = ldv; 5923dec9fcdSqs148142 ldvp->channel = channel++; 5933dec9fcdSqs148142 ldvp->vdma_index = i; 5943dec9fcdSqs148142 ldvp->ldv_intr_handler = hxge_tx_intr; 5953dec9fcdSqs148142 ldvp->ldv_ldf_masks = 0; 5963dec9fcdSqs148142 ldvp->use_timer = B_FALSE; 5973dec9fcdSqs148142 ldvp->hxgep = hxgep; 5983dec9fcdSqs148142 hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p); 5993dec9fcdSqs148142 nldvs++; 6003dec9fcdSqs148142 } 6013dec9fcdSqs148142 6023dec9fcdSqs148142 /* 6033dec9fcdSqs148142 * VMAC 6043dec9fcdSqs148142 */ 6053dec9fcdSqs148142 ldvp->is_vmac = B_TRUE; 6063dec9fcdSqs148142 ldvp->ldv_intr_handler = hxge_vmac_intr; 6073dec9fcdSqs148142 ldvp->ldv_ldf_masks = 0; 6083dec9fcdSqs148142 ldv = HXGE_VMAC_LD; 6093dec9fcdSqs148142 ldvp->ldv = ldv; 6103dec9fcdSqs148142 ldvp->use_timer = B_FALSE; 6113dec9fcdSqs148142 ldvp->hxgep = hxgep; 6123dec9fcdSqs148142 hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p); 6133dec9fcdSqs148142 nldvs++; 6143dec9fcdSqs148142 6153dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 6163dec9fcdSqs148142 "==> hxge_ldgv_init: nldvs %d navail %d nrequired %d", 6173dec9fcdSqs148142 nldvs, *navail_p, *nrequired_p)); 6183dec9fcdSqs148142 6193dec9fcdSqs148142 /* 6203dec9fcdSqs148142 * PFC 6213dec9fcdSqs148142 */ 6223dec9fcdSqs148142 ldvp->is_pfc = B_TRUE; 6233dec9fcdSqs148142 ldvp->ldv_intr_handler = hxge_pfc_intr; 6243dec9fcdSqs148142 ldvp->ldv_ldf_masks = 0; 6253dec9fcdSqs148142 ldv = HXGE_PFC_LD; 6263dec9fcdSqs148142 ldvp->ldv = ldv; 6273dec9fcdSqs148142 ldvp->use_timer = B_FALSE; 6283dec9fcdSqs148142 ldvp->hxgep = hxgep; 6293dec9fcdSqs148142 hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p); 6303dec9fcdSqs148142 nldvs++; 6313dec9fcdSqs148142 6323dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 6333dec9fcdSqs148142 "==> hxge_ldgv_init: nldvs %d navail %d nrequired %d", 6343dec9fcdSqs148142 nldvs, *navail_p, *nrequired_p)); 6353dec9fcdSqs148142 6363dec9fcdSqs148142 /* 6373dec9fcdSqs148142 * System error interrupts. 6383dec9fcdSqs148142 */ 6393dec9fcdSqs148142 ldv = HXGE_SYS_ERROR_LD; 6403dec9fcdSqs148142 ldvp->ldv = ldv; 6413dec9fcdSqs148142 ldvp->is_syserr = B_TRUE; 6423dec9fcdSqs148142 ldvp->ldv_intr_handler = hxge_syserr_intr; 6433dec9fcdSqs148142 ldvp->ldv_ldf_masks = 0; 6443dec9fcdSqs148142 ldvp->hxgep = hxgep; 6453dec9fcdSqs148142 ldvp->use_timer = B_FALSE; 6463dec9fcdSqs148142 ldgvp->ldvp_syserr = ldvp; 6473dec9fcdSqs148142 6483dec9fcdSqs148142 /* Reset PEU error mask to allow PEU error interrupts */ 649e5d97391SQiyan Sun - Sun Microsystems - San Diego United States /* 650e5d97391SQiyan Sun - Sun Microsystems - San Diego United States * Keep the msix parity error mask here and remove it 651e5d97391SQiyan Sun - Sun Microsystems - San Diego United States * after ddi_intr_enable call to avoid a msix par err 652e5d97391SQiyan Sun - Sun Microsystems - San Diego United States */ 653e5d97391SQiyan Sun - Sun Microsystems - San Diego United States parity_err_mask.value = 0; 654e5d97391SQiyan Sun - Sun Microsystems - San Diego United States parity_err_mask.bits.eic_msix_parerr_mask = 1; 655e5d97391SQiyan Sun - Sun Microsystems - San Diego United States HXGE_REG_WR32(hxgep->hpi_handle, PEU_INTR_MASK, parity_err_mask.value); 6563dec9fcdSqs148142 6573dec9fcdSqs148142 /* 6583dec9fcdSqs148142 * Unmask the system interrupt states. 6593dec9fcdSqs148142 */ 6603dec9fcdSqs148142 (void) hxge_fzc_sys_err_mask_set(hxgep, B_FALSE); 6613dec9fcdSqs148142 (void) hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p); 6623dec9fcdSqs148142 nldvs++; 6633dec9fcdSqs148142 6643dec9fcdSqs148142 ldgvp->ldg_intrs = *nrequired_p; 6653dec9fcdSqs148142 6663dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 6673dec9fcdSqs148142 "==> hxge_ldgv_init: nldvs %d navail %d nrequired %d", 6683dec9fcdSqs148142 nldvs, *navail_p, *nrequired_p)); 6693dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_ldgv_init")); 6703dec9fcdSqs148142 return (status); 6713dec9fcdSqs148142 } 6723dec9fcdSqs148142 6733dec9fcdSqs148142 hxge_status_t 6743dec9fcdSqs148142 hxge_ldgv_uninit(p_hxge_t hxgep) 6753dec9fcdSqs148142 { 6763dec9fcdSqs148142 p_hxge_ldgv_t ldgvp; 6773dec9fcdSqs148142 6783dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_ldgv_uninit")); 6793dec9fcdSqs148142 ldgvp = hxgep->ldgvp; 6803dec9fcdSqs148142 if (ldgvp == NULL) { 6813dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 6823dec9fcdSqs148142 "<== hxge_ldgv_uninit: no logical group configured.")); 6833dec9fcdSqs148142 return (HXGE_OK); 6843dec9fcdSqs148142 } 6853dec9fcdSqs148142 6863dec9fcdSqs148142 if (ldgvp->ldgp) { 6873dec9fcdSqs148142 KMEM_FREE(ldgvp->ldgp, sizeof (hxge_ldg_t) * ldgvp->maxldgs); 6883dec9fcdSqs148142 } 6893dec9fcdSqs148142 if (ldgvp->ldvp) { 6903dec9fcdSqs148142 KMEM_FREE(ldgvp->ldvp, sizeof (hxge_ldv_t) * ldgvp->maxldvs); 6913dec9fcdSqs148142 } 6923dec9fcdSqs148142 6933dec9fcdSqs148142 KMEM_FREE(ldgvp, sizeof (hxge_ldgv_t)); 6943dec9fcdSqs148142 hxgep->ldgvp = NULL; 6953dec9fcdSqs148142 6963dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_ldgv_uninit")); 6973dec9fcdSqs148142 return (HXGE_OK); 6983dec9fcdSqs148142 } 6993dec9fcdSqs148142 7003dec9fcdSqs148142 hxge_status_t 7013dec9fcdSqs148142 hxge_intr_ldgv_init(p_hxge_t hxgep) 7023dec9fcdSqs148142 { 7033dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 7043dec9fcdSqs148142 7053dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intr_ldgv_init")); 7063dec9fcdSqs148142 /* 7073dec9fcdSqs148142 * Configure the logical device group numbers, state vectors 7083dec9fcdSqs148142 * and interrupt masks for each logical device. 7093dec9fcdSqs148142 */ 7103dec9fcdSqs148142 status = hxge_fzc_intr_init(hxgep); 7113dec9fcdSqs148142 7123dec9fcdSqs148142 /* 7133dec9fcdSqs148142 * Configure logical device masks and timers. 7143dec9fcdSqs148142 */ 7153dec9fcdSqs148142 status = hxge_intr_mask_mgmt(hxgep); 7163dec9fcdSqs148142 7173dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intr_ldgv_init")); 7183dec9fcdSqs148142 return (status); 7193dec9fcdSqs148142 } 7203dec9fcdSqs148142 7213dec9fcdSqs148142 hxge_status_t 7223dec9fcdSqs148142 hxge_intr_mask_mgmt(p_hxge_t hxgep) 7233dec9fcdSqs148142 { 7243dec9fcdSqs148142 p_hxge_ldgv_t ldgvp; 7253dec9fcdSqs148142 p_hxge_ldg_t ldgp; 7263dec9fcdSqs148142 p_hxge_ldv_t ldvp; 7273dec9fcdSqs148142 hpi_handle_t handle; 7283dec9fcdSqs148142 int i, j; 7293dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 7303dec9fcdSqs148142 7313dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intr_mask_mgmt")); 7323dec9fcdSqs148142 7333dec9fcdSqs148142 if ((ldgvp = hxgep->ldgvp) == NULL) { 7343dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 7353dec9fcdSqs148142 "<== hxge_intr_mask_mgmt: Null ldgvp")); 7363dec9fcdSqs148142 return (HXGE_ERROR); 7373dec9fcdSqs148142 } 7383dec9fcdSqs148142 handle = HXGE_DEV_HPI_HANDLE(hxgep); 7393dec9fcdSqs148142 ldgp = ldgvp->ldgp; 7403dec9fcdSqs148142 ldvp = ldgvp->ldvp; 7413dec9fcdSqs148142 if (ldgp == NULL || ldvp == NULL) { 7423dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 7433dec9fcdSqs148142 "<== hxge_intr_mask_mgmt: Null ldgp or ldvp")); 7443dec9fcdSqs148142 return (HXGE_ERROR); 7453dec9fcdSqs148142 } 7463dec9fcdSqs148142 7473dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 7483dec9fcdSqs148142 "==> hxge_intr_mask_mgmt: # of intrs %d ", ldgvp->ldg_intrs)); 7493dec9fcdSqs148142 /* Initialize masks. */ 7503dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 7513dec9fcdSqs148142 "==> hxge_intr_mask_mgmt(Hydra): # intrs %d ", ldgvp->ldg_intrs)); 7523dec9fcdSqs148142 for (i = 0; i < ldgvp->ldg_intrs; i++, ldgp++) { 7533dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 7543dec9fcdSqs148142 "==> hxge_intr_mask_mgmt(Hydra): # ldv %d in group %d", 7553dec9fcdSqs148142 ldgp->nldvs, ldgp->ldg)); 7563dec9fcdSqs148142 for (j = 0; j < ldgp->nldvs; j++, ldvp++) { 7573dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 7583dec9fcdSqs148142 "==> hxge_intr_mask_mgmt: set ldv # %d " 7593dec9fcdSqs148142 "for ldg %d", ldvp->ldv, ldgp->ldg)); 7603dec9fcdSqs148142 rs = hpi_intr_mask_set(handle, ldvp->ldv, 7613dec9fcdSqs148142 ldvp->ldv_ldf_masks); 7623dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 7633dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 7643dec9fcdSqs148142 "<== hxge_intr_mask_mgmt: set mask failed " 7653dec9fcdSqs148142 " rs 0x%x ldv %d mask 0x%x", 7663dec9fcdSqs148142 rs, ldvp->ldv, ldvp->ldv_ldf_masks)); 7673dec9fcdSqs148142 return (HXGE_ERROR | rs); 7683dec9fcdSqs148142 } 7693dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 7703dec9fcdSqs148142 "==> hxge_intr_mask_mgmt: set mask OK " 7713dec9fcdSqs148142 " rs 0x%x ldv %d mask 0x%x", 7723dec9fcdSqs148142 rs, ldvp->ldv, ldvp->ldv_ldf_masks)); 7733dec9fcdSqs148142 } 7743dec9fcdSqs148142 } 7753dec9fcdSqs148142 7763dec9fcdSqs148142 ldgp = ldgvp->ldgp; 7773dec9fcdSqs148142 /* Configure timer and arm bit */ 7783dec9fcdSqs148142 for (i = 0; i < hxgep->ldgvp->ldg_intrs; i++, ldgp++) { 7793dec9fcdSqs148142 rs = hpi_intr_ldg_mgmt_set(handle, ldgp->ldg, 7803dec9fcdSqs148142 ldgp->arm, ldgp->ldg_timer); 7813dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 7823dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 7833dec9fcdSqs148142 "<== hxge_intr_mask_mgmt: set timer failed " 7843dec9fcdSqs148142 " rs 0x%x dg %d timer 0x%x", 7853dec9fcdSqs148142 rs, ldgp->ldg, ldgp->ldg_timer)); 7863dec9fcdSqs148142 return (HXGE_ERROR | rs); 7873dec9fcdSqs148142 } 7883dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 7893dec9fcdSqs148142 "==> hxge_intr_mask_mgmt: set timer OK " 7903dec9fcdSqs148142 " rs 0x%x ldg %d timer 0x%x", 7913dec9fcdSqs148142 rs, ldgp->ldg, ldgp->ldg_timer)); 7923dec9fcdSqs148142 } 7933dec9fcdSqs148142 7943dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_fzc_intr_mask_mgmt")); 7953dec9fcdSqs148142 return (HXGE_OK); 7963dec9fcdSqs148142 } 7973dec9fcdSqs148142 7983dec9fcdSqs148142 hxge_status_t 7993dec9fcdSqs148142 hxge_intr_mask_mgmt_set(p_hxge_t hxgep, boolean_t on) 8003dec9fcdSqs148142 { 8013dec9fcdSqs148142 p_hxge_ldgv_t ldgvp; 8023dec9fcdSqs148142 p_hxge_ldg_t ldgp; 8033dec9fcdSqs148142 p_hxge_ldv_t ldvp; 8043dec9fcdSqs148142 hpi_handle_t handle; 8053dec9fcdSqs148142 int i, j; 8063dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 8073dec9fcdSqs148142 8083dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 8093dec9fcdSqs148142 "==> hxge_intr_mask_mgmt_set (%d)", on)); 8103dec9fcdSqs148142 8113dec9fcdSqs148142 if ((ldgvp = hxgep->ldgvp) == NULL) { 8123dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 8133dec9fcdSqs148142 "==> hxge_intr_mask_mgmt_set: Null ldgvp")); 8143dec9fcdSqs148142 return (HXGE_ERROR); 8153dec9fcdSqs148142 } 8163dec9fcdSqs148142 handle = HXGE_DEV_HPI_HANDLE(hxgep); 8173dec9fcdSqs148142 ldgp = ldgvp->ldgp; 8183dec9fcdSqs148142 ldvp = ldgvp->ldvp; 8193dec9fcdSqs148142 if (ldgp == NULL || ldvp == NULL) { 8203dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 8213dec9fcdSqs148142 "<== hxge_intr_mask_mgmt_set: Null ldgp or ldvp")); 8223dec9fcdSqs148142 return (HXGE_ERROR); 8233dec9fcdSqs148142 } 8243dec9fcdSqs148142 8253dec9fcdSqs148142 /* set masks. */ 8263dec9fcdSqs148142 for (i = 0; i < ldgvp->ldg_intrs; i++, ldgp++) { 8273dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 8283dec9fcdSqs148142 "==> hxge_intr_mask_mgmt_set: flag %d ldg %d" 8293dec9fcdSqs148142 "set mask nldvs %d", on, ldgp->ldg, ldgp->nldvs)); 8303dec9fcdSqs148142 for (j = 0; j < ldgp->nldvs; j++, ldvp++) { 8313dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 8323dec9fcdSqs148142 "==> hxge_intr_mask_mgmt_set: " 8333dec9fcdSqs148142 "for %d %d flag %d", i, j, on)); 8343dec9fcdSqs148142 if (on) { 8353dec9fcdSqs148142 ldvp->ldv_ldf_masks = 0; 8363dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 8373dec9fcdSqs148142 "==> hxge_intr_mask_mgmt_set: " 8383dec9fcdSqs148142 "ON mask off")); 8393dec9fcdSqs148142 } else { 8403dec9fcdSqs148142 ldvp->ldv_ldf_masks = (uint8_t)LD_IM_MASK; 8413dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 8423dec9fcdSqs148142 "==> hxge_intr_mask_mgmt_set:mask on")); 8433dec9fcdSqs148142 } 8443dec9fcdSqs148142 8453dec9fcdSqs148142 rs = hpi_intr_mask_set(handle, ldvp->ldv, 8463dec9fcdSqs148142 ldvp->ldv_ldf_masks); 8473dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 8483dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 8493dec9fcdSqs148142 "==> hxge_intr_mask_mgmt_set: " 8503dec9fcdSqs148142 "set mask failed rs 0x%x ldv %d mask 0x%x", 8513dec9fcdSqs148142 rs, ldvp->ldv, ldvp->ldv_ldf_masks)); 8523dec9fcdSqs148142 return (HXGE_ERROR | rs); 8533dec9fcdSqs148142 } 8543dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 8553dec9fcdSqs148142 "==> hxge_intr_mask_mgmt_set: flag %d" 8563dec9fcdSqs148142 "set mask OK ldv %d mask 0x%x", 8573dec9fcdSqs148142 on, ldvp->ldv, ldvp->ldv_ldf_masks)); 8583dec9fcdSqs148142 } 8593dec9fcdSqs148142 } 8603dec9fcdSqs148142 8613dec9fcdSqs148142 ldgp = ldgvp->ldgp; 8623dec9fcdSqs148142 /* set the arm bit */ 8633dec9fcdSqs148142 for (i = 0; i < hxgep->ldgvp->ldg_intrs; i++, ldgp++) { 8643dec9fcdSqs148142 if (on && !ldgp->arm) { 8653dec9fcdSqs148142 ldgp->arm = B_TRUE; 8663dec9fcdSqs148142 } else if (!on && ldgp->arm) { 8673dec9fcdSqs148142 ldgp->arm = B_FALSE; 8683dec9fcdSqs148142 } 8693dec9fcdSqs148142 rs = hpi_intr_ldg_mgmt_set(handle, ldgp->ldg, 8703dec9fcdSqs148142 ldgp->arm, ldgp->ldg_timer); 8713dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 8723dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 8733dec9fcdSqs148142 "<== hxge_intr_mask_mgmt_set: " 8743dec9fcdSqs148142 "set timer failed rs 0x%x ldg %d timer 0x%x", 8753dec9fcdSqs148142 rs, ldgp->ldg, ldgp->ldg_timer)); 8763dec9fcdSqs148142 return (HXGE_ERROR | rs); 8773dec9fcdSqs148142 } 8783dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, 8793dec9fcdSqs148142 "==> hxge_intr_mask_mgmt_set: OK (flag %d) " 8803dec9fcdSqs148142 "set timer ldg %d timer 0x%x", 8813dec9fcdSqs148142 on, ldgp->ldg, ldgp->ldg_timer)); 8823dec9fcdSqs148142 } 8833dec9fcdSqs148142 8843dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intr_mask_mgmt_set")); 8853dec9fcdSqs148142 return (HXGE_OK); 8863dec9fcdSqs148142 } 8873dec9fcdSqs148142 8883dec9fcdSqs148142 /* 8893dec9fcdSqs148142 * For Big Endian systems, the mac address will be from OBP. For Little 8903dec9fcdSqs148142 * Endian (x64) systems, it will be retrieved from the card since it cannot 8913dec9fcdSqs148142 * be programmed into PXE. 8923dec9fcdSqs148142 * This function also populates the MMAC parameters. 8933dec9fcdSqs148142 */ 8943dec9fcdSqs148142 static hxge_status_t 8953dec9fcdSqs148142 hxge_get_mac_addr_properties(p_hxge_t hxgep) 8963dec9fcdSqs148142 { 8973dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_get_mac_addr_properties ")); 8983dec9fcdSqs148142 8993dec9fcdSqs148142 (void) hxge_pfc_mac_addrs_get(hxgep); 9003dec9fcdSqs148142 hxgep->ouraddr = hxgep->factaddr; 9013dec9fcdSqs148142 9023dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_get_mac_addr_properties ")); 9033dec9fcdSqs148142 return (HXGE_OK); 9043dec9fcdSqs148142 } 9053dec9fcdSqs148142 9063dec9fcdSqs148142 static void 9073dec9fcdSqs148142 hxge_ldgv_setup(p_hxge_ldg_t *ldgp, p_hxge_ldv_t *ldvp, uint8_t ldv, 9083dec9fcdSqs148142 uint8_t endldg, int *ngrps) 9093dec9fcdSqs148142 { 9103dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, INT_CTL, "==> hxge_ldgv_setup")); 9113dec9fcdSqs148142 /* Assign the group number for each device. */ 9123dec9fcdSqs148142 (*ldvp)->ldg_assigned = (*ldgp)->ldg; 9133dec9fcdSqs148142 (*ldvp)->ldgp = *ldgp; 9143dec9fcdSqs148142 (*ldvp)->ldv = ldv; 9153dec9fcdSqs148142 9163dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, INT_CTL, 9173dec9fcdSqs148142 "==> hxge_ldgv_setup: ldv %d endldg %d ldg %d, ldvp $%p", 9183dec9fcdSqs148142 ldv, endldg, (*ldgp)->ldg, (*ldgp)->ldvp)); 9193dec9fcdSqs148142 9203dec9fcdSqs148142 (*ldgp)->nldvs++; 9213dec9fcdSqs148142 if ((*ldgp)->ldg == (endldg - 1)) { 9223dec9fcdSqs148142 if ((*ldgp)->ldvp == NULL) { 9233dec9fcdSqs148142 (*ldgp)->ldvp = *ldvp; 9243dec9fcdSqs148142 *ngrps += 1; 9253dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, INT_CTL, 9263dec9fcdSqs148142 "==> hxge_ldgv_setup: ngrps %d", *ngrps)); 9273dec9fcdSqs148142 } 9283dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, INT_CTL, 9293dec9fcdSqs148142 "==> hxge_ldgv_setup: ldvp $%p ngrps %d", 9303dec9fcdSqs148142 *ldvp, *ngrps)); 9313dec9fcdSqs148142 ++*ldvp; 9323dec9fcdSqs148142 } else { 9333dec9fcdSqs148142 (*ldgp)->ldvp = *ldvp; 9343dec9fcdSqs148142 *ngrps += 1; 9353dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, INT_CTL, "==> hxge_ldgv_setup(done): " 9363dec9fcdSqs148142 "ldv %d endldg %d ldg %d, ldvp $%p", 9373dec9fcdSqs148142 ldv, endldg, (*ldgp)->ldg, (*ldgp)->ldvp)); 938*2bc98732SRichard Lowe ++*ldvp; 939*2bc98732SRichard Lowe ++*ldgp; 9403dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, INT_CTL, 9413dec9fcdSqs148142 "==> hxge_ldgv_setup: new ngrps %d", *ngrps)); 9423dec9fcdSqs148142 } 9433dec9fcdSqs148142 9443dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, INT_CTL, "==> hxge_ldgv_setup: " 9453dec9fcdSqs148142 "ldg %d nldvs %d ldv %d ldvp $%p endldg %d ngrps %d", 9463dec9fcdSqs148142 (*ldgp)->ldg, (*ldgp)->nldvs, ldv, ldvp, endldg, *ngrps)); 9473dec9fcdSqs148142 9483dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, INT_CTL, "<== hxge_ldgv_setup")); 9493dec9fcdSqs148142 } 950