xref: /onnv-gate/usr/src/uts/common/io/hxge/hxge_virtual.c (revision 8275:7c223a798022)
16349Sqs148142 /*
26349Sqs148142  * CDDL HEADER START
36349Sqs148142  *
46349Sqs148142  * The contents of this file are subject to the terms of the
56349Sqs148142  * Common Development and Distribution License (the "License").
66349Sqs148142  * You may not use this file except in compliance with the License.
76349Sqs148142  *
86349Sqs148142  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96349Sqs148142  * or http://www.opensolaris.org/os/licensing.
106349Sqs148142  * See the License for the specific language governing permissions
116349Sqs148142  * and limitations under the License.
126349Sqs148142  *
136349Sqs148142  * When distributing Covered Code, include this CDDL HEADER in each
146349Sqs148142  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156349Sqs148142  * If applicable, add the following below this CDDL HEADER, with the
166349Sqs148142  * fields enclosed by brackets "[]" replaced with your own identifying
176349Sqs148142  * information: Portions Copyright [yyyy] [name of copyright owner]
186349Sqs148142  *
196349Sqs148142  * CDDL HEADER END
206349Sqs148142  */
216349Sqs148142 /*
226349Sqs148142  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
236349Sqs148142  * Use is subject to license terms.
246349Sqs148142  */
256349Sqs148142 
266349Sqs148142 #include <hxge_impl.h>
276349Sqs148142 #include <hxge_vmac.h>
286349Sqs148142 #include <hxge_pfc.h>
296349Sqs148142 #include <hpi_pfc.h>
306349Sqs148142 
316349Sqs148142 static hxge_status_t hxge_get_mac_addr_properties(p_hxge_t);
326349Sqs148142 static void hxge_use_cfg_hydra_properties(p_hxge_t);
336349Sqs148142 static void hxge_use_cfg_dma_config(p_hxge_t);
346349Sqs148142 static void hxge_use_cfg_class_config(p_hxge_t);
356349Sqs148142 static void hxge_set_hw_dma_config(p_hxge_t);
366349Sqs148142 static void hxge_set_hw_class_config(p_hxge_t);
376349Sqs148142 static void hxge_ldgv_setup(p_hxge_ldg_t *ldgp, p_hxge_ldv_t *ldvp, uint8_t ldv,
386349Sqs148142 	uint8_t endldg, int *ngrps);
396349Sqs148142 
406349Sqs148142 extern uint16_t hxge_rcr_timeout;
416349Sqs148142 extern uint16_t hxge_rcr_threshold;
426349Sqs148142 
436349Sqs148142 extern uint32_t hxge_rbr_size;
446349Sqs148142 extern uint32_t hxge_rcr_size;
456349Sqs148142 
466349Sqs148142 extern uint_t hxge_rx_intr();
476349Sqs148142 extern uint_t hxge_tx_intr();
486349Sqs148142 extern uint_t hxge_vmac_intr();
496349Sqs148142 extern uint_t hxge_syserr_intr();
506349Sqs148142 extern uint_t hxge_pfc_intr();
516349Sqs148142 
526349Sqs148142 /*
536349Sqs148142  * Entry point to populate configuration parameters into the master hxge
546349Sqs148142  * data structure and to update the NDD parameter list.
556349Sqs148142  */
566349Sqs148142 hxge_status_t
hxge_get_config_properties(p_hxge_t hxgep)576349Sqs148142 hxge_get_config_properties(p_hxge_t hxgep)
586349Sqs148142 {
596349Sqs148142 	hxge_status_t		status = HXGE_OK;
606349Sqs148142 
616349Sqs148142 	HXGE_DEBUG_MSG((hxgep, VPD_CTL, " ==> hxge_get_config_properties"));
626349Sqs148142 
636349Sqs148142 	if (hxgep->hxge_hw_p == NULL) {
646349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
656349Sqs148142 		    " hxge_get_config_properties: common hardware not set"));
666349Sqs148142 		return (HXGE_ERROR);
676349Sqs148142 	}
686349Sqs148142 
696349Sqs148142 	hxgep->classifier.tcam_size = TCAM_HXGE_TCAM_MAX_ENTRY;
706349Sqs148142 
716349Sqs148142 	status = hxge_get_mac_addr_properties(hxgep);
726349Sqs148142 	if (status != HXGE_OK) {
736349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
746349Sqs148142 		    " hxge_get_config_properties: mac addr properties failed"));
756349Sqs148142 		return (status);
766349Sqs148142 	}
776349Sqs148142 
786349Sqs148142 	HXGE_DEBUG_MSG((hxgep, VPD_CTL,
796349Sqs148142 	    " ==> hxge_get_config_properties: Hydra"));
806349Sqs148142 
816349Sqs148142 	hxge_use_cfg_hydra_properties(hxgep);
826349Sqs148142 
836349Sqs148142 	HXGE_DEBUG_MSG((hxgep, VPD_CTL, " <== hxge_get_config_properties"));
846349Sqs148142 	return (HXGE_OK);
856349Sqs148142 }
866349Sqs148142 
876349Sqs148142 
886349Sqs148142 static void
hxge_set_hw_vlan_class_config(p_hxge_t hxgep)896349Sqs148142 hxge_set_hw_vlan_class_config(p_hxge_t hxgep)
906349Sqs148142 {
916349Sqs148142 	int			i;
926349Sqs148142 	p_hxge_param_t		param_arr;
936349Sqs148142 	uint_t			vlan_cnt;
946349Sqs148142 	int			*vlan_cfg_val;
956349Sqs148142 	hxge_param_map_t	*vmap;
966349Sqs148142 	char			*prop;
976349Sqs148142 	p_hxge_class_pt_cfg_t 	p_class_cfgp;
986349Sqs148142 	uint32_t		good_cfg[32];
996349Sqs148142 	int			good_count = 0;
1006349Sqs148142 	hxge_mv_cfg_t		*vlan_tbl;
1016349Sqs148142 
1026349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_set_hw_vlan_config"));
1036349Sqs148142 	p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
1046349Sqs148142 
1056349Sqs148142 	param_arr = hxgep->param_arr;
1066349Sqs148142 	prop = param_arr[param_vlan_ids].fcode_name;
1076349Sqs148142 
1086349Sqs148142 	/*
1096349Sqs148142 	 * uint32_t array, each array entry specifying a VLAN id
1106349Sqs148142 	 */
1116349Sqs148142 	for (i = 0; i <= VLAN_ID_MAX; i++) {
1126349Sqs148142 		p_class_cfgp->vlan_tbl[i].flag = 0;
1136349Sqs148142 	}
1146349Sqs148142 
1156349Sqs148142 	vlan_tbl = (hxge_mv_cfg_t *)&p_class_cfgp->vlan_tbl[0];
1166349Sqs148142 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0, prop,
1176349Sqs148142 	    &vlan_cfg_val, &vlan_cnt) != DDI_PROP_SUCCESS) {
1186349Sqs148142 		return;
1196349Sqs148142 	}
1206349Sqs148142 
1216349Sqs148142 	for (i = 0; i < vlan_cnt; i++) {
1226349Sqs148142 		vmap = (hxge_param_map_t *)&vlan_cfg_val[i];
1236349Sqs148142 		if ((vmap->param_id) && (vmap->param_id <= VLAN_ID_MAX)) {
1246349Sqs148142 			HXGE_DEBUG_MSG((hxgep, CFG2_CTL,
1256349Sqs148142 			    " hxge_vlan_config vlan id %d", vmap->param_id));
1266349Sqs148142 
1276349Sqs148142 			good_cfg[good_count] = vlan_cfg_val[i];
1286349Sqs148142 			if (vlan_tbl[vmap->param_id].flag == 0)
1296349Sqs148142 				good_count++;
1306349Sqs148142 
1316349Sqs148142 			vlan_tbl[vmap->param_id].flag = 1;
1326349Sqs148142 		}
1336349Sqs148142 	}
1346349Sqs148142 
1356349Sqs148142 	ddi_prop_free(vlan_cfg_val);
1366349Sqs148142 	if (good_count != vlan_cnt) {
1376349Sqs148142 		(void) ddi_prop_update_int_array(DDI_DEV_T_NONE,
1386349Sqs148142 		    hxgep->dip, prop, (int *)good_cfg, good_count);
1396349Sqs148142 	}
1406349Sqs148142 
1416349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_set_hw_vlan_config"));
1426349Sqs148142 }
1436349Sqs148142 
1446349Sqs148142 
1456349Sqs148142 /*
1466349Sqs148142  * Read param_vlan_ids and param_implicit_vlan_id properties from either
1476349Sqs148142  * hxge.conf or OBP. Update the soft properties. Populate these
1486349Sqs148142  * properties into the hxge data structure.
1496349Sqs148142  */
1506349Sqs148142 static void
hxge_use_cfg_vlan_class_config(p_hxge_t hxgep)1516349Sqs148142 hxge_use_cfg_vlan_class_config(p_hxge_t hxgep)
1526349Sqs148142 {
1536349Sqs148142 	uint_t		vlan_cnt;
1546349Sqs148142 	int		*vlan_cfg_val;
1556349Sqs148142 	int		status;
1566349Sqs148142 	p_hxge_param_t	param_arr;
1576349Sqs148142 	char		*prop;
1586349Sqs148142 	uint32_t	implicit_vlan_id = 0;
1596349Sqs148142 	int		*int_prop_val;
1606349Sqs148142 	uint_t		prop_len;
1616349Sqs148142 	p_hxge_param_t	pa;
1626349Sqs148142 
1636349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_use_cfg_vlan_config"));
1646349Sqs148142 	param_arr = hxgep->param_arr;
1656349Sqs148142 	prop = param_arr[param_vlan_ids].fcode_name;
1666349Sqs148142 
1676349Sqs148142 	status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0, prop,
1686349Sqs148142 	    &vlan_cfg_val, &vlan_cnt);
1696349Sqs148142 	if (status == DDI_PROP_SUCCESS) {
1706349Sqs148142 		status = ddi_prop_update_int_array(DDI_DEV_T_NONE,
1716349Sqs148142 		    hxgep->dip, prop, vlan_cfg_val, vlan_cnt);
1726349Sqs148142 		ddi_prop_free(vlan_cfg_val);
1736349Sqs148142 	}
1746349Sqs148142 
1756349Sqs148142 	pa = &param_arr[param_implicit_vlan_id];
1766349Sqs148142 	prop = pa->fcode_name;
1776349Sqs148142 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0, prop,
1786349Sqs148142 	    &int_prop_val, &prop_len) == DDI_PROP_SUCCESS) {
1796349Sqs148142 		implicit_vlan_id = (uint32_t)*int_prop_val;
1806349Sqs148142 		if ((implicit_vlan_id >= pa->minimum) ||
1816349Sqs148142 		    (implicit_vlan_id <= pa->maximum)) {
1826349Sqs148142 			status = ddi_prop_update_int(DDI_DEV_T_NONE, hxgep->dip,
1836349Sqs148142 			    prop, (int)implicit_vlan_id);
1846349Sqs148142 		}
1856349Sqs148142 		ddi_prop_free(int_prop_val);
1866349Sqs148142 	}
1876349Sqs148142 
1886349Sqs148142 	hxge_set_hw_vlan_class_config(hxgep);
1896349Sqs148142 
1906349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_use_cfg_vlan_config"));
1916349Sqs148142 }
1926349Sqs148142 
1936349Sqs148142 /*
1946349Sqs148142  * Read in the configuration parameters from either hxge.conf or OBP and
1956349Sqs148142  * populate the master data structure hxge.
1966349Sqs148142  * Use these parameters to update the soft properties and the ndd array.
1976349Sqs148142  */
1986349Sqs148142 static void
hxge_use_cfg_hydra_properties(p_hxge_t hxgep)1996349Sqs148142 hxge_use_cfg_hydra_properties(p_hxge_t hxgep)
2006349Sqs148142 {
2016349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_use_cfg_hydra_properties"));
2026349Sqs148142 
2036349Sqs148142 	(void) hxge_use_cfg_dma_config(hxgep);
2046349Sqs148142 	(void) hxge_use_cfg_vlan_class_config(hxgep);
2056349Sqs148142 	(void) hxge_use_cfg_class_config(hxgep);
2066349Sqs148142 
2076349Sqs148142 	/*
2086349Sqs148142 	 * Read in the hardware (fcode) properties and use these properties
2096349Sqs148142 	 * to update the ndd array.
2106349Sqs148142 	 */
2116349Sqs148142 	(void) hxge_get_param_soft_properties(hxgep);
2126349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_use_cfg_hydra_properties"));
2136349Sqs148142 }
2146349Sqs148142 
2156349Sqs148142 
2166349Sqs148142 /*
2176349Sqs148142  * Read param_accept_jumbo, param_rxdma_intr_time, and param_rxdma_intr_pkts
2186349Sqs148142  * from either hxge.conf or OBP.
2196349Sqs148142  * Update the soft properties.
2206349Sqs148142  * Populate these properties into the hxge data structure for latter use.
2216349Sqs148142  */
2226349Sqs148142 static void
hxge_use_cfg_dma_config(p_hxge_t hxgep)2236349Sqs148142 hxge_use_cfg_dma_config(p_hxge_t hxgep)
2246349Sqs148142 {
2256349Sqs148142 	int			tx_ndmas, rx_ndmas;
2266349Sqs148142 	p_hxge_dma_pt_cfg_t	p_dma_cfgp;
2276349Sqs148142 	p_hxge_hw_pt_cfg_t	p_cfgp;
2286349Sqs148142 	dev_info_t		*dip;
2296349Sqs148142 	p_hxge_param_t		param_arr;
2306349Sqs148142 	char			*prop;
2316349Sqs148142 	int 			*prop_val;
2326349Sqs148142 	uint_t 			prop_len;
2336349Sqs148142 
2346349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_use_cfg_dma_config"));
2356349Sqs148142 	param_arr = hxgep->param_arr;
2366349Sqs148142 
2376349Sqs148142 	p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
2386349Sqs148142 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
2396349Sqs148142 	dip = hxgep->dip;
2406349Sqs148142 
2416349Sqs148142 	tx_ndmas = 4;
2426349Sqs148142 	p_cfgp->start_tdc = 0;
2436349Sqs148142 	p_cfgp->max_tdcs =  hxgep->max_tdcs = tx_ndmas;
2446349Sqs148142 	hxgep->tdc_mask = (tx_ndmas - 1);
2456349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, "==> hxge_use_cfg_dma_config: "
2466349Sqs148142 	    "p_cfgp 0x%llx max_tdcs %d hxgep->max_tdcs %d",
2476349Sqs148142 	    p_cfgp, p_cfgp->max_tdcs, hxgep->max_tdcs));
2486349Sqs148142 
2496349Sqs148142 	rx_ndmas = 4;
2506349Sqs148142 	p_cfgp->start_rdc = 0;
2516349Sqs148142 	p_cfgp->max_rdcs =  hxgep->max_rdcs = rx_ndmas;
2526349Sqs148142 
2536349Sqs148142 	p_cfgp->start_ldg = 0;
2546349Sqs148142 	p_cfgp->max_ldgs = HXGE_INT_MAX_LDG;
2556349Sqs148142 
2566349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, "==> hxge_use_default_dma_config: "
2576349Sqs148142 	    "p_cfgp 0x%llx max_rdcs %d hxgep->max_rdcs %d",
2586349Sqs148142 	    p_cfgp, p_cfgp->max_rdcs, hxgep->max_rdcs));
2596349Sqs148142 
2606349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, "==> hxge_use_cfg_dma_config: "
2616349Sqs148142 	    "p_cfgp 0x%016llx start_ldg %d hxgep->max_ldgs %d ",
2626349Sqs148142 	    p_cfgp, p_cfgp->start_ldg,  p_cfgp->max_ldgs));
2636349Sqs148142 
2646349Sqs148142 	/*
2656349Sqs148142 	 * add code for individual rdc properties
2666349Sqs148142 	 */
2676349Sqs148142 	prop = param_arr[param_accept_jumbo].fcode_name;
2686349Sqs148142 
2696349Sqs148142 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
2706349Sqs148142 	    &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
2716349Sqs148142 		if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) {
2726349Sqs148142 			(void) ddi_prop_update_int_array(DDI_DEV_T_NONE,
2736349Sqs148142 			    hxgep->dip, prop, prop_val, prop_len);
2746349Sqs148142 		}
2756349Sqs148142 		ddi_prop_free(prop_val);
2766349Sqs148142 	}
2776349Sqs148142 
2786349Sqs148142 	prop = param_arr[param_rxdma_intr_time].fcode_name;
2796349Sqs148142 
2806349Sqs148142 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
2816349Sqs148142 	    &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
2826349Sqs148142 		if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) {
2836349Sqs148142 			(void) ddi_prop_update_int_array(DDI_DEV_T_NONE,
2846349Sqs148142 			    hxgep->dip, prop, prop_val, prop_len);
2856349Sqs148142 		}
2866349Sqs148142 		ddi_prop_free(prop_val);
2876349Sqs148142 	}
2886349Sqs148142 
2896349Sqs148142 	prop = param_arr[param_rxdma_intr_pkts].fcode_name;
2906349Sqs148142 
2916349Sqs148142 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop,
2926349Sqs148142 	    &prop_val, &prop_len) == DDI_PROP_SUCCESS) {
2936349Sqs148142 		if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) {
2946349Sqs148142 			(void) ddi_prop_update_int_array(DDI_DEV_T_NONE,
2956349Sqs148142 			    hxgep->dip, prop, prop_val, prop_len);
2966349Sqs148142 		}
2976349Sqs148142 		ddi_prop_free(prop_val);
2986349Sqs148142 	}
2996349Sqs148142 
3006349Sqs148142 	hxge_set_hw_dma_config(hxgep);
3016349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, "<== hxge_use_cfg_dma_config"));
3026349Sqs148142 }
3036349Sqs148142 
3046349Sqs148142 static void
hxge_use_cfg_class_config(p_hxge_t hxgep)3056349Sqs148142 hxge_use_cfg_class_config(p_hxge_t hxgep)
3066349Sqs148142 {
3076349Sqs148142 	hxge_set_hw_class_config(hxgep);
3086349Sqs148142 }
3096349Sqs148142 
3106349Sqs148142 static void
hxge_set_hw_dma_config(p_hxge_t hxgep)3116349Sqs148142 hxge_set_hw_dma_config(p_hxge_t hxgep)
3126349Sqs148142 {
3136349Sqs148142 	p_hxge_dma_pt_cfg_t	p_dma_cfgp;
3146349Sqs148142 	p_hxge_hw_pt_cfg_t	p_cfgp;
3156349Sqs148142 
3166349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, "==> hxge_set_hw_dma_config"));
3176349Sqs148142 
3186349Sqs148142 	p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
3196349Sqs148142 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
3206349Sqs148142 
3216349Sqs148142 	/* Transmit DMA Channels */
3226349Sqs148142 	hxgep->ntdc = p_cfgp->max_tdcs;
3236349Sqs148142 
3246349Sqs148142 	/* Receive DMA Channels */
3256349Sqs148142 	hxgep->nrdc = p_cfgp->max_rdcs;
3266349Sqs148142 
3276349Sqs148142 	p_dma_cfgp->rbr_size = hxge_rbr_size;
3287618SMichael.Speer@Sun.COM 	if (hxge_rcr_size > HXGE_RCR_MAX)
3297618SMichael.Speer@Sun.COM 		hxge_rcr_size = HXGE_RCR_MAX;
3306349Sqs148142 	p_dma_cfgp->rcr_size = hxge_rcr_size;
3316349Sqs148142 
3326349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_set_hw_dma_config"));
3336349Sqs148142 }
3346349Sqs148142 
3356349Sqs148142 
3366349Sqs148142 boolean_t
hxge_check_rxdma_port_member(p_hxge_t hxgep,uint8_t rdc)3376349Sqs148142 hxge_check_rxdma_port_member(p_hxge_t hxgep, uint8_t rdc)
3386349Sqs148142 {
3396349Sqs148142 	p_hxge_dma_pt_cfg_t	p_dma_cfgp;
3406349Sqs148142 	p_hxge_hw_pt_cfg_t	p_cfgp;
3416349Sqs148142 	int			status = B_TRUE;
3426349Sqs148142 
3436349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG2_CTL, "==> hxge_check_rxdma_port_member"));
3446349Sqs148142 
3456349Sqs148142 	p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
3466349Sqs148142 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
3476349Sqs148142 
3486349Sqs148142 	/* Receive DMA Channels */
3496349Sqs148142 	if (rdc < p_cfgp->max_rdcs)
3506349Sqs148142 		status = B_TRUE;
3516349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG2_CTL, " <== hxge_check_rxdma_port_member"));
3526349Sqs148142 
3536349Sqs148142 	return (status);
3546349Sqs148142 }
3556349Sqs148142 
3566349Sqs148142 boolean_t
hxge_check_txdma_port_member(p_hxge_t hxgep,uint8_t tdc)3576349Sqs148142 hxge_check_txdma_port_member(p_hxge_t hxgep, uint8_t tdc)
3586349Sqs148142 {
3596349Sqs148142 	p_hxge_dma_pt_cfg_t	p_dma_cfgp;
3606349Sqs148142 	p_hxge_hw_pt_cfg_t	p_cfgp;
3616349Sqs148142 	int			status = B_FALSE;
3626349Sqs148142 
3636349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG2_CTL, "==> hxge_check_txdma_port_member"));
3646349Sqs148142 
3656349Sqs148142 	p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
3666349Sqs148142 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
3676349Sqs148142 
3686349Sqs148142 	/* Receive DMA Channels */
3696349Sqs148142 	if (tdc < p_cfgp->max_tdcs)
3706349Sqs148142 		status = B_TRUE;
3716349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG2_CTL, " <== hxge_check_txdma_port_member"));
3726349Sqs148142 
3736349Sqs148142 	return (status);
3746349Sqs148142 }
3756349Sqs148142 
3766349Sqs148142 
3776349Sqs148142 /*
3786349Sqs148142  * Read the L2 classes, L3 classes, and initial hash from either hxge.conf
3796349Sqs148142  * or OBP. Populate these properties into the hxge data structure for latter
3806349Sqs148142  * use. Note that we are not updating these soft properties.
3816349Sqs148142  */
3826349Sqs148142 static void
hxge_set_hw_class_config(p_hxge_t hxgep)3836349Sqs148142 hxge_set_hw_class_config(p_hxge_t hxgep)
3846349Sqs148142 {
3856349Sqs148142 	int			i, j;
3866349Sqs148142 	p_hxge_param_t		param_arr;
3876349Sqs148142 	int			*int_prop_val;
3886349Sqs148142 	uint32_t		cfg_value;
3896349Sqs148142 	char			*prop;
3906349Sqs148142 	p_hxge_class_pt_cfg_t	p_class_cfgp;
3916349Sqs148142 	int			start_prop, end_prop;
3926349Sqs148142 	uint_t			prop_cnt;
3936349Sqs148142 
3946349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, " ==> hxge_set_hw_class_config"));
3956349Sqs148142 
3966349Sqs148142 	p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
3976349Sqs148142 
3986349Sqs148142 	param_arr = hxgep->param_arr;
3996349Sqs148142 
4006349Sqs148142 	/*
4016349Sqs148142 	 * L2 class configuration. User configurable ether types
4026349Sqs148142 	 */
4036349Sqs148142 	start_prop =  param_class_cfg_ether_usr1;
4046349Sqs148142 	end_prop = param_class_cfg_ether_usr2;
4056349Sqs148142 
4066349Sqs148142 	for (i = start_prop; i <= end_prop; i++) {
4076349Sqs148142 		prop = param_arr[i].fcode_name;
4086349Sqs148142 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip,
4096349Sqs148142 		    0, prop, &int_prop_val, &prop_cnt) == DDI_PROP_SUCCESS) {
4106349Sqs148142 			cfg_value =  (uint32_t)*int_prop_val;
4116349Sqs148142 			ddi_prop_free(int_prop_val);
4126349Sqs148142 		} else {
4136349Sqs148142 			cfg_value = (uint32_t)param_arr[i].value;
4146349Sqs148142 		}
4156349Sqs148142 
4166349Sqs148142 		j = (i - start_prop) + TCAM_CLASS_ETYPE_1;
4176349Sqs148142 		p_class_cfgp->class_cfg[j] = cfg_value;
4186349Sqs148142 	}
4196349Sqs148142 
4206349Sqs148142 	/*
4216349Sqs148142 	 * Use properties from either .conf or the NDD param array. Only bits
4226349Sqs148142 	 * 2 and 3 are significant
4236349Sqs148142 	 */
4246349Sqs148142 	start_prop =  param_class_opt_ipv4_tcp;
4256349Sqs148142 	end_prop = param_class_opt_ipv6_sctp;
4266349Sqs148142 
4276349Sqs148142 	for (i = start_prop; i <= end_prop; i++) {
4286349Sqs148142 		prop = param_arr[i].fcode_name;
4296349Sqs148142 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip,
4306349Sqs148142 		    0, prop, &int_prop_val, &prop_cnt) == DDI_PROP_SUCCESS) {
4316349Sqs148142 			cfg_value =  (uint32_t)*int_prop_val;
4326349Sqs148142 			ddi_prop_free(int_prop_val);
4336349Sqs148142 		} else {
4346349Sqs148142 			cfg_value = (uint32_t)param_arr[i].value;
4356349Sqs148142 		}
4366349Sqs148142 
4376349Sqs148142 		j = (i - start_prop) + TCAM_CLASS_TCP_IPV4;
4386349Sqs148142 		p_class_cfgp->class_cfg[j] = cfg_value;
4396349Sqs148142 	}
4406349Sqs148142 
4416349Sqs148142 	prop = param_arr[param_hash_init_value].fcode_name;
4426349Sqs148142 
4436349Sqs148142 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hxgep->dip, 0, prop,
4446349Sqs148142 	    &int_prop_val, &prop_cnt) == DDI_PROP_SUCCESS) {
4456349Sqs148142 		cfg_value =  (uint32_t)*int_prop_val;
4466349Sqs148142 		ddi_prop_free(int_prop_val);
4476349Sqs148142 	} else {
4486349Sqs148142 		cfg_value = (uint32_t)param_arr[param_hash_init_value].value;
4496349Sqs148142 	}
4506349Sqs148142 
4516349Sqs148142 	p_class_cfgp->init_hash = (uint32_t)cfg_value;
4526349Sqs148142 
4536349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, " <== hxge_set_hw_class_config"));
4546349Sqs148142 }
4556349Sqs148142 
4566349Sqs148142 
4576349Sqs148142 /*
4586349Sqs148142  * Interrupts related interface functions.
4596349Sqs148142  */
4606349Sqs148142 hxge_status_t
hxge_ldgv_init(p_hxge_t hxgep,int * navail_p,int * nrequired_p)4616349Sqs148142 hxge_ldgv_init(p_hxge_t hxgep, int *navail_p, int *nrequired_p)
4626349Sqs148142 {
4636349Sqs148142 	uint8_t			ldv, i, maxldvs, maxldgs, start, end, nldvs;
4646349Sqs148142 	int			ldg, endldg, ngrps;
4656349Sqs148142 	uint8_t			channel;
4666349Sqs148142 	p_hxge_dma_pt_cfg_t	p_dma_cfgp;
4676349Sqs148142 	p_hxge_hw_pt_cfg_t	p_cfgp;
4686349Sqs148142 	p_hxge_ldgv_t		ldgvp;
4696349Sqs148142 	p_hxge_ldg_t		ldgp, ptr;
4706349Sqs148142 	p_hxge_ldv_t		ldvp;
4716349Sqs148142 	hxge_status_t		status = HXGE_OK;
472*7949SQiyan.Sun@Sun.COM 	peu_intr_mask_t		parity_err_mask;
4736349Sqs148142 
4746349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_ldgv_init"));
4756349Sqs148142 	if (!*navail_p) {
4766349Sqs148142 		*nrequired_p = 0;
4776349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
4786349Sqs148142 		    "<== hxge_ldgv_init:no avail"));
4796349Sqs148142 		return (HXGE_ERROR);
4806349Sqs148142 	}
4816349Sqs148142 	p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
4826349Sqs148142 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
4836349Sqs148142 
4846349Sqs148142 	/* each DMA channels */
4856349Sqs148142 	nldvs = p_cfgp->max_tdcs + p_cfgp->max_rdcs;
4866349Sqs148142 
4876349Sqs148142 	/* vmac */
4886349Sqs148142 	nldvs++;
4896349Sqs148142 
4906349Sqs148142 	/* pfc */
4916349Sqs148142 	nldvs++;
4926349Sqs148142 
4936349Sqs148142 	/* system error interrupts. */
4946349Sqs148142 	nldvs++;
4956349Sqs148142 
4966349Sqs148142 	maxldvs = nldvs;
4976349Sqs148142 	maxldgs = p_cfgp->max_ldgs;
4986349Sqs148142 
4996349Sqs148142 	if (!maxldvs || !maxldgs) {
5006349Sqs148142 		/* No devices configured. */
5016349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_ldgv_init: "
5026349Sqs148142 		    "no logical devices or groups configured."));
5036349Sqs148142 		return (HXGE_ERROR);
5046349Sqs148142 	}
5056349Sqs148142 	ldgvp = hxgep->ldgvp;
5066349Sqs148142 	if (ldgvp == NULL) {
5076349Sqs148142 		ldgvp = KMEM_ZALLOC(sizeof (hxge_ldgv_t), KM_SLEEP);
5086349Sqs148142 		hxgep->ldgvp = ldgvp;
5096349Sqs148142 		ldgvp->maxldgs = maxldgs;
5106349Sqs148142 		ldgvp->maxldvs = maxldvs;
5116349Sqs148142 		ldgp = ldgvp->ldgp =
5126349Sqs148142 		    KMEM_ZALLOC(sizeof (hxge_ldg_t) * maxldgs, KM_SLEEP);
5136349Sqs148142 		ldvp = ldgvp->ldvp =
5146349Sqs148142 		    KMEM_ZALLOC(sizeof (hxge_ldv_t) * maxldvs, KM_SLEEP);
5156349Sqs148142 	}
5166349Sqs148142 
5176349Sqs148142 	ldgvp->ndma_ldvs = p_cfgp->max_tdcs + p_cfgp->max_rdcs;
5186349Sqs148142 	ldgvp->tmres = HXGE_TIMER_RESO;
5196349Sqs148142 
5206349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
5216349Sqs148142 	    "==> hxge_ldgv_init: maxldvs %d maxldgs %d nldvs %d",
5226349Sqs148142 	    maxldvs, maxldgs, nldvs));
5236349Sqs148142 
5246349Sqs148142 	ldg = p_cfgp->start_ldg;
5256349Sqs148142 	ptr = ldgp;
5266349Sqs148142 	for (i = 0; i < maxldgs; i++) {
5276349Sqs148142 		ptr->arm = B_TRUE;
5286349Sqs148142 		ptr->vldg_index = i;
5296349Sqs148142 		ptr->ldg_timer = HXGE_TIMER_LDG;
5306349Sqs148142 		ptr->ldg = ldg++;
5316349Sqs148142 		ptr->sys_intr_handler = hxge_intr;
5326349Sqs148142 		ptr->nldvs = 0;
5336349Sqs148142 		ptr->hxgep = hxgep;
5346349Sqs148142 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
5356349Sqs148142 		    "==> hxge_ldgv_init: maxldvs %d maxldgs %d ldg %d",
5366349Sqs148142 		    maxldvs, maxldgs, ptr->ldg));
5376349Sqs148142 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
5386349Sqs148142 		    "==> hxge_ldv_init: timer %d", ptr->ldg_timer));
5396349Sqs148142 		ptr++;
5406349Sqs148142 	}
5416349Sqs148142 
5426349Sqs148142 	ldg = p_cfgp->start_ldg;
5436349Sqs148142 	if (maxldgs > *navail_p) {
5446349Sqs148142 		ngrps = *navail_p;
5456349Sqs148142 	} else {
5466349Sqs148142 		ngrps = maxldgs;
5476349Sqs148142 	}
5486349Sqs148142 	endldg = ldg + ngrps;
5496349Sqs148142 
5506349Sqs148142 	/*
5516349Sqs148142 	 * Receive DMA channels.
5526349Sqs148142 	 */
5536349Sqs148142 	channel = p_cfgp->start_rdc;
5546349Sqs148142 	start = p_cfgp->start_rdc + HXGE_RDMA_LD_START;
5556349Sqs148142 	end = start + p_cfgp->max_rdcs;
5566349Sqs148142 	nldvs = 0;
5576349Sqs148142 	ldgvp->nldvs = 0;
5586349Sqs148142 	ldgp->ldvp = NULL;
5596349Sqs148142 	*nrequired_p = 0;
5606349Sqs148142 	ptr = ldgp;
5616349Sqs148142 
5626349Sqs148142 	/*
5636349Sqs148142 	 * Start with RDC to configure logical devices for each group.
5646349Sqs148142 	 */
5656349Sqs148142 	for (i = 0, ldv = start; ldv < end; i++, ldv++) {
5666349Sqs148142 		ldvp->is_rxdma = B_TRUE;
5676349Sqs148142 		ldvp->ldv = ldv;
5686349Sqs148142 
5696349Sqs148142 		/*
5706349Sqs148142 		 * If non-seq needs to change the following code
5716349Sqs148142 		 */
5726349Sqs148142 		ldvp->channel = channel++;
5736349Sqs148142 		ldvp->vdma_index = i;
5746349Sqs148142 		ldvp->ldv_intr_handler = hxge_rx_intr;
5756349Sqs148142 		ldvp->ldv_ldf_masks = 0;
5766349Sqs148142 		ldvp->use_timer = B_FALSE;
5776349Sqs148142 		ldvp->hxgep = hxgep;
5786349Sqs148142 		hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p);
5796349Sqs148142 		nldvs++;
5806349Sqs148142 	}
5816349Sqs148142 
5826349Sqs148142 	/*
5836349Sqs148142 	 * Transmit DMA channels.
5846349Sqs148142 	 */
5856349Sqs148142 	channel = p_cfgp->start_tdc;
5866349Sqs148142 	start = p_cfgp->start_tdc + HXGE_TDMA_LD_START;
5876349Sqs148142 	end = start + p_cfgp->max_tdcs;
5886349Sqs148142 	for (i = 0, ldv = start; ldv < end; i++, ldv++) {
5896349Sqs148142 		ldvp->is_txdma = B_TRUE;
5906349Sqs148142 		ldvp->ldv = ldv;
5916349Sqs148142 		ldvp->channel = channel++;
5926349Sqs148142 		ldvp->vdma_index = i;
5936349Sqs148142 		ldvp->ldv_intr_handler = hxge_tx_intr;
5946349Sqs148142 		ldvp->ldv_ldf_masks = 0;
5956349Sqs148142 		ldvp->use_timer = B_FALSE;
5966349Sqs148142 		ldvp->hxgep = hxgep;
5976349Sqs148142 		hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p);
5986349Sqs148142 		nldvs++;
5996349Sqs148142 	}
6006349Sqs148142 
6016349Sqs148142 	/*
6026349Sqs148142 	 * VMAC
6036349Sqs148142 	 */
6046349Sqs148142 	ldvp->is_vmac = B_TRUE;
6056349Sqs148142 	ldvp->ldv_intr_handler = hxge_vmac_intr;
6066349Sqs148142 	ldvp->ldv_ldf_masks = 0;
6076349Sqs148142 	ldv = HXGE_VMAC_LD;
6086349Sqs148142 	ldvp->ldv = ldv;
6096349Sqs148142 	ldvp->use_timer = B_FALSE;
6106349Sqs148142 	ldvp->hxgep = hxgep;
6116349Sqs148142 	hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p);
6126349Sqs148142 	nldvs++;
6136349Sqs148142 
6146349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
6156349Sqs148142 	    "==> hxge_ldgv_init: nldvs %d navail %d nrequired %d",
6166349Sqs148142 	    nldvs, *navail_p, *nrequired_p));
6176349Sqs148142 
6186349Sqs148142 	/*
6196349Sqs148142 	 * PFC
6206349Sqs148142 	 */
6216349Sqs148142 	ldvp->is_pfc = B_TRUE;
6226349Sqs148142 	ldvp->ldv_intr_handler = hxge_pfc_intr;
6236349Sqs148142 	ldvp->ldv_ldf_masks = 0;
6246349Sqs148142 	ldv = HXGE_PFC_LD;
6256349Sqs148142 	ldvp->ldv = ldv;
6266349Sqs148142 	ldvp->use_timer = B_FALSE;
6276349Sqs148142 	ldvp->hxgep = hxgep;
6286349Sqs148142 	hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p);
6296349Sqs148142 	nldvs++;
6306349Sqs148142 
6316349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
6326349Sqs148142 	    "==> hxge_ldgv_init: nldvs %d navail %d nrequired %d",
6336349Sqs148142 	    nldvs, *navail_p, *nrequired_p));
6346349Sqs148142 
6356349Sqs148142 	/*
6366349Sqs148142 	 * System error interrupts.
6376349Sqs148142 	 */
6386349Sqs148142 	ldv = HXGE_SYS_ERROR_LD;
6396349Sqs148142 	ldvp->ldv = ldv;
6406349Sqs148142 	ldvp->is_syserr = B_TRUE;
6416349Sqs148142 	ldvp->ldv_intr_handler = hxge_syserr_intr;
6426349Sqs148142 	ldvp->ldv_ldf_masks = 0;
6436349Sqs148142 	ldvp->hxgep = hxgep;
6446349Sqs148142 	ldvp->use_timer = B_FALSE;
6456349Sqs148142 	ldgvp->ldvp_syserr = ldvp;
6466349Sqs148142 
6476349Sqs148142 	/* Reset PEU error mask to allow PEU error interrupts */
648*7949SQiyan.Sun@Sun.COM 	/*
649*7949SQiyan.Sun@Sun.COM 	 * Keep the msix parity error mask here and remove it
650*7949SQiyan.Sun@Sun.COM 	 * after ddi_intr_enable call to avoid a msix par err
651*7949SQiyan.Sun@Sun.COM 	 */
652*7949SQiyan.Sun@Sun.COM 	parity_err_mask.value = 0;
653*7949SQiyan.Sun@Sun.COM 	parity_err_mask.bits.eic_msix_parerr_mask = 1;
654*7949SQiyan.Sun@Sun.COM 	HXGE_REG_WR32(hxgep->hpi_handle, PEU_INTR_MASK, parity_err_mask.value);
6556349Sqs148142 
6566349Sqs148142 	/*
6576349Sqs148142 	 * Unmask the system interrupt states.
6586349Sqs148142 	 */
6596349Sqs148142 	(void) hxge_fzc_sys_err_mask_set(hxgep, B_FALSE);
6606349Sqs148142 	(void) hxge_ldgv_setup(&ptr, &ldvp, ldv, endldg, nrequired_p);
6616349Sqs148142 	nldvs++;
6626349Sqs148142 
6636349Sqs148142 	ldgvp->ldg_intrs = *nrequired_p;
6646349Sqs148142 
6656349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
6666349Sqs148142 	    "==> hxge_ldgv_init: nldvs %d navail %d nrequired %d",
6676349Sqs148142 	    nldvs, *navail_p, *nrequired_p));
6686349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_ldgv_init"));
6696349Sqs148142 	return (status);
6706349Sqs148142 }
6716349Sqs148142 
6726349Sqs148142 hxge_status_t
hxge_ldgv_uninit(p_hxge_t hxgep)6736349Sqs148142 hxge_ldgv_uninit(p_hxge_t hxgep)
6746349Sqs148142 {
6756349Sqs148142 	p_hxge_ldgv_t		ldgvp;
6766349Sqs148142 
6776349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_ldgv_uninit"));
6786349Sqs148142 	ldgvp = hxgep->ldgvp;
6796349Sqs148142 	if (ldgvp == NULL) {
6806349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
6816349Sqs148142 		    "<== hxge_ldgv_uninit: no logical group configured."));
6826349Sqs148142 		return (HXGE_OK);
6836349Sqs148142 	}
6846349Sqs148142 
6856349Sqs148142 	if (ldgvp->ldgp) {
6866349Sqs148142 		KMEM_FREE(ldgvp->ldgp, sizeof (hxge_ldg_t) * ldgvp->maxldgs);
6876349Sqs148142 	}
6886349Sqs148142 	if (ldgvp->ldvp) {
6896349Sqs148142 		KMEM_FREE(ldgvp->ldvp, sizeof (hxge_ldv_t) * ldgvp->maxldvs);
6906349Sqs148142 	}
6916349Sqs148142 
6926349Sqs148142 	KMEM_FREE(ldgvp, sizeof (hxge_ldgv_t));
6936349Sqs148142 	hxgep->ldgvp = NULL;
6946349Sqs148142 
6956349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_ldgv_uninit"));
6966349Sqs148142 	return (HXGE_OK);
6976349Sqs148142 }
6986349Sqs148142 
6996349Sqs148142 hxge_status_t
hxge_intr_ldgv_init(p_hxge_t hxgep)7006349Sqs148142 hxge_intr_ldgv_init(p_hxge_t hxgep)
7016349Sqs148142 {
7026349Sqs148142 	hxge_status_t	status = HXGE_OK;
7036349Sqs148142 
7046349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intr_ldgv_init"));
7056349Sqs148142 	/*
7066349Sqs148142 	 * Configure the logical device group numbers, state vectors
7076349Sqs148142 	 * and interrupt masks for each logical device.
7086349Sqs148142 	 */
7096349Sqs148142 	status = hxge_fzc_intr_init(hxgep);
7106349Sqs148142 
7116349Sqs148142 	/*
7126349Sqs148142 	 * Configure logical device masks and timers.
7136349Sqs148142 	 */
7146349Sqs148142 	status = hxge_intr_mask_mgmt(hxgep);
7156349Sqs148142 
7166349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intr_ldgv_init"));
7176349Sqs148142 	return (status);
7186349Sqs148142 }
7196349Sqs148142 
7206349Sqs148142 hxge_status_t
hxge_intr_mask_mgmt(p_hxge_t hxgep)7216349Sqs148142 hxge_intr_mask_mgmt(p_hxge_t hxgep)
7226349Sqs148142 {
7236349Sqs148142 	p_hxge_ldgv_t	ldgvp;
7246349Sqs148142 	p_hxge_ldg_t	ldgp;
7256349Sqs148142 	p_hxge_ldv_t	ldvp;
7266349Sqs148142 	hpi_handle_t	handle;
7276349Sqs148142 	int		i, j;
7286349Sqs148142 	hpi_status_t	rs = HPI_SUCCESS;
7296349Sqs148142 
7306349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intr_mask_mgmt"));
7316349Sqs148142 
7326349Sqs148142 	if ((ldgvp = hxgep->ldgvp) == NULL) {
7336349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7346349Sqs148142 		    "<== hxge_intr_mask_mgmt: Null ldgvp"));
7356349Sqs148142 		return (HXGE_ERROR);
7366349Sqs148142 	}
7376349Sqs148142 	handle = HXGE_DEV_HPI_HANDLE(hxgep);
7386349Sqs148142 	ldgp = ldgvp->ldgp;
7396349Sqs148142 	ldvp = ldgvp->ldvp;
7406349Sqs148142 	if (ldgp == NULL || ldvp == NULL) {
7416349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7426349Sqs148142 		    "<== hxge_intr_mask_mgmt: Null ldgp or ldvp"));
7436349Sqs148142 		return (HXGE_ERROR);
7446349Sqs148142 	}
7456349Sqs148142 
7466349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
7476349Sqs148142 	    "==> hxge_intr_mask_mgmt: # of intrs %d ", ldgvp->ldg_intrs));
7486349Sqs148142 	/* Initialize masks. */
7496349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
7506349Sqs148142 	    "==> hxge_intr_mask_mgmt(Hydra): # intrs %d ", ldgvp->ldg_intrs));
7516349Sqs148142 	for (i = 0; i < ldgvp->ldg_intrs; i++, ldgp++) {
7526349Sqs148142 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
7536349Sqs148142 		    "==> hxge_intr_mask_mgmt(Hydra): # ldv %d in group %d",
7546349Sqs148142 		    ldgp->nldvs, ldgp->ldg));
7556349Sqs148142 		for (j = 0; j < ldgp->nldvs; j++, ldvp++) {
7566349Sqs148142 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
7576349Sqs148142 			    "==> hxge_intr_mask_mgmt: set ldv # %d "
7586349Sqs148142 			    "for ldg %d", ldvp->ldv, ldgp->ldg));
7596349Sqs148142 			rs = hpi_intr_mask_set(handle, ldvp->ldv,
7606349Sqs148142 			    ldvp->ldv_ldf_masks);
7616349Sqs148142 			if (rs != HPI_SUCCESS) {
7626349Sqs148142 				HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7636349Sqs148142 				    "<== hxge_intr_mask_mgmt: set mask failed "
7646349Sqs148142 				    " rs 0x%x ldv %d mask 0x%x",
7656349Sqs148142 				    rs, ldvp->ldv, ldvp->ldv_ldf_masks));
7666349Sqs148142 				return (HXGE_ERROR | rs);
7676349Sqs148142 			}
7686349Sqs148142 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
7696349Sqs148142 			    "==> hxge_intr_mask_mgmt: set mask OK "
7706349Sqs148142 			    " rs 0x%x ldv %d mask 0x%x",
7716349Sqs148142 			    rs, ldvp->ldv, ldvp->ldv_ldf_masks));
7726349Sqs148142 		}
7736349Sqs148142 	}
7746349Sqs148142 
7756349Sqs148142 	ldgp = ldgvp->ldgp;
7766349Sqs148142 	/* Configure timer and arm bit */
7776349Sqs148142 	for (i = 0; i < hxgep->ldgvp->ldg_intrs; i++, ldgp++) {
7786349Sqs148142 		rs = hpi_intr_ldg_mgmt_set(handle, ldgp->ldg,
7796349Sqs148142 		    ldgp->arm, ldgp->ldg_timer);
7806349Sqs148142 		if (rs != HPI_SUCCESS) {
7816349Sqs148142 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7826349Sqs148142 			    "<== hxge_intr_mask_mgmt: set timer failed "
7836349Sqs148142 			    " rs 0x%x dg %d timer 0x%x",
7846349Sqs148142 			    rs, ldgp->ldg, ldgp->ldg_timer));
7856349Sqs148142 			return (HXGE_ERROR | rs);
7866349Sqs148142 		}
7876349Sqs148142 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
7886349Sqs148142 		    "==> hxge_intr_mask_mgmt: set timer OK "
7896349Sqs148142 		    " rs 0x%x ldg %d timer 0x%x",
7906349Sqs148142 		    rs, ldgp->ldg, ldgp->ldg_timer));
7916349Sqs148142 	}
7926349Sqs148142 
7936349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_fzc_intr_mask_mgmt"));
7946349Sqs148142 	return (HXGE_OK);
7956349Sqs148142 }
7966349Sqs148142 
7976349Sqs148142 hxge_status_t
hxge_intr_mask_mgmt_set(p_hxge_t hxgep,boolean_t on)7986349Sqs148142 hxge_intr_mask_mgmt_set(p_hxge_t hxgep, boolean_t on)
7996349Sqs148142 {
8006349Sqs148142 	p_hxge_ldgv_t	ldgvp;
8016349Sqs148142 	p_hxge_ldg_t	ldgp;
8026349Sqs148142 	p_hxge_ldv_t	ldvp;
8036349Sqs148142 	hpi_handle_t	handle;
8046349Sqs148142 	int		i, j;
8056349Sqs148142 	hpi_status_t	rs = HPI_SUCCESS;
8066349Sqs148142 
8076349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL,
8086349Sqs148142 	    "==> hxge_intr_mask_mgmt_set (%d)", on));
8096349Sqs148142 
8106349Sqs148142 	if ((ldgvp = hxgep->ldgvp) == NULL) {
8116349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
8126349Sqs148142 		    "==> hxge_intr_mask_mgmt_set: Null ldgvp"));
8136349Sqs148142 		return (HXGE_ERROR);
8146349Sqs148142 	}
8156349Sqs148142 	handle = HXGE_DEV_HPI_HANDLE(hxgep);
8166349Sqs148142 	ldgp = ldgvp->ldgp;
8176349Sqs148142 	ldvp = ldgvp->ldvp;
8186349Sqs148142 	if (ldgp == NULL || ldvp == NULL) {
8196349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
8206349Sqs148142 		    "<== hxge_intr_mask_mgmt_set: Null ldgp or ldvp"));
8216349Sqs148142 		return (HXGE_ERROR);
8226349Sqs148142 	}
8236349Sqs148142 
8246349Sqs148142 	/* set masks. */
8256349Sqs148142 	for (i = 0; i < ldgvp->ldg_intrs; i++, ldgp++) {
8266349Sqs148142 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
8276349Sqs148142 		    "==> hxge_intr_mask_mgmt_set: flag %d ldg %d"
8286349Sqs148142 		    "set mask nldvs %d", on, ldgp->ldg, ldgp->nldvs));
8296349Sqs148142 		for (j = 0; j < ldgp->nldvs; j++, ldvp++) {
8306349Sqs148142 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
8316349Sqs148142 			    "==> hxge_intr_mask_mgmt_set: "
8326349Sqs148142 			    "for %d %d flag %d", i, j, on));
8336349Sqs148142 			if (on) {
8346349Sqs148142 				ldvp->ldv_ldf_masks = 0;
8356349Sqs148142 				HXGE_DEBUG_MSG((hxgep, INT_CTL,
8366349Sqs148142 				    "==> hxge_intr_mask_mgmt_set: "
8376349Sqs148142 				    "ON mask off"));
8386349Sqs148142 			} else {
8396349Sqs148142 				ldvp->ldv_ldf_masks = (uint8_t)LD_IM_MASK;
8406349Sqs148142 				HXGE_DEBUG_MSG((hxgep, INT_CTL,
8416349Sqs148142 				    "==> hxge_intr_mask_mgmt_set:mask on"));
8426349Sqs148142 			}
8436349Sqs148142 
8446349Sqs148142 			rs = hpi_intr_mask_set(handle, ldvp->ldv,
8456349Sqs148142 			    ldvp->ldv_ldf_masks);
8466349Sqs148142 			if (rs != HPI_SUCCESS) {
8476349Sqs148142 				HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
8486349Sqs148142 				    "==> hxge_intr_mask_mgmt_set: "
8496349Sqs148142 				    "set mask failed rs 0x%x ldv %d mask 0x%x",
8506349Sqs148142 				    rs, ldvp->ldv, ldvp->ldv_ldf_masks));
8516349Sqs148142 				return (HXGE_ERROR | rs);
8526349Sqs148142 			}
8536349Sqs148142 			HXGE_DEBUG_MSG((hxgep, INT_CTL,
8546349Sqs148142 			    "==> hxge_intr_mask_mgmt_set: flag %d"
8556349Sqs148142 			    "set mask OK ldv %d mask 0x%x",
8566349Sqs148142 			    on, ldvp->ldv, ldvp->ldv_ldf_masks));
8576349Sqs148142 		}
8586349Sqs148142 	}
8596349Sqs148142 
8606349Sqs148142 	ldgp = ldgvp->ldgp;
8616349Sqs148142 	/* set the arm bit */
8626349Sqs148142 	for (i = 0; i < hxgep->ldgvp->ldg_intrs; i++, ldgp++) {
8636349Sqs148142 		if (on && !ldgp->arm) {
8646349Sqs148142 			ldgp->arm = B_TRUE;
8656349Sqs148142 		} else if (!on && ldgp->arm) {
8666349Sqs148142 			ldgp->arm = B_FALSE;
8676349Sqs148142 		}
8686349Sqs148142 		rs = hpi_intr_ldg_mgmt_set(handle, ldgp->ldg,
8696349Sqs148142 		    ldgp->arm, ldgp->ldg_timer);
8706349Sqs148142 		if (rs != HPI_SUCCESS) {
8716349Sqs148142 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
8726349Sqs148142 			    "<== hxge_intr_mask_mgmt_set: "
8736349Sqs148142 			    "set timer failed rs 0x%x ldg %d timer 0x%x",
8746349Sqs148142 			    rs, ldgp->ldg, ldgp->ldg_timer));
8756349Sqs148142 			return (HXGE_ERROR | rs);
8766349Sqs148142 		}
8776349Sqs148142 		HXGE_DEBUG_MSG((hxgep, INT_CTL,
8786349Sqs148142 		    "==> hxge_intr_mask_mgmt_set: OK (flag %d) "
8796349Sqs148142 		    "set timer ldg %d timer 0x%x",
8806349Sqs148142 		    on, ldgp->ldg, ldgp->ldg_timer));
8816349Sqs148142 	}
8826349Sqs148142 
8836349Sqs148142 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intr_mask_mgmt_set"));
8846349Sqs148142 	return (HXGE_OK);
8856349Sqs148142 }
8866349Sqs148142 
8876349Sqs148142 /*
8886349Sqs148142  * For Big Endian systems, the mac address will be from OBP. For Little
8896349Sqs148142  * Endian (x64) systems, it will be retrieved from the card since it cannot
8906349Sqs148142  * be programmed into PXE.
8916349Sqs148142  * This function also populates the MMAC parameters.
8926349Sqs148142  */
8936349Sqs148142 static hxge_status_t
hxge_get_mac_addr_properties(p_hxge_t hxgep)8946349Sqs148142 hxge_get_mac_addr_properties(p_hxge_t hxgep)
8956349Sqs148142 {
8966349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_get_mac_addr_properties "));
8976349Sqs148142 
8986349Sqs148142 	(void) hxge_pfc_mac_addrs_get(hxgep);
8996349Sqs148142 	hxgep->ouraddr = hxgep->factaddr;
9006349Sqs148142 
9016349Sqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_get_mac_addr_properties "));
9026349Sqs148142 	return (HXGE_OK);
9036349Sqs148142 }
9046349Sqs148142 
9056349Sqs148142 static void
hxge_ldgv_setup(p_hxge_ldg_t * ldgp,p_hxge_ldv_t * ldvp,uint8_t ldv,uint8_t endldg,int * ngrps)9066349Sqs148142 hxge_ldgv_setup(p_hxge_ldg_t *ldgp, p_hxge_ldv_t *ldvp, uint8_t ldv,
9076349Sqs148142 	uint8_t endldg, int *ngrps)
9086349Sqs148142 {
9096349Sqs148142 	HXGE_DEBUG_MSG((NULL, INT_CTL, "==> hxge_ldgv_setup"));
9106349Sqs148142 	/* Assign the group number for each device. */
9116349Sqs148142 	(*ldvp)->ldg_assigned = (*ldgp)->ldg;
9126349Sqs148142 	(*ldvp)->ldgp = *ldgp;
9136349Sqs148142 	(*ldvp)->ldv = ldv;
9146349Sqs148142 
9156349Sqs148142 	HXGE_DEBUG_MSG((NULL, INT_CTL,
9166349Sqs148142 	    "==> hxge_ldgv_setup: ldv %d endldg %d ldg %d, ldvp $%p",
9176349Sqs148142 	    ldv, endldg, (*ldgp)->ldg, (*ldgp)->ldvp));
9186349Sqs148142 
9196349Sqs148142 	(*ldgp)->nldvs++;
9206349Sqs148142 	if ((*ldgp)->ldg == (endldg - 1)) {
9216349Sqs148142 		if ((*ldgp)->ldvp == NULL) {
9226349Sqs148142 			(*ldgp)->ldvp = *ldvp;
9236349Sqs148142 			*ngrps += 1;
9246349Sqs148142 			HXGE_DEBUG_MSG((NULL, INT_CTL,
9256349Sqs148142 			    "==> hxge_ldgv_setup: ngrps %d", *ngrps));
9266349Sqs148142 		}
9276349Sqs148142 		HXGE_DEBUG_MSG((NULL, INT_CTL,
9286349Sqs148142 		    "==> hxge_ldgv_setup: ldvp $%p ngrps %d",
9296349Sqs148142 		    *ldvp, *ngrps));
9306349Sqs148142 		++*ldvp;
9316349Sqs148142 	} else {
9326349Sqs148142 		(*ldgp)->ldvp = *ldvp;
9336349Sqs148142 		*ngrps += 1;
9346349Sqs148142 		HXGE_DEBUG_MSG((NULL, INT_CTL, "==> hxge_ldgv_setup(done): "
9356349Sqs148142 		    "ldv %d endldg %d ldg %d, ldvp $%p",
9366349Sqs148142 		    ldv, endldg, (*ldgp)->ldg, (*ldgp)->ldvp));
9376349Sqs148142 		(*ldvp) = ++*ldvp;
9386349Sqs148142 		(*ldgp) = ++*ldgp;
9396349Sqs148142 		HXGE_DEBUG_MSG((NULL, INT_CTL,
9406349Sqs148142 		    "==> hxge_ldgv_setup: new ngrps %d", *ngrps));
9416349Sqs148142 	}
9426349Sqs148142 
9436349Sqs148142 	HXGE_DEBUG_MSG((NULL, INT_CTL, "==> hxge_ldgv_setup: "
9446349Sqs148142 	    "ldg %d nldvs %d ldv %d ldvp $%p endldg %d ngrps %d",
9456349Sqs148142 	    (*ldgp)->ldg, (*ldgp)->nldvs, ldv, ldvp, endldg, *ngrps));
9466349Sqs148142 
9476349Sqs148142 	HXGE_DEBUG_MSG((NULL, INT_CTL, "<== hxge_ldgv_setup"));
9486349Sqs148142 }
949