xref: /onnv-gate/usr/src/uts/common/io/hxge/hxge_pfc.c (revision 8718:3ebdab15f891)
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 /*
23*8718SMichael.Speer@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
246349Sqs148142  * Use is subject to license terms.
256349Sqs148142  */
266349Sqs148142 
276349Sqs148142 #include <hxge_impl.h>
286349Sqs148142 #include <hxge_classify.h>
296349Sqs148142 #include <hxge_pfc.h>
306349Sqs148142 #include <hpi_pfc.h>
316349Sqs148142 #include <sys/ethernet.h>
326349Sqs148142 
336349Sqs148142 static uint32_t crc32_mchash(p_ether_addr_t addr);
346349Sqs148142 static hxge_status_t hxge_pfc_load_hash_table(p_hxge_t hxgep);
356349Sqs148142 static uint32_t hxge_get_blade_id(p_hxge_t hxgep);
366349Sqs148142 static hxge_status_t hxge_tcam_default_add_entry(p_hxge_t hxgep,
376349Sqs148142 	tcam_class_t class);
386349Sqs148142 static hxge_status_t hxge_tcam_default_config(p_hxge_t hxgep);
396349Sqs148142 
406349Sqs148142 hxge_status_t
hxge_classify_init(p_hxge_t hxgep)416349Sqs148142 hxge_classify_init(p_hxge_t hxgep)
426349Sqs148142 {
436349Sqs148142 	hxge_status_t status = HXGE_OK;
446349Sqs148142 
456349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_init"));
466349Sqs148142 
476349Sqs148142 	status = hxge_classify_init_sw(hxgep);
486349Sqs148142 	if (status != HXGE_OK)
496349Sqs148142 		return (status);
506349Sqs148142 
516349Sqs148142 	status = hxge_classify_init_hw(hxgep);
526349Sqs148142 	if (status != HXGE_OK) {
536349Sqs148142 		(void) hxge_classify_exit_sw(hxgep);
546349Sqs148142 		return (status);
556349Sqs148142 	}
566349Sqs148142 
576349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_init"));
586349Sqs148142 
596349Sqs148142 	return (HXGE_OK);
606349Sqs148142 }
616349Sqs148142 
626349Sqs148142 hxge_status_t
hxge_classify_uninit(p_hxge_t hxgep)636349Sqs148142 hxge_classify_uninit(p_hxge_t hxgep)
646349Sqs148142 {
656349Sqs148142 	return (hxge_classify_exit_sw(hxgep));
666349Sqs148142 }
676349Sqs148142 
686349Sqs148142 static hxge_status_t
hxge_tcam_dump_entry(p_hxge_t hxgep,uint32_t location)696349Sqs148142 hxge_tcam_dump_entry(p_hxge_t hxgep, uint32_t location)
706349Sqs148142 {
716349Sqs148142 	hxge_tcam_entry_t	tcam_rdptr;
726349Sqs148142 	uint64_t		asc_ram = 0;
736349Sqs148142 	hpi_handle_t		handle;
746349Sqs148142 	hpi_status_t		status;
756349Sqs148142 
766349Sqs148142 	handle = hxgep->hpi_reg_handle;
776349Sqs148142 
786349Sqs148142 	/* Retrieve the saved entry */
796349Sqs148142 	bcopy((void *)&hxgep->classifier.tcam_entries[location].tce,
806349Sqs148142 	    (void *)&tcam_rdptr, sizeof (hxge_tcam_entry_t));
816349Sqs148142 
826349Sqs148142 	/* Compare the entry */
836349Sqs148142 	status = hpi_pfc_tcam_entry_read(handle, location, &tcam_rdptr);
846349Sqs148142 	if (status == HPI_FAILURE) {
856349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
866349Sqs148142 		    " hxge_tcam_dump_entry: tcam read failed at location %d ",
876349Sqs148142 		    location));
886349Sqs148142 		return (HXGE_ERROR);
896349Sqs148142 	}
906349Sqs148142 
916349Sqs148142 	status = hpi_pfc_tcam_asc_ram_entry_read(handle, location, &asc_ram);
926349Sqs148142 
936349Sqs148142 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "location %x\n"
946349Sqs148142 	    " key:  %llx %llx\n mask: %llx %llx\n ASC RAM %llx \n", location,
956349Sqs148142 	    tcam_rdptr.key0, tcam_rdptr.key1,
966349Sqs148142 	    tcam_rdptr.mask0, tcam_rdptr.mask1, asc_ram));
976349Sqs148142 	return (HXGE_OK);
986349Sqs148142 }
996349Sqs148142 
1006349Sqs148142 void
hxge_get_tcam(p_hxge_t hxgep,p_mblk_t mp)1016349Sqs148142 hxge_get_tcam(p_hxge_t hxgep, p_mblk_t mp)
1026349Sqs148142 {
1036349Sqs148142 	uint32_t	tcam_loc;
1046349Sqs148142 	uint32_t	*lptr;
1056349Sqs148142 	int		location;
1066349Sqs148142 	int		start_location = 0;
1076349Sqs148142 	int		stop_location = hxgep->classifier.tcam_size;
1086349Sqs148142 
1096349Sqs148142 	lptr = (uint32_t *)mp->b_rptr;
1106349Sqs148142 	location = *lptr;
1116349Sqs148142 
1126349Sqs148142 	if ((location >= hxgep->classifier.tcam_size) || (location < -1)) {
1136349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1146349Sqs148142 		    "hxge_tcam_dump: Invalid location %d \n", location));
1156349Sqs148142 		return;
1166349Sqs148142 	}
1176349Sqs148142 	if (location == -1) {
1186349Sqs148142 		start_location = 0;
1196349Sqs148142 		stop_location = hxgep->classifier.tcam_size;
1206349Sqs148142 	} else {
1216349Sqs148142 		start_location = location;
1226349Sqs148142 		stop_location = location + 1;
1236349Sqs148142 	}
1246349Sqs148142 	for (tcam_loc = start_location; tcam_loc < stop_location; tcam_loc++)
1256349Sqs148142 		(void) hxge_tcam_dump_entry(hxgep, tcam_loc);
1266349Sqs148142 }
1276349Sqs148142 
1286349Sqs148142 /*ARGSUSED*/
1296349Sqs148142 static hxge_status_t
hxge_add_tcam_entry(p_hxge_t hxgep,flow_resource_t * flow_res)1306349Sqs148142 hxge_add_tcam_entry(p_hxge_t hxgep, flow_resource_t *flow_res)
1316349Sqs148142 {
1326349Sqs148142 	return (HXGE_OK);
1336349Sqs148142 }
1346349Sqs148142 
1356349Sqs148142 void
hxge_put_tcam(p_hxge_t hxgep,p_mblk_t mp)1366349Sqs148142 hxge_put_tcam(p_hxge_t hxgep, p_mblk_t mp)
1376349Sqs148142 {
1386349Sqs148142 	flow_resource_t *fs;
1396349Sqs148142 	fs = (flow_resource_t *)mp->b_rptr;
1406349Sqs148142 
1416349Sqs148142 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1426349Sqs148142 	    "hxge_put_tcam addr fs $%p  type %x offset %x",
1436349Sqs148142 	    fs, fs->flow_spec.flow_type, fs->channel_cookie));
1446349Sqs148142 
1456349Sqs148142 	(void) hxge_add_tcam_entry(hxgep, fs);
1466349Sqs148142 }
1476349Sqs148142 
1486349Sqs148142 static uint32_t
hxge_get_blade_id(p_hxge_t hxgep)1496349Sqs148142 hxge_get_blade_id(p_hxge_t hxgep)
1506349Sqs148142 {
1516349Sqs148142 	phy_debug_training_vec_t	blade_id;
1526349Sqs148142 
1536349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_get_blade_id"));
1546349Sqs148142 	HXGE_REG_RD32(hxgep->hpi_reg_handle, PHY_DEBUG_TRAINING_VEC,
1556349Sqs148142 	    &blade_id.value);
1566349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_get_blade_id: id = %d",
1576349Sqs148142 	    blade_id.bits.bld_num));
1586349Sqs148142 
1596349Sqs148142 	return (blade_id.bits.bld_num);
1606349Sqs148142 }
1616349Sqs148142 
1626349Sqs148142 static hxge_status_t
hxge_tcam_default_add_entry(p_hxge_t hxgep,tcam_class_t class)1636349Sqs148142 hxge_tcam_default_add_entry(p_hxge_t hxgep, tcam_class_t class)
1646349Sqs148142 {
1656349Sqs148142 	hpi_status_t		rs = HPI_SUCCESS;
1666349Sqs148142 	uint32_t		location;
1676349Sqs148142 	hxge_tcam_entry_t	entry;
1686349Sqs148142 	hxge_tcam_spread_t	*key = NULL;
1696349Sqs148142 	hxge_tcam_spread_t	*mask = NULL;
1706349Sqs148142 	hpi_handle_t		handle;
1716349Sqs148142 	p_hxge_hw_list_t	hw_p;
1726349Sqs148142 
1736349Sqs148142 	if ((hw_p = hxgep->hxge_hw_p) == NULL) {
1746349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1756349Sqs148142 		    " hxge_tcam_default_add_entry: common hardware not set"));
1766349Sqs148142 		return (HXGE_ERROR);
1776349Sqs148142 	}
1786349Sqs148142 
1796349Sqs148142 	bzero(&entry, sizeof (hxge_tcam_entry_t));
1806349Sqs148142 
1816349Sqs148142 	/*
1826349Sqs148142 	 * The class id and blade id are common for all classes
1836349Sqs148142 	 * Only use the blade id for matching and the rest are wild cards.
1846349Sqs148142 	 * This will allow one TCAM entry to match all traffic in order
1856349Sqs148142 	 * to spread the traffic using source hash.
1866349Sqs148142 	 */
1876349Sqs148142 	key = &entry.key.spread;
1886349Sqs148142 	mask = &entry.mask.spread;
1896349Sqs148142 
1906349Sqs148142 	key->blade_id = hxge_get_blade_id(hxgep);
1916349Sqs148142 
1926864Sqs148142 	mask->class_code = 0xf;
1936864Sqs148142 	mask->class_code_l = 0x1;
1946349Sqs148142 	mask->blade_id = 0;
1956349Sqs148142 	mask->wild1 = 0x7ffffff;
1966864Sqs148142 	mask->wild = 0xffffffff;
1976864Sqs148142 	mask->wild_l = 0xffffffff;
1986349Sqs148142 
1996349Sqs148142 	location = class;
2006349Sqs148142 
2016349Sqs148142 	handle = hxgep->hpi_reg_handle;
2026349Sqs148142 
2036349Sqs148142 	MUTEX_ENTER(&hw_p->hxge_tcam_lock);
2046349Sqs148142 	rs = hpi_pfc_tcam_entry_write(handle, location, &entry);
2056349Sqs148142 	if (rs & HPI_PFC_ERROR) {
2066349Sqs148142 		MUTEX_EXIT(&hw_p->hxge_tcam_lock);
2076349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2086349Sqs148142 		    " hxge_tcam_default_add_entry tcam entry write"
2096349Sqs148142 		    " failed for location %d", location));
2106349Sqs148142 		return (HXGE_ERROR);
2116349Sqs148142 	}
2126349Sqs148142 
2136349Sqs148142 	/* Add the associative portion */
2146349Sqs148142 	entry.match_action.value = 0;
2156349Sqs148142 
2166349Sqs148142 	/* Use source hash to spread traffic */
2176349Sqs148142 	entry.match_action.bits.channel_d = 0;
2186349Sqs148142 	entry.match_action.bits.channel_c = 1;
2196349Sqs148142 	entry.match_action.bits.channel_b = 2;
2206349Sqs148142 	entry.match_action.bits.channel_a = 3;
2216349Sqs148142 	entry.match_action.bits.source_hash = 1;
2226349Sqs148142 	entry.match_action.bits.discard = 0;
2236349Sqs148142 
2246349Sqs148142 	rs = hpi_pfc_tcam_asc_ram_entry_write(handle,
2256349Sqs148142 	    location, entry.match_action.value);
2266349Sqs148142 	if (rs & HPI_PFC_ERROR) {
2276349Sqs148142 		MUTEX_EXIT(&hw_p->hxge_tcam_lock);
2286349Sqs148142 		HXGE_DEBUG_MSG((hxgep, PFC_CTL,
2296349Sqs148142 		    " hxge_tcam_default_add_entry tcam entry write"
2306349Sqs148142 		    " failed for ASC RAM location %d", location));
2316349Sqs148142 		return (HXGE_ERROR);
2326349Sqs148142 	}
2336349Sqs148142 
2346349Sqs148142 	bcopy((void *) &entry,
2356349Sqs148142 	    (void *) &hxgep->classifier.tcam_entries[location].tce,
2366349Sqs148142 	    sizeof (hxge_tcam_entry_t));
2376349Sqs148142 
2386349Sqs148142 	MUTEX_EXIT(&hw_p->hxge_tcam_lock);
2396349Sqs148142 
2406349Sqs148142 	return (HXGE_OK);
2416349Sqs148142 }
2426349Sqs148142 
2436349Sqs148142 /*
2446349Sqs148142  * Configure one TCAM entry for each class and make it match
2456349Sqs148142  * everything within the class in order to spread the traffic
2466349Sqs148142  * among the DMA channels based on the source hash.
2476349Sqs148142  *
2486349Sqs148142  * This is the default for now. This may change when Crossbow is
2496349Sqs148142  * available for configuring TCAM.
2506349Sqs148142  */
2516349Sqs148142 static hxge_status_t
hxge_tcam_default_config(p_hxge_t hxgep)2526349Sqs148142 hxge_tcam_default_config(p_hxge_t hxgep)
2536349Sqs148142 {
2546349Sqs148142 	uint8_t		class;
2556349Sqs148142 	uint32_t	class_config;
2566349Sqs148142 	hxge_status_t	status = HXGE_OK;
2576349Sqs148142 
2586349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_tcam_default_config"));
2596349Sqs148142 
2606349Sqs148142 	/*
2616349Sqs148142 	 * Add TCAM and its associative ram entries
2626349Sqs148142 	 * A wild card will be used for the class code in order to match
2636349Sqs148142 	 * any classes.
2646349Sqs148142 	 */
2656349Sqs148142 	class = 0;
2666349Sqs148142 	status = hxge_tcam_default_add_entry(hxgep, class);
2676349Sqs148142 	if (status != HXGE_OK) {
2686349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2696349Sqs148142 		    "hxge_tcam_default_config "
2706349Sqs148142 		    "hxge_tcam_default_add_entry failed class %d ",
2716349Sqs148142 		    class));
2726349Sqs148142 		return (HXGE_ERROR);
2736349Sqs148142 	}
2746349Sqs148142 
2756349Sqs148142 	/* Enable the classes */
2766349Sqs148142 	for (class = TCAM_CLASS_TCP_IPV4;
2776349Sqs148142 	    class <= TCAM_CLASS_SCTP_IPV6; class++) {
2786349Sqs148142 		/*
2796349Sqs148142 		 * By default, it is set to HXGE_CLASS_TCAM_LOOKUP in
2806349Sqs148142 		 * hxge_ndd.c. It may be overwritten in hxge.conf.
2816349Sqs148142 		 */
2826349Sqs148142 		class_config = hxgep->class_config.class_cfg[class];
2836349Sqs148142 
2846349Sqs148142 		status = hxge_pfc_ip_class_config(hxgep, class, class_config);
2856349Sqs148142 		if (status & HPI_PFC_ERROR) {
2866349Sqs148142 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2876349Sqs148142 			    "hxge_tcam_default_config "
2886349Sqs148142 			    "hxge_pfc_ip_class_config failed "
2896349Sqs148142 			    " class %d config %x ", class, class_config));
2906349Sqs148142 			return (HXGE_ERROR);
2916349Sqs148142 		}
2926349Sqs148142 	}
2936349Sqs148142 
2946349Sqs148142 	status = hxge_pfc_config_tcam_enable(hxgep);
2956349Sqs148142 
2966349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_tcam_default_config"));
2976349Sqs148142 
2986349Sqs148142 	return (status);
2996349Sqs148142 }
3006349Sqs148142 
3016349Sqs148142 hxge_status_t
hxge_pfc_set_default_mac_addr(p_hxge_t hxgep)3026349Sqs148142 hxge_pfc_set_default_mac_addr(p_hxge_t hxgep)
3036349Sqs148142 {
3046349Sqs148142 	hxge_status_t status;
3056349Sqs148142 
3066349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_set_default_mac_addr"));
3076349Sqs148142 
3086349Sqs148142 	MUTEX_ENTER(&hxgep->ouraddr_lock);
3096349Sqs148142 
3106349Sqs148142 	/*
3116349Sqs148142 	 * Set new interface local address and re-init device.
3126349Sqs148142 	 * This is destructive to any other streams attached
3136349Sqs148142 	 * to this device.
3146349Sqs148142 	 */
3156349Sqs148142 	RW_ENTER_WRITER(&hxgep->filter_lock);
3166349Sqs148142 	status = hxge_pfc_set_mac_address(hxgep,
3176349Sqs148142 	    HXGE_MAC_DEFAULT_ADDR_SLOT, &hxgep->ouraddr);
3186349Sqs148142 	RW_EXIT(&hxgep->filter_lock);
3196349Sqs148142 
3206349Sqs148142 	MUTEX_EXIT(&hxgep->ouraddr_lock);
3216349Sqs148142 
3226349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_set_default_mac_addr"));
3236349Sqs148142 	return (status);
3246349Sqs148142 }
3256349Sqs148142 
3266349Sqs148142 /*
3276349Sqs148142  * Add a multicast address entry into the HW hash table
3286349Sqs148142  */
3296349Sqs148142 hxge_status_t
hxge_add_mcast_addr(p_hxge_t hxgep,struct ether_addr * addrp)3306349Sqs148142 hxge_add_mcast_addr(p_hxge_t hxgep, struct ether_addr *addrp)
3316349Sqs148142 {
3326349Sqs148142 	uint32_t	mchash;
3336349Sqs148142 	p_hash_filter_t	hash_filter;
3346349Sqs148142 	uint16_t	hash_bit;
3356349Sqs148142 	boolean_t	rx_init = B_FALSE;
3366349Sqs148142 	uint_t		j;
3376349Sqs148142 	hxge_status_t	status = HXGE_OK;
3386349Sqs148142 
3396349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_add_mcast_addr"));
3406349Sqs148142 
3416349Sqs148142 	RW_ENTER_WRITER(&hxgep->filter_lock);
3426349Sqs148142 	mchash = crc32_mchash(addrp);
3436349Sqs148142 
3446349Sqs148142 	if (hxgep->hash_filter == NULL) {
3456349Sqs148142 		HXGE_DEBUG_MSG((NULL, STR_CTL,
3466349Sqs148142 		    "Allocating hash filter storage."));
3476349Sqs148142 		hxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
3486349Sqs148142 		    KM_SLEEP);
3496349Sqs148142 	}
3506349Sqs148142 
3516349Sqs148142 	hash_filter = hxgep->hash_filter;
3526349Sqs148142 	/*
3536349Sqs148142 	 * Note that mchash is an 8 bit value and thus 0 <= mchash <= 255.
3546349Sqs148142 	 * Consequently, 0 <= j <= 15 and 0 <= mchash % HASH_REG_WIDTH <= 15.
3556349Sqs148142 	 */
3566349Sqs148142 	j = mchash / HASH_REG_WIDTH;
3576349Sqs148142 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
3586349Sqs148142 	hash_filter->hash_filter_regs[j] |= hash_bit;
3596349Sqs148142 
3606349Sqs148142 	hash_filter->hash_bit_ref_cnt[mchash]++;
3616349Sqs148142 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
3626349Sqs148142 		hash_filter->hash_ref_cnt++;
3636349Sqs148142 		rx_init = B_TRUE;
3646349Sqs148142 	}
3656349Sqs148142 
3666349Sqs148142 	if (rx_init) {
3676349Sqs148142 		(void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, B_FALSE);
3686349Sqs148142 		(void) hxge_pfc_load_hash_table(hxgep);
3696349Sqs148142 		(void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, B_TRUE);
3706349Sqs148142 	}
3716349Sqs148142 
3726349Sqs148142 	RW_EXIT(&hxgep->filter_lock);
3736349Sqs148142 
3746349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_add_mcast_addr"));
3756349Sqs148142 
3766349Sqs148142 	return (HXGE_OK);
3776349Sqs148142 fail:
3786349Sqs148142 	RW_EXIT(&hxgep->filter_lock);
3796349Sqs148142 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_add_mcast_addr: "
3806349Sqs148142 	    "Unable to add multicast address"));
3816349Sqs148142 
3826349Sqs148142 	return (status);
3836349Sqs148142 }
3846349Sqs148142 
3856349Sqs148142 /*
3866349Sqs148142  * Remove a multicast address entry from the HW hash table
3876349Sqs148142  */
3886349Sqs148142 hxge_status_t
hxge_del_mcast_addr(p_hxge_t hxgep,struct ether_addr * addrp)3896349Sqs148142 hxge_del_mcast_addr(p_hxge_t hxgep, struct ether_addr *addrp)
3906349Sqs148142 {
3916349Sqs148142 	uint32_t	mchash;
3926349Sqs148142 	p_hash_filter_t	hash_filter;
3936349Sqs148142 	uint16_t	hash_bit;
3946349Sqs148142 	boolean_t	rx_init = B_FALSE;
3956349Sqs148142 	uint_t		j;
3966349Sqs148142 	hxge_status_t	status = HXGE_OK;
3976349Sqs148142 
3986349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_del_mcast_addr"));
3996349Sqs148142 	RW_ENTER_WRITER(&hxgep->filter_lock);
4006349Sqs148142 	mchash = crc32_mchash(addrp);
4016349Sqs148142 	if (hxgep->hash_filter == NULL) {
4026349Sqs148142 		HXGE_DEBUG_MSG((NULL, STR_CTL,
4036349Sqs148142 		    "Hash filter already de_allocated."));
4046349Sqs148142 		RW_EXIT(&hxgep->filter_lock);
4056349Sqs148142 		HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_del_mcast_addr"));
4066349Sqs148142 		return (HXGE_OK);
4076349Sqs148142 	}
4086349Sqs148142 
4096349Sqs148142 	hash_filter = hxgep->hash_filter;
4106349Sqs148142 	hash_filter->hash_bit_ref_cnt[mchash]--;
4116349Sqs148142 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
4126349Sqs148142 		j = mchash / HASH_REG_WIDTH;
4136349Sqs148142 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
4146349Sqs148142 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
4156349Sqs148142 		hash_filter->hash_ref_cnt--;
4166349Sqs148142 		rx_init = B_TRUE;
4176349Sqs148142 	}
4186349Sqs148142 
4196349Sqs148142 	if (hash_filter->hash_ref_cnt == 0) {
4206349Sqs148142 		HXGE_DEBUG_MSG((NULL, STR_CTL,
4216349Sqs148142 		    "De-allocating hash filter storage."));
4226349Sqs148142 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
4236349Sqs148142 		hxgep->hash_filter = NULL;
4246349Sqs148142 	}
4256349Sqs148142 
4266349Sqs148142 	if (rx_init) {
4276349Sqs148142 		(void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, B_FALSE);
4286349Sqs148142 		(void) hxge_pfc_load_hash_table(hxgep);
4296349Sqs148142 
4306349Sqs148142 		/* Enable hash only if there are any hash entries */
4316349Sqs148142 		if (hxgep->hash_filter != NULL)
4326349Sqs148142 			(void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle,
4336349Sqs148142 			    B_TRUE);
4346349Sqs148142 	}
4356349Sqs148142 
4366349Sqs148142 	RW_EXIT(&hxgep->filter_lock);
4376349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_del_mcast_addr"));
4386349Sqs148142 
4396349Sqs148142 	return (HXGE_OK);
4406349Sqs148142 fail:
4416349Sqs148142 	RW_EXIT(&hxgep->filter_lock);
4426349Sqs148142 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_del_mcast_addr: "
4436349Sqs148142 	    "Unable to remove multicast address"));
4446349Sqs148142 
4456349Sqs148142 	return (status);
4466349Sqs148142 }
4476349Sqs148142 
448*8718SMichael.Speer@Sun.COM hxge_status_t
hxge_pfc_clear_mac_address(p_hxge_t hxgep,uint32_t slot)449*8718SMichael.Speer@Sun.COM hxge_pfc_clear_mac_address(p_hxge_t hxgep, uint32_t slot)
450*8718SMichael.Speer@Sun.COM {
451*8718SMichael.Speer@Sun.COM 	hpi_status_t status;
4526349Sqs148142 
453*8718SMichael.Speer@Sun.COM 	status = hpi_pfc_clear_mac_address(hxgep->hpi_reg_handle, slot);
454*8718SMichael.Speer@Sun.COM 	if (status != HPI_SUCCESS)
455*8718SMichael.Speer@Sun.COM 		return (HXGE_ERROR);
456*8718SMichael.Speer@Sun.COM 
457*8718SMichael.Speer@Sun.COM 	return (HXGE_OK);
458*8718SMichael.Speer@Sun.COM }
459*8718SMichael.Speer@Sun.COM 
460*8718SMichael.Speer@Sun.COM hxge_status_t
hxge_pfc_set_mac_address(p_hxge_t hxgep,uint32_t slot,struct ether_addr * addrp)4616349Sqs148142 hxge_pfc_set_mac_address(p_hxge_t hxgep, uint32_t slot,
4626349Sqs148142     struct ether_addr *addrp)
4636349Sqs148142 {
4646349Sqs148142 	hpi_handle_t		handle;
4656349Sqs148142 	uint64_t		addr;
4666349Sqs148142 	hpi_status_t		hpi_status;
4676349Sqs148142 	uint8_t			*address = addrp->ether_addr_octet;
4686349Sqs148142 	uint64_t		tmp;
4696349Sqs148142 	int			i;
4706349Sqs148142 
4716349Sqs148142 	if (hxgep->hxge_hw_p == NULL) {
4726349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
4736349Sqs148142 		    " hxge_pfc_set_mac_address: common hardware not set"));
4746349Sqs148142 		return (HXGE_ERROR);
4756349Sqs148142 	}
4766349Sqs148142 
4776349Sqs148142 	/*
4786349Sqs148142 	 * Convert a byte array to a 48 bit value.
4796349Sqs148142 	 * Need to check endianess if in doubt
4806349Sqs148142 	 */
4816349Sqs148142 	addr = 0;
4826349Sqs148142 	for (i = 0; i < ETHERADDRL; i++) {
4836349Sqs148142 		tmp = address[i];
4846349Sqs148142 		addr <<= 8;
4856349Sqs148142 		addr |= tmp;
4866349Sqs148142 	}
4876349Sqs148142 
4886349Sqs148142 	handle = hxgep->hpi_reg_handle;
4896349Sqs148142 	hpi_status = hpi_pfc_set_mac_address(handle, slot, addr);
4906349Sqs148142 
4916349Sqs148142 	if (hpi_status != HPI_SUCCESS) {
4926349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
4936349Sqs148142 		    " hxge_pfc_set_mac_address: failed to set address"));
4946349Sqs148142 		return (HXGE_ERROR);
4956349Sqs148142 	}
4966349Sqs148142 
4976349Sqs148142 	return (HXGE_OK);
4986349Sqs148142 }
4996349Sqs148142 
5006349Sqs148142 /*ARGSUSED*/
5016349Sqs148142 hxge_status_t
hxge_pfc_num_macs_get(p_hxge_t hxgep,uint8_t * nmacs)502*8718SMichael.Speer@Sun.COM hxge_pfc_num_macs_get(p_hxge_t hxgep, uint8_t *nmacs)
5036349Sqs148142 {
5046349Sqs148142 	*nmacs = PFC_N_MAC_ADDRESSES;
5056349Sqs148142 	return (HXGE_OK);
5066349Sqs148142 }
5076349Sqs148142 
5086349Sqs148142 
5096349Sqs148142 hxge_status_t
hxge_pfc_set_hash(p_hxge_t hxgep,uint32_t seed)5106349Sqs148142 hxge_pfc_set_hash(p_hxge_t hxgep, uint32_t seed)
5116349Sqs148142 {
5126349Sqs148142 	hpi_status_t		rs = HPI_SUCCESS;
5136349Sqs148142 	hpi_handle_t		handle;
5146349Sqs148142 	p_hxge_class_pt_cfg_t 	p_class_cfgp;
5156349Sqs148142 
5166349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_set_hash"));
5176349Sqs148142 
5186349Sqs148142 	p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
5196349Sqs148142 	p_class_cfgp->init_hash = seed;
5206349Sqs148142 	handle = hxgep->hpi_reg_handle;
5216349Sqs148142 
5226349Sqs148142 	rs = hpi_pfc_set_hash_seed_value(handle, seed);
5236349Sqs148142 	if (rs & HPI_PFC_ERROR) {
5246349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
5256349Sqs148142 		    " hxge_pfc_set_hash %x failed ", seed));
5266349Sqs148142 		return (HXGE_ERROR | rs);
5276349Sqs148142 	}
5286349Sqs148142 
5296349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, " <== hxge_pfc_set_hash"));
5306349Sqs148142 
5316349Sqs148142 	return (HXGE_OK);
5326349Sqs148142 }
5336349Sqs148142 
5346349Sqs148142 hxge_status_t
hxge_pfc_config_tcam_enable(p_hxge_t hxgep)5356349Sqs148142 hxge_pfc_config_tcam_enable(p_hxge_t hxgep)
5366349Sqs148142 {
5376349Sqs148142 	hpi_handle_t		handle;
5386349Sqs148142 	boolean_t		enable = B_TRUE;
5396349Sqs148142 	hpi_status_t		hpi_status;
5406349Sqs148142 
5416349Sqs148142 	handle = hxgep->hpi_reg_handle;
5426349Sqs148142 	if (hxgep->hxge_hw_p == NULL) {
5436349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
5446349Sqs148142 		    " hxge_pfc_config_tcam_enable: common hardware not set"));
5456349Sqs148142 		return (HXGE_ERROR);
5466349Sqs148142 	}
5476349Sqs148142 
5486349Sqs148142 	hpi_status = hpi_pfc_set_tcam_enable(handle, enable);
5496349Sqs148142 	if (hpi_status != HPI_SUCCESS) {
5506349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
5516349Sqs148142 		    " hpi_pfc_set_tcam_enable: enable tcam failed"));
5526349Sqs148142 		return (HXGE_ERROR);
5536349Sqs148142 	}
5546349Sqs148142 
5556349Sqs148142 	return (HXGE_OK);
5566349Sqs148142 }
5576349Sqs148142 
5586349Sqs148142 hxge_status_t
hxge_pfc_config_tcam_disable(p_hxge_t hxgep)5596349Sqs148142 hxge_pfc_config_tcam_disable(p_hxge_t hxgep)
5606349Sqs148142 {
5616349Sqs148142 	hpi_handle_t		handle;
5626349Sqs148142 	boolean_t		enable = B_FALSE;
5636349Sqs148142 	hpi_status_t		hpi_status;
5646349Sqs148142 
5656349Sqs148142 	handle = hxgep->hpi_reg_handle;
5666349Sqs148142 	if (hxgep->hxge_hw_p == NULL) {
5676349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
5686349Sqs148142 		    " hxge_pfc_config_tcam_disable: common hardware not set"));
5696349Sqs148142 		return (HXGE_ERROR);
5706349Sqs148142 	}
5716349Sqs148142 
5726349Sqs148142 	hpi_status = hpi_pfc_set_tcam_enable(handle, enable);
5736349Sqs148142 	if (hpi_status != HPI_SUCCESS) {
5746349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
5756349Sqs148142 		    " hpi_pfc_set_tcam_enable: disable tcam failed"));
5766349Sqs148142 		return (HXGE_ERROR);
5776349Sqs148142 	}
5786349Sqs148142 
5796349Sqs148142 	return (HXGE_OK);
5806349Sqs148142 }
5816349Sqs148142 
5826349Sqs148142 static hxge_status_t
hxge_cfg_tcam_ip_class_get(p_hxge_t hxgep,tcam_class_t class,uint32_t * class_config)5836349Sqs148142 hxge_cfg_tcam_ip_class_get(p_hxge_t hxgep, tcam_class_t class,
5846349Sqs148142     uint32_t *class_config)
5856349Sqs148142 {
5866349Sqs148142 	hpi_status_t	rs = HPI_SUCCESS;
5876349Sqs148142 	tcam_key_cfg_t	cfg;
5886349Sqs148142 	hpi_handle_t	handle;
5896349Sqs148142 	uint32_t	ccfg = 0;
5906349Sqs148142 
5916349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_cfg_tcam_ip_class_get"));
5926349Sqs148142 
5936349Sqs148142 	bzero(&cfg, sizeof (tcam_key_cfg_t));
5946349Sqs148142 	handle = hxgep->hpi_reg_handle;
5956349Sqs148142 
5966349Sqs148142 	rs = hpi_pfc_get_l3_class_config(handle, class, &cfg);
5976349Sqs148142 	if (rs & HPI_PFC_ERROR) {
5986349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
5996349Sqs148142 		    " hxge_cfg_tcam_ip_class opt %x for class %d failed ",
6006349Sqs148142 		    class_config, class));
6016349Sqs148142 		return (HXGE_ERROR | rs);
6026349Sqs148142 	}
6036349Sqs148142 	if (cfg.discard)
6046349Sqs148142 		ccfg |=  HXGE_CLASS_DISCARD;
6056349Sqs148142 
6066349Sqs148142 	if (cfg.lookup_enable)
6076349Sqs148142 		ccfg |= HXGE_CLASS_TCAM_LOOKUP;
6086349Sqs148142 
6096349Sqs148142 	*class_config = ccfg;
6106349Sqs148142 
6116349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_cfg_tcam_ip_class_get %x",
6126349Sqs148142 	    ccfg));
6136349Sqs148142 
6146349Sqs148142 	return (HXGE_OK);
6156349Sqs148142 }
6166349Sqs148142 
6176349Sqs148142 hxge_status_t
hxge_pfc_ip_class_config_get(p_hxge_t hxgep,tcam_class_t class,uint32_t * config)6186349Sqs148142 hxge_pfc_ip_class_config_get(p_hxge_t hxgep, tcam_class_t class,
6196349Sqs148142     uint32_t *config)
6206349Sqs148142 {
6216349Sqs148142 	uint32_t	t_class_config;
6226349Sqs148142 	int		t_status = HXGE_OK;
6236349Sqs148142 
6246349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_ip_class_config_get"));
6256349Sqs148142 	t_class_config = 0;
6266349Sqs148142 	t_status = hxge_cfg_tcam_ip_class_get(hxgep, class, &t_class_config);
6276349Sqs148142 
6286349Sqs148142 	if (t_status & HPI_PFC_ERROR) {
6296349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
6306349Sqs148142 		    " hxge_pfc_ip_class_config_get for class %d tcam failed",
6316349Sqs148142 		    class));
6326349Sqs148142 		return (t_status);
6336349Sqs148142 	}
6346349Sqs148142 
6356349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, " hxge_pfc_ip_class_config tcam %x",
6366349Sqs148142 	    t_class_config));
6376349Sqs148142 
6386349Sqs148142 	*config = t_class_config;
6396349Sqs148142 
6406349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_ip_class_config_get"));
6416349Sqs148142 	return (HXGE_OK);
6426349Sqs148142 }
6436349Sqs148142 
6446349Sqs148142 static hxge_status_t
hxge_pfc_config_init(p_hxge_t hxgep)6456349Sqs148142 hxge_pfc_config_init(p_hxge_t hxgep)
6466349Sqs148142 {
6476864Sqs148142 	hpi_handle_t		handle;
6486864Sqs148142 	block_reset_t		reset_reg;
6496349Sqs148142 
6506349Sqs148142 	handle = hxgep->hpi_reg_handle;
6516349Sqs148142 	if (hxgep->hxge_hw_p == NULL) {
6526349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
6536349Sqs148142 		    " hxge_pfc_config_init: common hardware not set"));
6546349Sqs148142 		return (HXGE_ERROR);
6556349Sqs148142 	}
6566349Sqs148142 
6576864Sqs148142 	/* Reset PFC block from PEU to clear any previous state */
6586864Sqs148142 	reset_reg.value = 0;
6596864Sqs148142 	reset_reg.bits.pfc_rst = 1;
6606864Sqs148142 	HXGE_REG_WR32(hxgep->hpi_handle, BLOCK_RESET, reset_reg.value);
6616864Sqs148142 	HXGE_DELAY(1000);
6626864Sqs148142 
6636349Sqs148142 	(void) hpi_pfc_set_tcam_enable(handle, B_FALSE);
6646349Sqs148142 	(void) hpi_pfc_set_l2_hash(handle, B_FALSE);
6658366SQiyan.Sun@Sun.COM 	(void) hpi_pfc_set_tcp_cksum(handle, B_TRUE);
6666349Sqs148142 	(void) hpi_pfc_set_default_dma(handle, 0);
6676349Sqs148142 	(void) hpi_pfc_mac_addr_enable(handle, 0);
6686349Sqs148142 	(void) hpi_pfc_set_force_csum(handle, B_FALSE);
6696349Sqs148142 
6706349Sqs148142 	/* Set the drop log mask to ignore the logs */
6716349Sqs148142 	(void) hpi_pfc_set_drop_log_mask(handle, 1, 1, 1, 1, 1);
6726349Sqs148142 
6736349Sqs148142 	/* Clear the interrupt masks to receive interrupts */
6746349Sqs148142 	(void) hpi_pfc_set_interrupt_mask(handle, 0, 0, 0);
6756349Sqs148142 
6766349Sqs148142 	/* Clear the interrupt status */
6776349Sqs148142 	(void) hpi_pfc_clear_interrupt_status(handle);
6786349Sqs148142 
6796349Sqs148142 	return (HXGE_OK);
6806349Sqs148142 }
6816349Sqs148142 
6826349Sqs148142 static hxge_status_t
hxge_pfc_tcam_invalidate_all(p_hxge_t hxgep)6836349Sqs148142 hxge_pfc_tcam_invalidate_all(p_hxge_t hxgep)
6846349Sqs148142 {
6856349Sqs148142 	hpi_status_t		rs = HPI_SUCCESS;
6866349Sqs148142 	hpi_handle_t		handle;
6876349Sqs148142 	p_hxge_hw_list_t	hw_p;
6886349Sqs148142 
6896349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL,
6906349Sqs148142 	    "==> hxge_pfc_tcam_invalidate_all"));
6916349Sqs148142 	handle = hxgep->hpi_reg_handle;
6926349Sqs148142 	if ((hw_p = hxgep->hxge_hw_p) == NULL) {
6936349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
6946349Sqs148142 		    " hxge_pfc_tcam_invalidate_all: common hardware not set"));
6956349Sqs148142 		return (HXGE_ERROR);
6966349Sqs148142 	}
6976349Sqs148142 
6986349Sqs148142 	MUTEX_ENTER(&hw_p->hxge_tcam_lock);
6996349Sqs148142 	rs = hpi_pfc_tcam_invalidate_all(handle);
7006349Sqs148142 	MUTEX_EXIT(&hw_p->hxge_tcam_lock);
7016349Sqs148142 
7026349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_tcam_invalidate_all"));
7036349Sqs148142 	if (rs != HPI_SUCCESS)
7046349Sqs148142 		return (HXGE_ERROR);
7056349Sqs148142 
7066349Sqs148142 	return (HXGE_OK);
7076349Sqs148142 }
7086349Sqs148142 
7096349Sqs148142 static hxge_status_t
hxge_pfc_tcam_init(p_hxge_t hxgep)7106349Sqs148142 hxge_pfc_tcam_init(p_hxge_t hxgep)
7116349Sqs148142 {
7126349Sqs148142 	hpi_status_t	rs = HPI_SUCCESS;
7136349Sqs148142 	hpi_handle_t	handle;
7146349Sqs148142 
7156349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_tcam_init"));
7166349Sqs148142 	handle = hxgep->hpi_reg_handle;
7176349Sqs148142 
7186349Sqs148142 	if (hxgep->hxge_hw_p == NULL) {
7196349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7206349Sqs148142 		    " hxge_pfc_tcam_init: common hardware not set"));
7216349Sqs148142 		return (HXGE_ERROR);
7226349Sqs148142 	}
7236349Sqs148142 
7246349Sqs148142 	/*
7256349Sqs148142 	 * Disable the TCAM.
7266349Sqs148142 	 */
7276349Sqs148142 	rs = hpi_pfc_set_tcam_enable(handle, B_FALSE);
7286349Sqs148142 	if (rs != HPI_SUCCESS) {
7296349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "failed TCAM Disable\n"));
7306349Sqs148142 		return (HXGE_ERROR | rs);
7316349Sqs148142 	}
7326349Sqs148142 
7336349Sqs148142 	/*
7346349Sqs148142 	 * Invalidate all the TCAM entries for this blade.
7356349Sqs148142 	 */
7366349Sqs148142 	rs = hxge_pfc_tcam_invalidate_all(hxgep);
7376349Sqs148142 	if (rs != HPI_SUCCESS) {
7386349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "failed TCAM Disable\n"));
7396349Sqs148142 		return (HXGE_ERROR | rs);
7406349Sqs148142 	}
7416349Sqs148142 
7426349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_tcam_init"));
7436349Sqs148142 	return (HXGE_OK);
7446349Sqs148142 }
7456349Sqs148142 
7466349Sqs148142 static hxge_status_t
hxge_pfc_vlan_tbl_clear_all(p_hxge_t hxgep)7476349Sqs148142 hxge_pfc_vlan_tbl_clear_all(p_hxge_t hxgep)
7486349Sqs148142 {
7496349Sqs148142 	hpi_handle_t		handle;
7506349Sqs148142 	hpi_status_t		rs = HPI_SUCCESS;
7516349Sqs148142 	p_hxge_hw_list_t	hw_p;
7526349Sqs148142 
7536349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_vlan_tbl_clear_all "));
7546349Sqs148142 
7556349Sqs148142 	handle = hxgep->hpi_reg_handle;
7566349Sqs148142 	if ((hw_p = hxgep->hxge_hw_p) == NULL) {
7576349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7586349Sqs148142 		    " hxge_pfc_vlan_tbl_clear_all: common hardware not set"));
7596349Sqs148142 		return (HXGE_ERROR);
7606349Sqs148142 	}
7616349Sqs148142 
762*8718SMichael.Speer@Sun.COM 	MUTEX_ENTER(&hw_p->hxge_vlan_lock);
7636349Sqs148142 	rs = hpi_pfc_cfg_vlan_table_clear(handle);
764*8718SMichael.Speer@Sun.COM 	MUTEX_EXIT(&hw_p->hxge_vlan_lock);
7656349Sqs148142 
7666349Sqs148142 	if (rs != HPI_SUCCESS) {
7676349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7686349Sqs148142 		    "failed vlan table clear\n"));
7696349Sqs148142 		return (HXGE_ERROR | rs);
7706349Sqs148142 	}
7716349Sqs148142 
7726349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_vlan_tbl_clear_all "));
7736349Sqs148142 	return (HXGE_OK);
7746349Sqs148142 }
7756349Sqs148142 
7766349Sqs148142 hxge_status_t
hxge_pfc_ip_class_config(p_hxge_t hxgep,tcam_class_t class,uint32_t config)7776349Sqs148142 hxge_pfc_ip_class_config(p_hxge_t hxgep, tcam_class_t class, uint32_t config)
7786349Sqs148142 {
7796349Sqs148142 	uint32_t		class_config;
7806349Sqs148142 	p_hxge_class_pt_cfg_t 	p_class_cfgp;
7816349Sqs148142 	tcam_key_cfg_t		cfg;
7826349Sqs148142 	hpi_handle_t		handle;
7836349Sqs148142 	hpi_status_t		rs = HPI_SUCCESS;
7846349Sqs148142 
7856349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_ip_class_config"));
7866349Sqs148142 	p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
7876349Sqs148142 	class_config = p_class_cfgp->class_cfg[class];
7886349Sqs148142 
7896349Sqs148142 	if (class_config != config) {
7906349Sqs148142 		p_class_cfgp->class_cfg[class] = config;
7916349Sqs148142 		class_config = config;
7926349Sqs148142 	}
7936349Sqs148142 
7946349Sqs148142 	handle = hxgep->hpi_reg_handle;
7956349Sqs148142 
7966349Sqs148142 	if (class == TCAM_CLASS_ETYPE_1 || class == TCAM_CLASS_ETYPE_2) {
7976349Sqs148142 		rs = hpi_pfc_set_l2_class_slot(handle,
7986349Sqs148142 		    class_config & HXGE_CLASS_ETHER_TYPE_MASK,
7996349Sqs148142 		    class_config & HXGE_CLASS_VALID,
8006349Sqs148142 		    class - TCAM_CLASS_ETYPE_1);
8016349Sqs148142 	} else {
8026349Sqs148142 		if (class_config & HXGE_CLASS_DISCARD)
8036349Sqs148142 			cfg.discard = 1;
8046349Sqs148142 		else
8056349Sqs148142 			cfg.discard = 0;
8066349Sqs148142 		if (class_config & HXGE_CLASS_TCAM_LOOKUP)
8076349Sqs148142 			cfg.lookup_enable = 1;
8086349Sqs148142 		else
8096349Sqs148142 			cfg.lookup_enable = 0;
8106349Sqs148142 
8116349Sqs148142 		rs = hpi_pfc_set_l3_class_config(handle, class, cfg);
8126349Sqs148142 	}
8136349Sqs148142 
8146349Sqs148142 	if (rs & HPI_PFC_ERROR) {
8156349Sqs148142 		HXGE_DEBUG_MSG((hxgep, PFC_CTL,
8166349Sqs148142 		    " hxge_pfc_ip_class_config %x for class %d tcam failed",
8176349Sqs148142 		    config, class));
8186349Sqs148142 		return (HXGE_ERROR);
8196349Sqs148142 	}
8206349Sqs148142 
8216349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_ip_class_config"));
8226349Sqs148142 	return (HXGE_OK);
8236349Sqs148142 }
8246349Sqs148142 
8256349Sqs148142 hxge_status_t
hxge_pfc_ip_class_config_all(p_hxge_t hxgep)8266349Sqs148142 hxge_pfc_ip_class_config_all(p_hxge_t hxgep)
8276349Sqs148142 {
8286349Sqs148142 	uint32_t	class_config;
8296349Sqs148142 	tcam_class_t	cl;
8306349Sqs148142 	int		status = HXGE_OK;
8316349Sqs148142 
8326349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_ip_class_config_all"));
8336349Sqs148142 
8346349Sqs148142 	for (cl = TCAM_CLASS_ETYPE_1; cl <= TCAM_CLASS_SCTP_IPV6; cl++) {
8356349Sqs148142 		if (cl == TCAM_CLASS_RESERVED_4 ||
8366349Sqs148142 		    cl == TCAM_CLASS_RESERVED_5 ||
8376349Sqs148142 		    cl == TCAM_CLASS_RESERVED_6 ||
8386349Sqs148142 		    cl == TCAM_CLASS_RESERVED_7)
8396349Sqs148142 			continue;
8406349Sqs148142 
8416349Sqs148142 		class_config = hxgep->class_config.class_cfg[cl];
8426349Sqs148142 		status = hxge_pfc_ip_class_config(hxgep, cl, class_config);
8436349Sqs148142 		if (status & HPI_PFC_ERROR) {
8446349Sqs148142 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
8456349Sqs148142 			    "hxge_pfc_ip_class_config failed "
8466349Sqs148142 			    " class %d config %x ", cl, class_config));
8476349Sqs148142 		}
8486349Sqs148142 	}
8496349Sqs148142 
8506349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_ip_class_config_all"));
8516349Sqs148142 	return (HXGE_OK);
8526349Sqs148142 }
8536349Sqs148142 
8546349Sqs148142 static hxge_status_t
hxge_pfc_update_hw(p_hxge_t hxgep)8556349Sqs148142 hxge_pfc_update_hw(p_hxge_t hxgep)
8566349Sqs148142 {
8576349Sqs148142 	hxge_status_t	status = HXGE_OK;
8586349Sqs148142 	hpi_handle_t	handle;
8596349Sqs148142 	p_hxge_param_t	pa;
8606349Sqs148142 	int		i;
8616349Sqs148142 	boolean_t	parity = 0;
8626349Sqs148142 	boolean_t	implicit_valid = 0;
8636349Sqs148142 	vlan_id_t	implicit_vlan_id;
8647775SQiyan.Sun@Sun.COM 	uint32_t	vlanid_group;
8657775SQiyan.Sun@Sun.COM 	uint64_t	offset;
8667775SQiyan.Sun@Sun.COM 	int		max_vlan_groups;
8677775SQiyan.Sun@Sun.COM 	int		vlan_group_step;
8686349Sqs148142 
8696349Sqs148142 	p_hxge_class_pt_cfg_t 	p_class_cfgp;
8706349Sqs148142 
8716349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_update_hw"));
8726349Sqs148142 	p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
8736349Sqs148142 	handle = hxgep->hpi_reg_handle;
8746349Sqs148142 
8756349Sqs148142 	status = hxge_pfc_set_hash(hxgep, p_class_cfgp->init_hash);
8766349Sqs148142 	if (status != HXGE_OK) {
8776349Sqs148142 		HXGE_DEBUG_MSG((hxgep, PFC_CTL, "hxge_pfc_set_hash Failed"));
8786349Sqs148142 		return (HXGE_ERROR);
8796349Sqs148142 	}
8806349Sqs148142 
8817775SQiyan.Sun@Sun.COM 	/*
8827775SQiyan.Sun@Sun.COM 	 * configure vlan table to join all vlans in order for Solaris
8837775SQiyan.Sun@Sun.COM 	 * network to receive vlan packets of any acceptible VIDs.
8847775SQiyan.Sun@Sun.COM 	 * This may change when Solaris network passes VIDs down.
8857775SQiyan.Sun@Sun.COM 	 */
8867775SQiyan.Sun@Sun.COM 	vlanid_group = 0xffffffff;
8877775SQiyan.Sun@Sun.COM 	max_vlan_groups = 128;
8887775SQiyan.Sun@Sun.COM 	vlan_group_step = 8;
8897775SQiyan.Sun@Sun.COM 	for (i = 0; i < max_vlan_groups; i++) {
8907775SQiyan.Sun@Sun.COM 		offset = PFC_VLAN_TABLE + i * vlan_group_step;
8917775SQiyan.Sun@Sun.COM 		REG_PIO_WRITE64(handle, offset, vlanid_group);
8926349Sqs148142 	}
8936349Sqs148142 
8946349Sqs148142 	/* Configure the vlan_ctrl register */
8956349Sqs148142 	/* Let hw generate the parity bits in pfc_vlan_table */
8966349Sqs148142 	parity = 0;
8976349Sqs148142 
8986349Sqs148142 	pa = (p_hxge_param_t)&hxgep->param_arr[param_implicit_vlan_id];
8996349Sqs148142 	implicit_vlan_id = (vlan_id_t)pa->value;
9006349Sqs148142 
9016349Sqs148142 	/*
9026349Sqs148142 	 * Enable it only if there is a valid implicity vlan id either in
9036349Sqs148142 	 * NDD table or the .conf file.
9046349Sqs148142 	 */
9056349Sqs148142 	if (implicit_vlan_id >= VLAN_ID_MIN && implicit_vlan_id <= VLAN_ID_MAX)
9066349Sqs148142 		implicit_valid = 1;
9076349Sqs148142 
9086349Sqs148142 	status = hpi_pfc_cfg_vlan_control_set(handle, parity, implicit_valid,
9096349Sqs148142 	    implicit_vlan_id);
9106349Sqs148142 	if (status != HPI_SUCCESS) {
9116349Sqs148142 		HXGE_DEBUG_MSG((hxgep, PFC_CTL,
9126349Sqs148142 		    "hxge_pfc_update_hw: hpi_pfc_cfg_vlan_control_set failed"));
9136349Sqs148142 		return (HXGE_ERROR);
9146349Sqs148142 	}
9156349Sqs148142 
9166349Sqs148142 	/* config MAC addresses */
9176349Sqs148142 	/* Need to think about this */
9186349Sqs148142 
9196349Sqs148142 	/* Configure hash value and classes */
9206349Sqs148142 	status = hxge_pfc_ip_class_config_all(hxgep);
9216349Sqs148142 	if (status != HXGE_OK) {
9226349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
9236349Sqs148142 		    "hxge_pfc_ip_class_config_all Failed"));
9246349Sqs148142 		return (HXGE_ERROR);
9256349Sqs148142 	}
9266349Sqs148142 
9276349Sqs148142 	return (HXGE_OK);
9286349Sqs148142 }
9296349Sqs148142 
9306349Sqs148142 hxge_status_t
hxge_pfc_hw_reset(p_hxge_t hxgep)9316349Sqs148142 hxge_pfc_hw_reset(p_hxge_t hxgep)
9326349Sqs148142 {
9336349Sqs148142 	hxge_status_t status = HXGE_OK;
9346349Sqs148142 
9356349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_hw_reset"));
9366349Sqs148142 
9376349Sqs148142 	status = hxge_pfc_config_init(hxgep);
9386349Sqs148142 	if (status != HXGE_OK) {
9396349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
9406349Sqs148142 		    "failed PFC config init."));
9416349Sqs148142 		return (status);
9426349Sqs148142 	}
9436349Sqs148142 
9446349Sqs148142 	status = hxge_pfc_tcam_init(hxgep);
9456349Sqs148142 	if (status != HXGE_OK) {
9466349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "failed TCAM init."));
9476349Sqs148142 		return (status);
9486349Sqs148142 	}
9496349Sqs148142 
9506349Sqs148142 	/*
9516349Sqs148142 	 * invalidate VLAN RDC tables
9526349Sqs148142 	 */
9536349Sqs148142 	status = hxge_pfc_vlan_tbl_clear_all(hxgep);
9546349Sqs148142 	if (status != HXGE_OK) {
9556349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
9566349Sqs148142 		    "failed VLAN Table Invalidate. "));
9576349Sqs148142 		return (status);
9586349Sqs148142 	}
9596349Sqs148142 	hxgep->classifier.state |= HXGE_PFC_HW_RESET;
9606349Sqs148142 
9616349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_hw_reset"));
9626349Sqs148142 
9636349Sqs148142 	return (HXGE_OK);
9646349Sqs148142 }
9656349Sqs148142 
9666349Sqs148142 hxge_status_t
hxge_classify_init_hw(p_hxge_t hxgep)9676349Sqs148142 hxge_classify_init_hw(p_hxge_t hxgep)
9686349Sqs148142 {
9696349Sqs148142 	hxge_status_t status = HXGE_OK;
9706349Sqs148142 
9716349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_init_hw"));
9726349Sqs148142 
9736349Sqs148142 	if (hxgep->classifier.state & HXGE_PFC_HW_INIT) {
9746349Sqs148142 		HXGE_DEBUG_MSG((hxgep, PFC_CTL,
9756349Sqs148142 		    "hxge_classify_init_hw already init"));
9766349Sqs148142 		return (HXGE_OK);
9776349Sqs148142 	}
9786349Sqs148142 
9796349Sqs148142 	/* Now do a real configuration */
9806349Sqs148142 	status = hxge_pfc_update_hw(hxgep);
9816349Sqs148142 	if (status != HXGE_OK) {
9826349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
9836349Sqs148142 		    "hxge_pfc_update_hw failed"));
9846349Sqs148142 		return (HXGE_ERROR);
9856349Sqs148142 	}
9866349Sqs148142 
9876349Sqs148142 	status = hxge_tcam_default_config(hxgep);
9886349Sqs148142 	if (status != HXGE_OK) {
9896349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
9906349Sqs148142 		    "hxge_tcam_default_config failed"));
9916349Sqs148142 		return (status);
9926349Sqs148142 	}
9936349Sqs148142 
9946349Sqs148142 	hxgep->classifier.state |= HXGE_PFC_HW_INIT;
9956349Sqs148142 
9966349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_init_hw"));
9976349Sqs148142 
9986349Sqs148142 	return (HXGE_OK);
9996349Sqs148142 }
10006349Sqs148142 
10016349Sqs148142 hxge_status_t
hxge_classify_init_sw(p_hxge_t hxgep)10026349Sqs148142 hxge_classify_init_sw(p_hxge_t hxgep)
10036349Sqs148142 {
10046349Sqs148142 	int		alloc_size;
10056349Sqs148142 	hxge_classify_t	*classify_ptr;
10066349Sqs148142 
10076349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_init_sw"));
10086349Sqs148142 	classify_ptr = &hxgep->classifier;
10096349Sqs148142 
10106349Sqs148142 	if (classify_ptr->state & HXGE_PFC_SW_INIT) {
10116349Sqs148142 		HXGE_DEBUG_MSG((hxgep, PFC_CTL,
10126349Sqs148142 		    "hxge_classify_init_sw already init"));
10136349Sqs148142 		return (HXGE_OK);
10146349Sqs148142 	}
10156349Sqs148142 
10166349Sqs148142 	/* Init SW structures */
10176349Sqs148142 	classify_ptr->tcam_size = TCAM_HXGE_TCAM_MAX_ENTRY;
10186349Sqs148142 
10196349Sqs148142 	alloc_size = sizeof (tcam_flow_spec_t) * classify_ptr->tcam_size;
10206349Sqs148142 	classify_ptr->tcam_entries = KMEM_ZALLOC(alloc_size, NULL);
10216349Sqs148142 	bzero(classify_ptr->class_usage, sizeof (classify_ptr->class_usage));
10226349Sqs148142 
10236349Sqs148142 	/* Start from the beginning of TCAM */
10246349Sqs148142 	hxgep->classifier.tcam_location = 0;
10256349Sqs148142 	classify_ptr->state |= HXGE_PFC_SW_INIT;
10266349Sqs148142 
10276349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_init_sw"));
10286349Sqs148142 
10296349Sqs148142 	return (HXGE_OK);
10306349Sqs148142 }
10316349Sqs148142 
10326349Sqs148142 hxge_status_t
hxge_classify_exit_sw(p_hxge_t hxgep)10336349Sqs148142 hxge_classify_exit_sw(p_hxge_t hxgep)
10346349Sqs148142 {
10356349Sqs148142 	int		alloc_size;
10366349Sqs148142 	hxge_classify_t	*classify_ptr;
10376349Sqs148142 	int		fsize;
10386349Sqs148142 
10396349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_exit_sw"));
10406349Sqs148142 	classify_ptr = &hxgep->classifier;
10416349Sqs148142 
10426349Sqs148142 	fsize = sizeof (tcam_flow_spec_t);
10436349Sqs148142 	if (classify_ptr->tcam_entries) {
10446349Sqs148142 		alloc_size = fsize * classify_ptr->tcam_size;
10456349Sqs148142 		KMEM_FREE((void *) classify_ptr->tcam_entries, alloc_size);
10466349Sqs148142 	}
10476349Sqs148142 	hxgep->classifier.state = NULL;
10486349Sqs148142 
10496349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_exit_sw"));
10506349Sqs148142 
10516349Sqs148142 	return (HXGE_OK);
10526349Sqs148142 }
10536349Sqs148142 
10546349Sqs148142 /*ARGSUSED*/
10556349Sqs148142 hxge_status_t
hxge_pfc_handle_sys_errors(p_hxge_t hxgep)10566349Sqs148142 hxge_pfc_handle_sys_errors(p_hxge_t hxgep)
10576349Sqs148142 {
10586349Sqs148142 	return (HXGE_OK);
10596349Sqs148142 }
10606349Sqs148142 
10616349Sqs148142 uint_t
hxge_pfc_intr(caddr_t arg1,caddr_t arg2)10626349Sqs148142 hxge_pfc_intr(caddr_t arg1, caddr_t arg2)
10636349Sqs148142 {
10646349Sqs148142 	p_hxge_ldv_t		ldvp = (p_hxge_ldv_t)arg1;
10656349Sqs148142 	p_hxge_t		hxgep = (p_hxge_t)arg2;
10666349Sqs148142 	hpi_handle_t		handle;
10676349Sqs148142 	p_hxge_pfc_stats_t	statsp;
10686349Sqs148142 	pfc_int_status_t	int_status;
10696349Sqs148142 	pfc_bad_cs_counter_t	bad_cs_count;
10706349Sqs148142 	pfc_drop_counter_t	drop_count;
10716349Sqs148142 	pfc_drop_log_t		drop_log;
10726349Sqs148142 	pfc_vlan_par_err_log_t	vlan_par_err_log;
10736349Sqs148142 	pfc_tcam_par_err_log_t	tcam_par_err_log;
10746349Sqs148142 
10756349Sqs148142 	if (ldvp == NULL) {
10766349Sqs148142 		HXGE_DEBUG_MSG((NULL, INT_CTL,
10776349Sqs148142 		    "<== hxge_pfc_intr: hxgep $%p ldvp $%p", hxgep, ldvp));
10786349Sqs148142 		return (DDI_INTR_UNCLAIMED);
10796349Sqs148142 	}
10806349Sqs148142 
10816349Sqs148142 	if (arg2 == NULL || (void *) ldvp->hxgep != arg2) {
10826349Sqs148142 		hxgep = ldvp->hxgep;
10836349Sqs148142 	}
10846349Sqs148142 
10856349Sqs148142 	handle = hxgep->hpi_reg_handle;
10866349Sqs148142 	statsp = (p_hxge_pfc_stats_t)&hxgep->statsp->pfc_stats;
10876349Sqs148142 
10886349Sqs148142 	/*
10896349Sqs148142 	 * need to read the pfc interrupt status register to figure out
10906349Sqs148142 	 * what is happenning
10916349Sqs148142 	 */
10926349Sqs148142 	(void) hpi_pfc_get_interrupt_status(handle, &int_status);
10936349Sqs148142 
10946349Sqs148142 	if (int_status.bits.pkt_drop) {
10956349Sqs148142 		statsp->pkt_drop++;
10966349Sqs148142 		if (statsp->pkt_drop == 1)
10976349Sqs148142 			HXGE_ERROR_MSG((hxgep, INT_CTL, "PFC pkt_drop"));
10986349Sqs148142 
10996349Sqs148142 		/* Collect each individual drops */
11006349Sqs148142 		(void) hpi_pfc_get_drop_log(handle, &drop_log);
11016349Sqs148142 
11026349Sqs148142 		if (drop_log.bits.tcp_ctrl_drop)
11036349Sqs148142 			statsp->errlog.tcp_ctrl_drop++;
11046349Sqs148142 		if (drop_log.bits.l2_addr_drop)
11056349Sqs148142 			statsp->errlog.l2_addr_drop++;
11066349Sqs148142 		if (drop_log.bits.class_code_drop)
11076349Sqs148142 			statsp->errlog.class_code_drop++;
11086349Sqs148142 		if (drop_log.bits.tcam_drop)
11096349Sqs148142 			statsp->errlog.tcam_drop++;
11106349Sqs148142 		if (drop_log.bits.vlan_drop)
11116349Sqs148142 			statsp->errlog.vlan_drop++;
11126349Sqs148142 
11136349Sqs148142 		/* Collect the total drops for all kinds */
11146349Sqs148142 		(void) hpi_pfc_get_drop_counter(handle, &drop_count.value);
11156349Sqs148142 		statsp->drop_count += drop_count.bits.drop_count;
11166349Sqs148142 	}
11176349Sqs148142 
11186349Sqs148142 	if (int_status.bits.tcam_parity_err) {
11196349Sqs148142 		statsp->tcam_parity_err++;
11206349Sqs148142 
11216349Sqs148142 		(void) hpi_pfc_get_tcam_parity_log(handle, &tcam_par_err_log);
11226349Sqs148142 		statsp->errlog.tcam_par_err_log = tcam_par_err_log.bits.addr;
11236349Sqs148142 
11246349Sqs148142 		if (statsp->tcam_parity_err == 1)
11256349Sqs148142 			HXGE_ERROR_MSG((hxgep,
11266349Sqs148142 			    INT_CTL, " TCAM parity error addr: 0x%x",
11276349Sqs148142 			    tcam_par_err_log.bits.addr));
11286349Sqs148142 	}
11296349Sqs148142 
11306349Sqs148142 	if (int_status.bits.vlan_parity_err) {
11316349Sqs148142 		statsp->vlan_parity_err++;
11326349Sqs148142 
11336349Sqs148142 		(void) hpi_pfc_get_vlan_parity_log(handle, &vlan_par_err_log);
11346349Sqs148142 		statsp->errlog.vlan_par_err_log = vlan_par_err_log.bits.addr;
11356349Sqs148142 
11366349Sqs148142 		if (statsp->vlan_parity_err == 1)
11376349Sqs148142 			HXGE_ERROR_MSG((hxgep, INT_CTL,
11386349Sqs148142 			    " vlan table parity error addr: 0x%x",
11396349Sqs148142 			    vlan_par_err_log.bits.addr));
11406349Sqs148142 	}
11416349Sqs148142 
11426349Sqs148142 	(void) hpi_pfc_get_bad_csum_counter(handle, &bad_cs_count.value);
11436349Sqs148142 	statsp->bad_cs_count += bad_cs_count.bits.bad_cs_count;
11446349Sqs148142 
11456349Sqs148142 	(void) hpi_pfc_clear_interrupt_status(handle);
11466349Sqs148142 	return (DDI_INTR_CLAIMED);
11476349Sqs148142 }
11486349Sqs148142 
11496349Sqs148142 static void
hxge_pfc_get_next_mac_addr(uint8_t * st_mac,struct ether_addr * final_mac)11506349Sqs148142 hxge_pfc_get_next_mac_addr(uint8_t *st_mac, struct ether_addr *final_mac)
11516349Sqs148142 {
11526349Sqs148142 	uint64_t	mac[ETHERADDRL];
11536349Sqs148142 	uint64_t	mac_addr = 0;
11546349Sqs148142 	int		i, j;
11556349Sqs148142 
11566349Sqs148142 	for (i = ETHERADDRL - 1, j = 0; j < ETHERADDRL; i--, j++) {
11576349Sqs148142 		mac[j] = st_mac[i];
11586349Sqs148142 		mac_addr |= (mac[j] << (j*8));
11596349Sqs148142 	}
11606349Sqs148142 
11616349Sqs148142 	final_mac->ether_addr_octet[0] = (mac_addr & 0xff0000000000) >> 40;
11626349Sqs148142 	final_mac->ether_addr_octet[1] = (mac_addr & 0xff00000000) >> 32;
11636349Sqs148142 	final_mac->ether_addr_octet[2] = (mac_addr & 0xff000000) >> 24;
11646349Sqs148142 	final_mac->ether_addr_octet[3] = (mac_addr & 0xff0000) >> 16;
11656349Sqs148142 	final_mac->ether_addr_octet[4] = (mac_addr & 0xff00) >> 8;
11666349Sqs148142 	final_mac->ether_addr_octet[5] = (mac_addr & 0xff);
11676349Sqs148142 }
11686349Sqs148142 
11696349Sqs148142 hxge_status_t
hxge_pfc_mac_addrs_get(p_hxge_t hxgep)11706349Sqs148142 hxge_pfc_mac_addrs_get(p_hxge_t hxgep)
11716349Sqs148142 {
11726349Sqs148142 	hxge_status_t	status = HXGE_OK;
11736349Sqs148142 	hpi_status_t	hpi_status = HPI_SUCCESS;
11746349Sqs148142 	hpi_handle_t	handle = HXGE_DEV_HPI_HANDLE(hxgep);
11756349Sqs148142 	uint8_t		mac_addr[ETHERADDRL];
11766349Sqs148142 
11776349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_mac_addr_get"));
11786349Sqs148142 
11796349Sqs148142 	hpi_status = hpi_pfc_mac_addr_get_i(handle, mac_addr, 0);
11806349Sqs148142 	if (hpi_status != HPI_SUCCESS) {
11816349Sqs148142 		status = (HXGE_ERROR | hpi_status);
11826349Sqs148142 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
11836349Sqs148142 		    "hxge_pfc_mac_addr_get: pfc_mac_addr_get_i failed"));
11846349Sqs148142 		goto exit;
11856349Sqs148142 	}
11866349Sqs148142 
11876349Sqs148142 	hxge_pfc_get_next_mac_addr(mac_addr, &hxgep->factaddr);
11886349Sqs148142 	HXGE_ERROR_MSG((hxgep, PFC_CTL, "MAC Addr(0): %x:%x:%x:%x:%x:%x\n",
11896349Sqs148142 	    mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
11906349Sqs148142 	    mac_addr[4], mac_addr[5]));
11916349Sqs148142 
11926349Sqs148142 exit:
11936349Sqs148142 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, "<== hxge_pfc_mac_addr_get, "
11946349Sqs148142 	    "status [0x%x]", status));
11956349Sqs148142 	return (status);
11966349Sqs148142 }
11976349Sqs148142 
11986349Sqs148142 /*
11996349Sqs148142  * Calculate the bit in the multicast address filter
12006349Sqs148142  * that selects the given * address.
12016349Sqs148142  * Note: For Hydra, the last 8-bits are used.
12026349Sqs148142  */
12036349Sqs148142 static uint32_t
crc32_mchash(p_ether_addr_t addr)12046349Sqs148142 crc32_mchash(p_ether_addr_t addr)
12056349Sqs148142 {
12066349Sqs148142 	uint8_t		*cp;
12076349Sqs148142 	uint32_t	crc;
12086349Sqs148142 	uint32_t	c;
12096349Sqs148142 	int		byte;
12106349Sqs148142 	int		bit;
12116349Sqs148142 
12126349Sqs148142 	cp = (uint8_t *)addr;
12136349Sqs148142 	crc = (uint32_t)0xffffffff;
12146349Sqs148142 	for (byte = 0; byte < ETHERADDRL; byte++) {
12156349Sqs148142 		/* Hydra calculates the hash backwardly */
12166349Sqs148142 		c = (uint32_t)cp[ETHERADDRL - 1 - byte];
12176349Sqs148142 		for (bit = 0; bit < 8; bit++) {
12186349Sqs148142 			if ((c & 0x1) ^ (crc & 0x1))
12196349Sqs148142 				crc = (crc >> 1)^0xedb88320;
12206349Sqs148142 			else
12216349Sqs148142 				crc = (crc >> 1);
12226349Sqs148142 			c >>= 1;
12236349Sqs148142 		}
12246349Sqs148142 	}
12256349Sqs148142 	return ((~crc) >> (32 - HASH_BITS));
12266349Sqs148142 }
12276349Sqs148142 
12286349Sqs148142 static hxge_status_t
hxge_pfc_load_hash_table(p_hxge_t hxgep)12296349Sqs148142 hxge_pfc_load_hash_table(p_hxge_t hxgep)
12306349Sqs148142 {
12316349Sqs148142 	uint32_t		i;
12326349Sqs148142 	uint16_t		hashtab_e;
12336349Sqs148142 	p_hash_filter_t		hash_filter;
12346349Sqs148142 	hpi_handle_t		handle;
12356349Sqs148142 
12366349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_load_hash_table\n"));
12376349Sqs148142 	handle = hxgep->hpi_reg_handle;
12386349Sqs148142 
12396349Sqs148142 	/*
12406349Sqs148142 	 * Load the multicast hash filter bits.
12416349Sqs148142 	 */
12426349Sqs148142 	hash_filter = hxgep->hash_filter;
12436349Sqs148142 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
12446349Sqs148142 		if (hash_filter != NULL) {
12456349Sqs148142 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[i];
12466349Sqs148142 		} else {
12476349Sqs148142 			hashtab_e = 0;
12486349Sqs148142 		}
12496349Sqs148142 
12506349Sqs148142 		if (hpi_pfc_set_multicast_hash_table(handle, i,
12516349Sqs148142 		    hashtab_e) != HPI_SUCCESS)
12526349Sqs148142 			return (HXGE_ERROR);
12536349Sqs148142 	}
12546349Sqs148142 
12556349Sqs148142 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_load_hash_table\n"));
12566349Sqs148142 
12576349Sqs148142 	return (HXGE_OK);
12586349Sqs148142 }
1259