xref: /onnv-gate/usr/src/uts/common/io/nxge/nxge_fflp.c (revision 11304:3092d1e303d6)
13859Sml29623 /*
23859Sml29623  * CDDL HEADER START
33859Sml29623  *
43859Sml29623  * The contents of this file are subject to the terms of the
53859Sml29623  * Common Development and Distribution License (the "License").
63859Sml29623  * You may not use this file except in compliance with the License.
73859Sml29623  *
83859Sml29623  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93859Sml29623  * or http://www.opensolaris.org/os/licensing.
103859Sml29623  * See the License for the specific language governing permissions
113859Sml29623  * and limitations under the License.
123859Sml29623  *
133859Sml29623  * When distributing Covered Code, include this CDDL HEADER in each
143859Sml29623  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153859Sml29623  * If applicable, add the following below this CDDL HEADER, with the
163859Sml29623  * fields enclosed by brackets "[]" replaced with your own identifying
173859Sml29623  * information: Portions Copyright [yyyy] [name of copyright owner]
183859Sml29623  *
193859Sml29623  * CDDL HEADER END
203859Sml29623  */
213859Sml29623 /*
22*11304SJanie.Lu@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
233859Sml29623  * Use is subject to license terms.
243859Sml29623  */
253859Sml29623 
263859Sml29623 #include <npi_fflp.h>
273859Sml29623 #include <npi_mac.h>
283859Sml29623 #include <nxge_defs.h>
293859Sml29623 #include <nxge_flow.h>
303859Sml29623 #include <nxge_fflp.h>
313859Sml29623 #include <nxge_impl.h>
323859Sml29623 #include <nxge_fflp_hash.h>
333859Sml29623 #include <nxge_common.h>
343859Sml29623 
353859Sml29623 
363859Sml29623 /*
373859Sml29623  * Function prototypes
383859Sml29623  */
393859Sml29623 static nxge_status_t nxge_fflp_vlan_tbl_clear_all(p_nxge_t);
403859Sml29623 static nxge_status_t nxge_fflp_tcam_invalidate_all(p_nxge_t);
413859Sml29623 static nxge_status_t nxge_fflp_tcam_init(p_nxge_t);
423859Sml29623 static nxge_status_t nxge_fflp_fcram_invalidate_all(p_nxge_t);
433859Sml29623 static nxge_status_t nxge_fflp_fcram_init(p_nxge_t);
443859Sml29623 static int nxge_flow_need_hash_lookup(p_nxge_t, flow_resource_t *);
453859Sml29623 static void nxge_fill_tcam_entry_tcp(p_nxge_t, flow_spec_t *, tcam_entry_t *);
463859Sml29623 static void nxge_fill_tcam_entry_udp(p_nxge_t, flow_spec_t *, tcam_entry_t *);
473859Sml29623 static void nxge_fill_tcam_entry_sctp(p_nxge_t, flow_spec_t *, tcam_entry_t *);
483859Sml29623 static void nxge_fill_tcam_entry_tcp_ipv6(p_nxge_t, flow_spec_t *,
493859Sml29623 	tcam_entry_t *);
503859Sml29623 static void nxge_fill_tcam_entry_udp_ipv6(p_nxge_t, flow_spec_t *,
513859Sml29623 	tcam_entry_t *);
523859Sml29623 static void nxge_fill_tcam_entry_sctp_ipv6(p_nxge_t, flow_spec_t *,
533859Sml29623 	tcam_entry_t *);
54*11304SJanie.Lu@Sun.COM static uint8_t nxge_get_rdc_offset(p_nxge_t, uint8_t, uint64_t);
55*11304SJanie.Lu@Sun.COM static uint8_t nxge_get_rdc_group(p_nxge_t, uint8_t, uint64_t);
56*11304SJanie.Lu@Sun.COM static uint16_t nxge_tcam_get_index(p_nxge_t, uint16_t);
57*11304SJanie.Lu@Sun.COM static uint32_t nxge_tcam_cls_to_flow(uint32_t);
58*11304SJanie.Lu@Sun.COM static uint8_t nxge_iptun_pkt_type_to_pid(uint8_t);
59*11304SJanie.Lu@Sun.COM static npi_status_t nxge_set_iptun_usr_cls_reg(p_nxge_t, uint64_t,
60*11304SJanie.Lu@Sun.COM 					iptun_cfg_t *);
61*11304SJanie.Lu@Sun.COM static boolean_t nxge_is_iptun_cls_present(p_nxge_t, uint8_t, int *);
623859Sml29623 
633859Sml29623 /*
643859Sml29623  * functions used outside this file
653859Sml29623  */
663859Sml29623 nxge_status_t nxge_fflp_config_vlan_table(p_nxge_t, uint16_t);
673859Sml29623 nxge_status_t nxge_fflp_ip_class_config_all(p_nxge_t);
683859Sml29623 nxge_status_t nxge_add_flow(p_nxge_t, flow_resource_t *);
693859Sml29623 static nxge_status_t nxge_tcam_handle_ip_fragment(p_nxge_t);
703859Sml29623 nxge_status_t nxge_add_tcam_entry(p_nxge_t, flow_resource_t *);
713859Sml29623 nxge_status_t nxge_add_fcram_entry(p_nxge_t, flow_resource_t *);
723859Sml29623 nxge_status_t nxge_flow_get_hash(p_nxge_t, flow_resource_t *,
733859Sml29623 	uint32_t *, uint16_t *);
74*11304SJanie.Lu@Sun.COM int nxge_get_valid_tcam_cnt(p_nxge_t);
75*11304SJanie.Lu@Sun.COM void nxge_get_tcam_entry_all(p_nxge_t, rx_class_cfg_t *);
76*11304SJanie.Lu@Sun.COM void nxge_get_tcam_entry(p_nxge_t, flow_resource_t *);
77*11304SJanie.Lu@Sun.COM void nxge_del_tcam_entry(p_nxge_t, uint32_t);
78*11304SJanie.Lu@Sun.COM void nxge_add_iptun_class(p_nxge_t, iptun_cfg_t *, uint8_t *);
79*11304SJanie.Lu@Sun.COM void nxge_cfg_iptun_hash(p_nxge_t, iptun_cfg_t *, uint8_t);
80*11304SJanie.Lu@Sun.COM void nxge_del_iptun_class(p_nxge_t, uint8_t);
81*11304SJanie.Lu@Sun.COM void nxge_get_iptun_class(p_nxge_t, iptun_cfg_t *, uint8_t);
82*11304SJanie.Lu@Sun.COM void nxge_set_ip_cls_sym(p_nxge_t, uint8_t, uint8_t);
83*11304SJanie.Lu@Sun.COM void nxge_get_ip_cls_sym(p_nxge_t, uint8_t, uint8_t *);
84*11304SJanie.Lu@Sun.COM 
853859Sml29623 
863859Sml29623 nxge_status_t
873859Sml29623 nxge_tcam_dump_entry(p_nxge_t nxgep, uint32_t location)
883859Sml29623 {
893859Sml29623 	tcam_entry_t tcam_rdptr;
903859Sml29623 	uint64_t asc_ram = 0;
913859Sml29623 	npi_handle_t handle;
923859Sml29623 	npi_status_t status;
933859Sml29623 
943859Sml29623 	handle = nxgep->npi_reg_handle;
953859Sml29623 
963859Sml29623 	bzero((char *)&tcam_rdptr, sizeof (struct tcam_entry));
973859Sml29623 	status = npi_fflp_tcam_entry_read(handle, (tcam_location_t)location,
986929Smisaki 	    (struct tcam_entry *)&tcam_rdptr);
993859Sml29623 	if (status & NPI_FAILURE) {
1003859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1016929Smisaki 		    " nxge_tcam_dump_entry:"
1026929Smisaki 		    "  tcam read failed at location %d ", location));
1033859Sml29623 		return (NXGE_ERROR);
1043859Sml29623 	}
1053859Sml29623 	status = npi_fflp_tcam_asc_ram_entry_read(handle,
1066929Smisaki 	    (tcam_location_t)location, &asc_ram);
1073859Sml29623 
1083859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "location %x\n"
1096929Smisaki 	    " key:  %llx %llx %llx %llx \n"
1106929Smisaki 	    " mask: %llx %llx %llx %llx \n"
1116929Smisaki 	    " ASC RAM %llx \n", location,
1126929Smisaki 	    tcam_rdptr.key0, tcam_rdptr.key1,
1136929Smisaki 	    tcam_rdptr.key2, tcam_rdptr.key3,
1146929Smisaki 	    tcam_rdptr.mask0, tcam_rdptr.mask1,
1156929Smisaki 	    tcam_rdptr.mask2, tcam_rdptr.mask3, asc_ram));
1163859Sml29623 	return (NXGE_OK);
1173859Sml29623 }
1183859Sml29623 
1193859Sml29623 void
1203859Sml29623 nxge_get_tcam(p_nxge_t nxgep, p_mblk_t mp)
1213859Sml29623 {
1223859Sml29623 	uint32_t tcam_loc;
1233859Sml29623 	int *lptr;
1243859Sml29623 	int location;
1253859Sml29623 
1263859Sml29623 	uint32_t start_location = 0;
1273859Sml29623 	uint32_t stop_location = nxgep->classifier.tcam_size;
1283859Sml29623 	lptr = (int *)mp->b_rptr;
1293859Sml29623 	location = *lptr;
1303859Sml29623 
1313859Sml29623 	if ((location >= nxgep->classifier.tcam_size) || (location < -1)) {
1323859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1336929Smisaki 		    "nxge_tcam_dump: Invalid location %d \n", location));
1343859Sml29623 		return;
1353859Sml29623 	}
1363859Sml29623 	if (location == -1) {
1373859Sml29623 		start_location = 0;
1383859Sml29623 		stop_location = nxgep->classifier.tcam_size;
1393859Sml29623 	} else {
1403859Sml29623 		start_location = location;
1413859Sml29623 		stop_location = location + 1;
1423859Sml29623 	}
1433859Sml29623 	for (tcam_loc = start_location; tcam_loc < stop_location; tcam_loc++)
1443859Sml29623 		(void) nxge_tcam_dump_entry(nxgep, tcam_loc);
1453859Sml29623 }
1463859Sml29623 
1473859Sml29623 /*
1483859Sml29623  * nxge_fflp_vlan_table_invalidate_all
1493859Sml29623  * invalidates the vlan RDC table entries.
1503859Sml29623  * INPUT
1513859Sml29623  * nxge    soft state data structure
1523859Sml29623  * Return
1533859Sml29623  *      NXGE_OK
1543859Sml29623  *      NXGE_ERROR
1553859Sml29623  *
1563859Sml29623  */
1573859Sml29623 
1583859Sml29623 static nxge_status_t
1593859Sml29623 nxge_fflp_vlan_tbl_clear_all(p_nxge_t nxgep)
1603859Sml29623 {
1613859Sml29623 	vlan_id_t vlan_id;
1623859Sml29623 	npi_handle_t handle;
1633859Sml29623 	npi_status_t rs = NPI_SUCCESS;
1643859Sml29623 	vlan_id_t start = 0, stop = NXGE_MAX_VLANS;
1653859Sml29623 
1663859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_vlan_tbl_clear_all "));
1673859Sml29623 	handle = nxgep->npi_reg_handle;
1683859Sml29623 	for (vlan_id = start; vlan_id < stop; vlan_id++) {
1693859Sml29623 		rs = npi_fflp_cfg_vlan_table_clear(handle, vlan_id);
1703859Sml29623 		if (rs != NPI_SUCCESS) {
1713859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1726929Smisaki 			    "VLAN Table invalidate failed for vlan id %d ",
1736929Smisaki 			    vlan_id));
1743859Sml29623 			return (NXGE_ERROR | rs);
1753859Sml29623 		}
1763859Sml29623 	}
1773859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_vlan_tbl_clear_all "));
1783859Sml29623 	return (NXGE_OK);
1793859Sml29623 }
1803859Sml29623 
1813859Sml29623 /*
1823859Sml29623  * The following functions are used by other modules to init
1833859Sml29623  * the fflp module.
1843859Sml29623  * these functions are the basic API used to init
1853859Sml29623  * the fflp modules (tcam, fcram etc ......)
1863859Sml29623  *
1873859Sml29623  * The TCAM search future would be disabled  by default.
1883859Sml29623  */
1893859Sml29623 
1903859Sml29623 static nxge_status_t
1913859Sml29623 nxge_fflp_tcam_init(p_nxge_t nxgep)
1923859Sml29623 {
1933859Sml29623 	uint8_t access_ratio;
1943859Sml29623 	tcam_class_t class;
1953859Sml29623 	npi_status_t rs = NPI_SUCCESS;
1963859Sml29623 	npi_handle_t handle;
1973859Sml29623 
1983859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_tcam_init"));
1993859Sml29623 	handle = nxgep->npi_reg_handle;
2003859Sml29623 
2013859Sml29623 	rs = npi_fflp_cfg_tcam_disable(handle);
2023859Sml29623 	if (rs != NPI_SUCCESS) {
2033859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "failed TCAM Disable\n"));
2043859Sml29623 		return (NXGE_ERROR | rs);
2053859Sml29623 	}
2063859Sml29623 
2073859Sml29623 	access_ratio = nxgep->param_arr[param_tcam_access_ratio].value;
2083859Sml29623 	rs = npi_fflp_cfg_tcam_access(handle, access_ratio);
2093859Sml29623 	if (rs != NPI_SUCCESS) {
2103859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2116929Smisaki 		    "failed TCAM Access cfg\n"));
2123859Sml29623 		return (NXGE_ERROR | rs);
2133859Sml29623 	}
2143859Sml29623 
2153859Sml29623 	/* disable configurable classes */
2163859Sml29623 	/* disable the configurable ethernet classes; */
2173859Sml29623 	for (class = TCAM_CLASS_ETYPE_1;
2186929Smisaki 	    class <= TCAM_CLASS_ETYPE_2; class++) {
2193859Sml29623 		rs = npi_fflp_cfg_enet_usr_cls_disable(handle, class);
2203859Sml29623 		if (rs != NPI_SUCCESS) {
2213859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2226929Smisaki 			    "TCAM USR Ether Class config failed."));
2233859Sml29623 			return (NXGE_ERROR | rs);
2243859Sml29623 		}
2253859Sml29623 	}
2263859Sml29623 
2273859Sml29623 	/* disable the configurable ip classes; */
2283859Sml29623 	for (class = TCAM_CLASS_IP_USER_4;
2296929Smisaki 	    class <= TCAM_CLASS_IP_USER_7; class++) {
2303859Sml29623 		rs = npi_fflp_cfg_ip_usr_cls_disable(handle, class);
2313859Sml29623 		if (rs != NPI_SUCCESS) {
2323859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2336929Smisaki 			    "TCAM USR IP Class cnfg failed."));
2343859Sml29623 			return (NXGE_ERROR | rs);
2353859Sml29623 		}
2363859Sml29623 	}
2373859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_tcam_init"));
2383859Sml29623 	return (NXGE_OK);
2393859Sml29623 }
2403859Sml29623 
2413859Sml29623 /*
2423859Sml29623  * nxge_fflp_tcam_invalidate_all
2433859Sml29623  * invalidates all the tcam entries.
2443859Sml29623  * INPUT
2453859Sml29623  * nxge    soft state data structure
2463859Sml29623  * Return
2473859Sml29623  *      NXGE_OK
2483859Sml29623  *      NXGE_ERROR
2493859Sml29623  *
2503859Sml29623  */
2513859Sml29623 
2523859Sml29623 
2533859Sml29623 static nxge_status_t
2543859Sml29623 nxge_fflp_tcam_invalidate_all(p_nxge_t nxgep)
2553859Sml29623 {
2563859Sml29623 	uint16_t location;
2573859Sml29623 	npi_status_t rs = NPI_SUCCESS;
2583859Sml29623 	npi_handle_t handle;
2593859Sml29623 	uint16_t start = 0, stop = nxgep->classifier.tcam_size;
2603859Sml29623 	p_nxge_hw_list_t hw_p;
2613859Sml29623 
2623859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
2636929Smisaki 	    "==> nxge_fflp_tcam_invalidate_all"));
2643859Sml29623 	handle = nxgep->npi_reg_handle;
2653859Sml29623 	if ((hw_p = nxgep->nxge_hw_p) == NULL) {
2663859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2676929Smisaki 		    " nxge_fflp_tcam_invalidate_all:"
2686929Smisaki 		    " common hardware not set", nxgep->niu_type));
2693859Sml29623 		return (NXGE_ERROR);
2703859Sml29623 	}
2713859Sml29623 	MUTEX_ENTER(&hw_p->nxge_tcam_lock);
2723859Sml29623 	for (location = start; location < stop; location++) {
2733859Sml29623 		rs = npi_fflp_tcam_entry_invalidate(handle, location);
2743859Sml29623 		if (rs != NPI_SUCCESS) {
2753859Sml29623 			MUTEX_EXIT(&hw_p->nxge_tcam_lock);
2763859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2776929Smisaki 			    "TCAM invalidate failed at loc %d ", location));
2783859Sml29623 			return (NXGE_ERROR | rs);
2793859Sml29623 		}
2803859Sml29623 	}
2813859Sml29623 	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
2823859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
2836929Smisaki 	    "<== nxge_fflp_tcam_invalidate_all"));
2843859Sml29623 	return (NXGE_OK);
2853859Sml29623 }
2863859Sml29623 
2873859Sml29623 /*
2883859Sml29623  * nxge_fflp_fcram_entry_invalidate_all
2893859Sml29623  * invalidates all the FCRAM entries.
2903859Sml29623  * INPUT
2913859Sml29623  * nxge    soft state data structure
2923859Sml29623  * Return
2933859Sml29623  *      NXGE_OK
2943859Sml29623  *      NXGE_ERROR
2953859Sml29623  *
2963859Sml29623  */
2973859Sml29623 
2983859Sml29623 static nxge_status_t
2993859Sml29623 nxge_fflp_fcram_invalidate_all(p_nxge_t nxgep)
3003859Sml29623 {
3013859Sml29623 	npi_handle_t handle;
3023859Sml29623 	npi_status_t rs = NPI_SUCCESS;
3033859Sml29623 	part_id_t pid = 0;
3043859Sml29623 	uint8_t base_mask, base_reloc;
3053859Sml29623 	fcram_entry_t fc;
3063859Sml29623 	uint32_t location;
3073859Sml29623 	uint32_t increment, last_location;
3083859Sml29623 
3093859Sml29623 	/*
3103859Sml29623 	 * (1) configure and enable partition 0 with no relocation
3113859Sml29623 	 * (2) Assume the FCRAM is used as IPv4 exact match entry cells
3123859Sml29623 	 * (3) Invalidate these cells by clearing the valid bit in
3133859Sml29623 	 * the subareas 0 and 4
3143859Sml29623 	 * (4) disable the partition
3153859Sml29623 	 *
3163859Sml29623 	 */
3173859Sml29623 
3183859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_fcram_invalidate_all"));
3193859Sml29623 
3203859Sml29623 	base_mask = base_reloc = 0x0;
3213859Sml29623 	handle = nxgep->npi_reg_handle;
3223859Sml29623 	rs = npi_fflp_cfg_fcram_partition(handle, pid, base_mask, base_reloc);
3233859Sml29623 
3243859Sml29623 	if (rs != NPI_SUCCESS) {
3253859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "failed partition cfg\n"));
3263859Sml29623 		return (NXGE_ERROR | rs);
3273859Sml29623 	}
3283859Sml29623 	rs = npi_fflp_cfg_fcram_partition_disable(handle, pid);
3293859Sml29623 
3303859Sml29623 	if (rs != NPI_SUCCESS) {
3313859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3326929Smisaki 		    "failed partition enable\n"));
3333859Sml29623 		return (NXGE_ERROR | rs);
3343859Sml29623 	}
3353859Sml29623 	fc.dreg[0].value = 0;
3363859Sml29623 	fc.hash_hdr_valid = 0;
3373859Sml29623 	fc.hash_hdr_ext = 1;	/* specify as IPV4 exact match entry */
3383859Sml29623 	increment = sizeof (hash_ipv4_t);
3393859Sml29623 	last_location = FCRAM_SIZE * 0x40;
3403859Sml29623 
3413859Sml29623 	for (location = 0; location < last_location; location += increment) {
3423859Sml29623 		rs = npi_fflp_fcram_subarea_write(handle, pid,
3436929Smisaki 		    location, fc.value[0]);
3443859Sml29623 		if (rs != NPI_SUCCESS) {
3453859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3466929Smisaki 			    "failed write at location %x ", location));
3473859Sml29623 			return (NXGE_ERROR | rs);
3483859Sml29623 		}
3493859Sml29623 	}
3503859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_fcram_invalidate_all"));
3513859Sml29623 	return (NXGE_OK);
3523859Sml29623 }
3533859Sml29623 
3543859Sml29623 static nxge_status_t
3553859Sml29623 nxge_fflp_fcram_init(p_nxge_t nxgep)
3563859Sml29623 {
3573859Sml29623 	fflp_fcram_output_drive_t strength;
3583859Sml29623 	fflp_fcram_qs_t qs;
3593859Sml29623 	npi_status_t rs = NPI_SUCCESS;
3603859Sml29623 	uint8_t access_ratio;
3613859Sml29623 	int partition;
3623859Sml29623 	npi_handle_t handle;
3633859Sml29623 	uint32_t min_time, max_time, sys_time;
3643859Sml29623 
3653859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_fcram_init"));
3663859Sml29623 
3673859Sml29623 	/*
3683859Sml29623 	 * Recommended values are needed.
3693859Sml29623 	 */
3703859Sml29623 	min_time = FCRAM_REFRESH_DEFAULT_MIN_TIME;
3713859Sml29623 	max_time = FCRAM_REFRESH_DEFAULT_MAX_TIME;
3723859Sml29623 	sys_time = FCRAM_REFRESH_DEFAULT_SYS_TIME;
3733859Sml29623 
3743859Sml29623 	handle = nxgep->npi_reg_handle;
3753859Sml29623 	strength = FCRAM_OUTDR_NORMAL;
3763859Sml29623 	qs = FCRAM_QS_MODE_QS;
3773859Sml29623 	rs = npi_fflp_cfg_fcram_reset(handle, strength, qs);
3783859Sml29623 	if (rs != NPI_SUCCESS) {
3793859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "failed FCRAM Reset. "));
3803859Sml29623 		return (NXGE_ERROR | rs);
3813859Sml29623 	}
3823859Sml29623 
3833859Sml29623 	access_ratio = nxgep->param_arr[param_fcram_access_ratio].value;
3843859Sml29623 	rs = npi_fflp_cfg_fcram_access(handle, access_ratio);
3853859Sml29623 	if (rs != NPI_SUCCESS) {
3863859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "failed FCRAM Access ratio"
3876929Smisaki 		    "configuration \n"));
3883859Sml29623 		return (NXGE_ERROR | rs);
3893859Sml29623 	}
3903859Sml29623 	rs = npi_fflp_cfg_fcram_refresh_time(handle, min_time,
3916929Smisaki 	    max_time, sys_time);
3923859Sml29623 	if (rs != NPI_SUCCESS) {
3933859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3946929Smisaki 		    "failed FCRAM refresh cfg"));
3953859Sml29623 		return (NXGE_ERROR);
3963859Sml29623 	}
3973859Sml29623 
3983859Sml29623 	/* disable all the partitions until explicitly enabled */
3993859Sml29623 	for (partition = 0; partition < FFLP_FCRAM_MAX_PARTITION; partition++) {
4003859Sml29623 		rs = npi_fflp_cfg_fcram_partition_disable(handle, partition);
4013859Sml29623 		if (rs != NPI_SUCCESS) {
4023859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4036929Smisaki 			    "failed FCRAM partition"
4046929Smisaki 			    " enable for partition %d ", partition));
4053859Sml29623 			return (NXGE_ERROR | rs);
4063859Sml29623 		}
4073859Sml29623 	}
4083859Sml29623 
4093859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_fcram_init"));
4103859Sml29623 	return (NXGE_OK);
4113859Sml29623 }
4123859Sml29623 
4133859Sml29623 nxge_status_t
4143859Sml29623 nxge_logical_mac_assign_rdc_table(p_nxge_t nxgep, uint8_t alt_mac)
4153859Sml29623 {
4163859Sml29623 	npi_status_t rs = NPI_SUCCESS;
4173859Sml29623 	hostinfo_t mac_rdc;
4183859Sml29623 	npi_handle_t handle;
4193859Sml29623 	p_nxge_class_pt_cfg_t p_class_cfgp;
4203859Sml29623 
4213859Sml29623 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
4223859Sml29623 	if (p_class_cfgp->mac_host_info[alt_mac].flag == 0) {
4233859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4246929Smisaki 		    " nxge_logical_mac_assign_rdc_table"
4256929Smisaki 		    " unconfigured alt MAC addr %d ", alt_mac));
4263859Sml29623 		return (NXGE_ERROR);
4273859Sml29623 	}
4283859Sml29623 	handle = nxgep->npi_reg_handle;
4293859Sml29623 	mac_rdc.value = 0;
4303859Sml29623 	mac_rdc.bits.w0.rdc_tbl_num =
4316929Smisaki 	    p_class_cfgp->mac_host_info[alt_mac].rdctbl;
4323859Sml29623 	mac_rdc.bits.w0.mac_pref = p_class_cfgp->mac_host_info[alt_mac].mpr_npr;
4333859Sml29623 
4343859Sml29623 	rs = npi_mac_hostinfo_entry(handle, OP_SET,
4356929Smisaki 	    nxgep->function_num, alt_mac, &mac_rdc);
4363859Sml29623 
4373859Sml29623 	if (rs != NPI_SUCCESS) {
4383859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4396929Smisaki 		    "failed Assign RDC table"));
4403859Sml29623 		return (NXGE_ERROR | rs);
4413859Sml29623 	}
4423859Sml29623 	return (NXGE_OK);
4433859Sml29623 }
4443859Sml29623 
4453859Sml29623 nxge_status_t
4463859Sml29623 nxge_main_mac_assign_rdc_table(p_nxge_t nxgep)
4473859Sml29623 {
4483859Sml29623 	npi_status_t rs = NPI_SUCCESS;
4493859Sml29623 	hostinfo_t mac_rdc;
4503859Sml29623 	npi_handle_t handle;
4513859Sml29623 
4523859Sml29623 	handle = nxgep->npi_reg_handle;
4533859Sml29623 	mac_rdc.value = 0;
4543859Sml29623 	mac_rdc.bits.w0.rdc_tbl_num = nxgep->class_config.mac_rdcgrp;
4553859Sml29623 	mac_rdc.bits.w0.mac_pref = 1;
4563859Sml29623 	switch (nxgep->function_num) {
4573859Sml29623 	case 0:
4583859Sml29623 	case 1:
4593859Sml29623 		rs = npi_mac_hostinfo_entry(handle, OP_SET,
4606929Smisaki 		    nxgep->function_num, XMAC_UNIQUE_HOST_INFO_ENTRY, &mac_rdc);
4613859Sml29623 		break;
4623859Sml29623 	case 2:
4633859Sml29623 	case 3:
4643859Sml29623 		rs = npi_mac_hostinfo_entry(handle, OP_SET,
4656929Smisaki 		    nxgep->function_num, BMAC_UNIQUE_HOST_INFO_ENTRY, &mac_rdc);
4663859Sml29623 		break;
4673859Sml29623 	default:
4683859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4696929Smisaki 		    "failed Assign RDC table (invalid function #)"));
4703859Sml29623 		return (NXGE_ERROR);
4713859Sml29623 	}
4723859Sml29623 
4733859Sml29623 	if (rs != NPI_SUCCESS) {
4743859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4756929Smisaki 		    "failed Assign RDC table"));
4763859Sml29623 		return (NXGE_ERROR | rs);
4773859Sml29623 	}
4783859Sml29623 	return (NXGE_OK);
4793859Sml29623 }
4803859Sml29623 
4813859Sml29623 /*
4823859Sml29623  * Initialize hostinfo registers for alternate MAC addresses and
4833859Sml29623  * multicast MAC address.
4843859Sml29623  */
4853859Sml29623 nxge_status_t
4863859Sml29623 nxge_alt_mcast_mac_assign_rdc_table(p_nxge_t nxgep)
4873859Sml29623 {
4883859Sml29623 	npi_status_t rs = NPI_SUCCESS;
4893859Sml29623 	hostinfo_t mac_rdc;
4903859Sml29623 	npi_handle_t handle;
4913859Sml29623 	int i;
4923859Sml29623 
4933859Sml29623 	handle = nxgep->npi_reg_handle;
4943859Sml29623 	mac_rdc.value = 0;
4953859Sml29623 	mac_rdc.bits.w0.rdc_tbl_num = nxgep->class_config.mcast_rdcgrp;
4963859Sml29623 	mac_rdc.bits.w0.mac_pref = 1;
4973859Sml29623 	switch (nxgep->function_num) {
4983859Sml29623 	case 0:
4993859Sml29623 	case 1:
5003859Sml29623 		/*
5013859Sml29623 		 * Tests indicate that it is OK not to re-initialize the
5023859Sml29623 		 * hostinfo registers for the XMAC's alternate MAC
5033859Sml29623 		 * addresses. But that is necessary for BMAC (case 2
5043859Sml29623 		 * and case 3 below)
5053859Sml29623 		 */
5063859Sml29623 		rs = npi_mac_hostinfo_entry(handle, OP_SET,
5076929Smisaki 		    nxgep->function_num,
5086929Smisaki 		    XMAC_MULTI_HOST_INFO_ENTRY, &mac_rdc);
5093859Sml29623 		break;
5103859Sml29623 	case 2:
5113859Sml29623 	case 3:
5123859Sml29623 		for (i = 1; i <= BMAC_MAX_ALT_ADDR_ENTRY; i++)
5133859Sml29623 			rs |= npi_mac_hostinfo_entry(handle, OP_SET,
5146929Smisaki 			    nxgep->function_num, i, &mac_rdc);
5153859Sml29623 
5163859Sml29623 		rs |= npi_mac_hostinfo_entry(handle, OP_SET,
5176929Smisaki 		    nxgep->function_num,
5186929Smisaki 		    BMAC_MULTI_HOST_INFO_ENTRY, &mac_rdc);
5193859Sml29623 		break;
5203859Sml29623 	default:
5213859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5226929Smisaki 		    "failed Assign RDC table (invalid function #)"));
5233859Sml29623 		return (NXGE_ERROR);
5243859Sml29623 	}
5253859Sml29623 
5263859Sml29623 	if (rs != NPI_SUCCESS) {
5273859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5286929Smisaki 		    "failed Assign RDC table"));
5293859Sml29623 		return (NXGE_ERROR | rs);
5303859Sml29623 	}
5313859Sml29623 	return (NXGE_OK);
5323859Sml29623 }
5333859Sml29623 
5343859Sml29623 nxge_status_t
5353859Sml29623 nxge_fflp_init_hostinfo(p_nxge_t nxgep)
5363859Sml29623 {
5373859Sml29623 	nxge_status_t status = NXGE_OK;
5383859Sml29623 
5393859Sml29623 	status = nxge_alt_mcast_mac_assign_rdc_table(nxgep);
5403859Sml29623 	status |= nxge_main_mac_assign_rdc_table(nxgep);
5413859Sml29623 	return (status);
5423859Sml29623 }
5433859Sml29623 
5443859Sml29623 nxge_status_t
5453859Sml29623 nxge_fflp_hw_reset(p_nxge_t nxgep)
5463859Sml29623 {
5473859Sml29623 	npi_handle_t handle;
5483859Sml29623 	npi_status_t rs = NPI_SUCCESS;
5493859Sml29623 	nxge_status_t status = NXGE_OK;
5503859Sml29623 
5513859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_hw_reset"));
5523859Sml29623 
5534977Sraghus 	if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
5543859Sml29623 		status = nxge_fflp_fcram_init(nxgep);
5553859Sml29623 		if (status != NXGE_OK) {
5563859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5576929Smisaki 			    " failed FCRAM init. "));
5583859Sml29623 			return (status);
5593859Sml29623 		}
5603859Sml29623 	}
5613859Sml29623 
5623859Sml29623 	status = nxge_fflp_tcam_init(nxgep);
5633859Sml29623 	if (status != NXGE_OK) {
5643859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5656929Smisaki 		    "failed TCAM init."));
5663859Sml29623 		return (status);
5673859Sml29623 	}
5683859Sml29623 
5693859Sml29623 	handle = nxgep->npi_reg_handle;
5703859Sml29623 	rs = npi_fflp_cfg_llcsnap_enable(handle);
5713859Sml29623 	if (rs != NPI_SUCCESS) {
5723859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5736929Smisaki 		    "failed LLCSNAP enable. "));
5743859Sml29623 		return (NXGE_ERROR | rs);
5753859Sml29623 	}
5763859Sml29623 
5773859Sml29623 	rs = npi_fflp_cfg_cam_errorcheck_disable(handle);
5783859Sml29623 	if (rs != NPI_SUCCESS) {
5793859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5806929Smisaki 		    "failed CAM Error Check enable. "));
5813859Sml29623 		return (NXGE_ERROR | rs);
5823859Sml29623 	}
5833859Sml29623 
5843859Sml29623 	/* init the hash generators */
5853859Sml29623 	rs = npi_fflp_cfg_hash_h1poly(handle, 0);
5863859Sml29623 	if (rs != NPI_SUCCESS) {
5873859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5886929Smisaki 		    "failed H1 Poly Init. "));
5893859Sml29623 		return (NXGE_ERROR | rs);
5903859Sml29623 	}
5913859Sml29623 
5923859Sml29623 	rs = npi_fflp_cfg_hash_h2poly(handle, 0);
5933859Sml29623 	if (rs != NPI_SUCCESS) {
5943859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5956929Smisaki 		    "failed H2 Poly Init. "));
5963859Sml29623 		return (NXGE_ERROR | rs);
5973859Sml29623 	}
5983859Sml29623 
5993859Sml29623 	/* invalidate TCAM entries */
6003859Sml29623 	status = nxge_fflp_tcam_invalidate_all(nxgep);
6013859Sml29623 	if (status != NXGE_OK) {
6023859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6036929Smisaki 		    "failed TCAM Entry Invalidate. "));
6043859Sml29623 		return (status);
6053859Sml29623 	}
6063859Sml29623 
6073859Sml29623 	/* invalidate FCRAM entries */
6084977Sraghus 	if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
6093859Sml29623 		status = nxge_fflp_fcram_invalidate_all(nxgep);
6103859Sml29623 		if (status != NXGE_OK) {
6113859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6126929Smisaki 			    "failed FCRAM Entry Invalidate."));
6133859Sml29623 			return (status);
6143859Sml29623 		}
6153859Sml29623 	}
6163859Sml29623 
6173859Sml29623 	/* invalidate VLAN RDC tables */
6183859Sml29623 	status = nxge_fflp_vlan_tbl_clear_all(nxgep);
6193859Sml29623 	if (status != NXGE_OK) {
6203859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6216929Smisaki 		    "failed VLAN Table Invalidate. "));
6223859Sml29623 		return (status);
6233859Sml29623 	}
6243859Sml29623 	nxgep->classifier.state |= NXGE_FFLP_HW_RESET;
6253859Sml29623 
6263859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_hw_reset"));
6273859Sml29623 	return (NXGE_OK);
6283859Sml29623 }
6293859Sml29623 
6303859Sml29623 nxge_status_t
6313859Sml29623 nxge_cfg_ip_cls_flow_key(p_nxge_t nxgep, tcam_class_t l3_class,
6323859Sml29623 	uint32_t class_config)
6333859Sml29623 {
6343859Sml29623 	flow_key_cfg_t fcfg;
6353859Sml29623 	npi_handle_t handle;
6363859Sml29623 	npi_status_t rs = NPI_SUCCESS;
6373859Sml29623 
6383859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_cfg_ip_cls_flow_key"));
6393859Sml29623 	handle = nxgep->npi_reg_handle;
6403859Sml29623 	bzero(&fcfg, sizeof (flow_key_cfg_t));
6413859Sml29623 
6423859Sml29623 	if (class_config & NXGE_CLASS_FLOW_USE_PROTO)
6433859Sml29623 		fcfg.use_proto = 1;
6443859Sml29623 	if (class_config & NXGE_CLASS_FLOW_USE_DST_PORT)
6453859Sml29623 		fcfg.use_dport = 1;
6463859Sml29623 	if (class_config & NXGE_CLASS_FLOW_USE_SRC_PORT)
6473859Sml29623 		fcfg.use_sport = 1;
6483859Sml29623 	if (class_config & NXGE_CLASS_FLOW_USE_IPDST)
6493859Sml29623 		fcfg.use_daddr = 1;
6503859Sml29623 	if (class_config & NXGE_CLASS_FLOW_USE_IPSRC)
6513859Sml29623 		fcfg.use_saddr = 1;
6523859Sml29623 	if (class_config & NXGE_CLASS_FLOW_USE_VLAN)
6533859Sml29623 		fcfg.use_vlan = 1;
6543859Sml29623 	if (class_config & NXGE_CLASS_FLOW_USE_L2DA)
6553859Sml29623 		fcfg.use_l2da = 1;
6563859Sml29623 	if (class_config & NXGE_CLASS_FLOW_USE_PORTNUM)
6573859Sml29623 		fcfg.use_portnum = 1;
6583859Sml29623 	fcfg.ip_opts_exist = 0;
6593859Sml29623 
6603859Sml29623 	rs = npi_fflp_cfg_ip_cls_flow_key(handle, l3_class, &fcfg);
6613859Sml29623 	if (rs & NPI_FFLP_ERROR) {
6623859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_ip_cls_flow_key"
6636929Smisaki 		    " opt %x for class %d failed ", class_config, l3_class));
6643859Sml29623 		return (NXGE_ERROR | rs);
6653859Sml29623 	}
6663859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_cfg_ip_cls_flow_key"));
6673859Sml29623 	return (NXGE_OK);
6683859Sml29623 }
6693859Sml29623 
6703859Sml29623 nxge_status_t
6713859Sml29623 nxge_cfg_ip_cls_flow_key_get(p_nxge_t nxgep, tcam_class_t l3_class,
6723859Sml29623 	uint32_t *class_config)
6733859Sml29623 {
6743859Sml29623 	flow_key_cfg_t fcfg;
6753859Sml29623 	npi_handle_t handle;
6763859Sml29623 	npi_status_t rs = NPI_SUCCESS;
6773859Sml29623 	uint32_t ccfg = 0;
6783859Sml29623 
6793859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_cfg_ip_cls_flow_key_get"));
6803859Sml29623 	handle = nxgep->npi_reg_handle;
6813859Sml29623 	bzero(&fcfg, sizeof (flow_key_cfg_t));
6823859Sml29623 
6833859Sml29623 	rs = npi_fflp_cfg_ip_cls_flow_key_get(handle, l3_class, &fcfg);
6843859Sml29623 	if (rs & NPI_FFLP_ERROR) {
6853859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_ip_cls_flow_key"
6866929Smisaki 		    " opt %x for class %d failed ", class_config, l3_class));
6873859Sml29623 		return (NXGE_ERROR | rs);
6883859Sml29623 	}
6893859Sml29623 
6903859Sml29623 	if (fcfg.use_proto)
6913859Sml29623 		ccfg |= NXGE_CLASS_FLOW_USE_PROTO;
6923859Sml29623 	if (fcfg.use_dport)
6933859Sml29623 		ccfg |= NXGE_CLASS_FLOW_USE_DST_PORT;
6943859Sml29623 	if (fcfg.use_sport)
6953859Sml29623 		ccfg |= NXGE_CLASS_FLOW_USE_SRC_PORT;
6963859Sml29623 	if (fcfg.use_daddr)
6973859Sml29623 		ccfg |= NXGE_CLASS_FLOW_USE_IPDST;
6983859Sml29623 	if (fcfg.use_saddr)
6993859Sml29623 		ccfg |= NXGE_CLASS_FLOW_USE_IPSRC;
7003859Sml29623 	if (fcfg.use_vlan)
7013859Sml29623 		ccfg |= NXGE_CLASS_FLOW_USE_VLAN;
7023859Sml29623 	if (fcfg.use_l2da)
7033859Sml29623 		ccfg |= NXGE_CLASS_FLOW_USE_L2DA;
7043859Sml29623 	if (fcfg.use_portnum)
7053859Sml29623 		ccfg |= NXGE_CLASS_FLOW_USE_PORTNUM;
7063859Sml29623 
7073859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
7086929Smisaki 	    " nxge_cfg_ip_cls_flow_key_get %x", ccfg));
7093859Sml29623 	*class_config = ccfg;
7103859Sml29623 
7113859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
7126929Smisaki 	    " <== nxge_cfg_ip_cls_flow_key_get"));
7133859Sml29623 	return (NXGE_OK);
7143859Sml29623 }
7153859Sml29623 
7163859Sml29623 static nxge_status_t
7173859Sml29623 nxge_cfg_tcam_ip_class_get(p_nxge_t nxgep, tcam_class_t class,
7183859Sml29623 	uint32_t *class_config)
7193859Sml29623 {
7203859Sml29623 	npi_status_t rs = NPI_SUCCESS;
7213859Sml29623 	tcam_key_cfg_t cfg;
7223859Sml29623 	npi_handle_t handle;
7233859Sml29623 	uint32_t ccfg = 0;
7243859Sml29623 
7253859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_cfg_tcam_ip_class"));
7263859Sml29623 
7273859Sml29623 	bzero(&cfg, sizeof (tcam_key_cfg_t));
7283859Sml29623 	handle = nxgep->npi_reg_handle;
7293859Sml29623 
7303859Sml29623 	rs = npi_fflp_cfg_ip_cls_tcam_key_get(handle, class, &cfg);
7313859Sml29623 	if (rs & NPI_FFLP_ERROR) {
7323859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_tcam_ip_class"
7336929Smisaki 		    " opt %x for class %d failed ", class_config, class));
7343859Sml29623 		return (NXGE_ERROR | rs);
7353859Sml29623 	}
7363859Sml29623 	if (cfg.discard)
7373859Sml29623 		ccfg |= NXGE_CLASS_DISCARD;
7383859Sml29623 	if (cfg.lookup_enable)
7393859Sml29623 		ccfg |= NXGE_CLASS_TCAM_LOOKUP;
7403859Sml29623 	if (cfg.use_ip_daddr)
7413859Sml29623 		ccfg |= NXGE_CLASS_TCAM_USE_SRC_ADDR;
7423859Sml29623 	*class_config = ccfg;
7433859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
7446929Smisaki 	    " ==> nxge_cfg_tcam_ip_class %x", ccfg));
7453859Sml29623 	return (NXGE_OK);
7463859Sml29623 }
7473859Sml29623 
7483859Sml29623 static nxge_status_t
7493859Sml29623 nxge_cfg_tcam_ip_class(p_nxge_t nxgep, tcam_class_t class,
7503859Sml29623 	uint32_t class_config)
7513859Sml29623 {
7523859Sml29623 	npi_status_t rs = NPI_SUCCESS;
7533859Sml29623 	tcam_key_cfg_t cfg;
7543859Sml29623 	npi_handle_t handle;
7553859Sml29623 	p_nxge_class_pt_cfg_t p_class_cfgp;
7563859Sml29623 
7573859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_cfg_tcam_ip_class"));
7583859Sml29623 
7593859Sml29623 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
7603859Sml29623 	p_class_cfgp->class_cfg[class] = class_config;
7613859Sml29623 
7623859Sml29623 	bzero(&cfg, sizeof (tcam_key_cfg_t));
7633859Sml29623 	handle = nxgep->npi_reg_handle;
7643859Sml29623 	cfg.discard = 0;
7653859Sml29623 	cfg.lookup_enable = 0;
7663859Sml29623 	cfg.use_ip_daddr = 0;
7673859Sml29623 	if (class_config & NXGE_CLASS_DISCARD)
7683859Sml29623 		cfg.discard = 1;
7693859Sml29623 	if (class_config & NXGE_CLASS_TCAM_LOOKUP)
7703859Sml29623 		cfg.lookup_enable = 1;
7713859Sml29623 	if (class_config & NXGE_CLASS_TCAM_USE_SRC_ADDR)
7723859Sml29623 		cfg.use_ip_daddr = 1;
7733859Sml29623 
7743859Sml29623 	rs = npi_fflp_cfg_ip_cls_tcam_key(handle, class, &cfg);
7753859Sml29623 	if (rs & NPI_FFLP_ERROR) {
7763859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_tcam_ip_class"
7776929Smisaki 		    " opt %x for class %d failed ", class_config, class));
7783859Sml29623 		return (NXGE_ERROR | rs);
7793859Sml29623 	}
7803859Sml29623 	return (NXGE_OK);
7813859Sml29623 }
7823859Sml29623 
7833859Sml29623 nxge_status_t
7843859Sml29623 nxge_fflp_set_hash1(p_nxge_t nxgep, uint32_t h1)
7853859Sml29623 {
7863859Sml29623 	npi_status_t rs = NPI_SUCCESS;
7873859Sml29623 	npi_handle_t handle;
7883859Sml29623 	p_nxge_class_pt_cfg_t p_class_cfgp;
7893859Sml29623 
7903859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_init_h1"));
7913859Sml29623 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
7923859Sml29623 	p_class_cfgp->init_h1 = h1;
7933859Sml29623 	handle = nxgep->npi_reg_handle;
7943859Sml29623 	rs = npi_fflp_cfg_hash_h1poly(handle, h1);
7953859Sml29623 	if (rs & NPI_FFLP_ERROR) {
7963859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7976929Smisaki 		    " nxge_fflp_init_h1 %x failed ", h1));
7983859Sml29623 		return (NXGE_ERROR | rs);
7993859Sml29623 	}
8003859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_fflp_init_h1"));
8013859Sml29623 	return (NXGE_OK);
8023859Sml29623 }
8033859Sml29623 
8043859Sml29623 nxge_status_t
8053859Sml29623 nxge_fflp_set_hash2(p_nxge_t nxgep, uint16_t h2)
8063859Sml29623 {
8073859Sml29623 	npi_status_t rs = NPI_SUCCESS;
8083859Sml29623 	npi_handle_t handle;
8093859Sml29623 	p_nxge_class_pt_cfg_t p_class_cfgp;
8103859Sml29623 
8113859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_init_h2"));
8123859Sml29623 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
8133859Sml29623 	p_class_cfgp->init_h2 = h2;
8143859Sml29623 
8153859Sml29623 	handle = nxgep->npi_reg_handle;
8163859Sml29623 	rs = npi_fflp_cfg_hash_h2poly(handle, h2);
8173859Sml29623 	if (rs & NPI_FFLP_ERROR) {
8183859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8196929Smisaki 		    " nxge_fflp_init_h2 %x failed ", h2));
8203859Sml29623 		return (NXGE_ERROR | rs);
8213859Sml29623 	}
8223859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_fflp_init_h2"));
8233859Sml29623 	return (NXGE_OK);
8243859Sml29623 }
8253859Sml29623 
8263859Sml29623 nxge_status_t
8273859Sml29623 nxge_classify_init_sw(p_nxge_t nxgep)
8283859Sml29623 {
8293859Sml29623 	nxge_classify_t *classify_ptr;
8303859Sml29623 
8313859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_classify_init_sw"));
8323859Sml29623 	classify_ptr = &nxgep->classifier;
8333859Sml29623 
8343859Sml29623 	if (classify_ptr->state & NXGE_FFLP_SW_INIT) {
8353859Sml29623 		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
8366929Smisaki 		    "nxge_classify_init_sw already init"));
8373859Sml29623 		return (NXGE_OK);
8383859Sml29623 	}
839*11304SJanie.Lu@Sun.COM 
840*11304SJanie.Lu@Sun.COM 	classify_ptr->tcam_size = nxgep->nxge_hw_p->tcam_size / nxgep->nports;
841*11304SJanie.Lu@Sun.COM 	classify_ptr->tcam_entries = (tcam_flow_spec_t *)nxgep->nxge_hw_p->tcam;
842*11304SJanie.Lu@Sun.COM 	classify_ptr->tcam_top = nxgep->function_num;
8433859Sml29623 
8443859Sml29623 	/* Init defaults */
8453859Sml29623 	/*
8463859Sml29623 	 * add hacks required for HW shortcomings for example, code to handle
8473859Sml29623 	 * fragmented packets
8483859Sml29623 	 */
8493859Sml29623 	nxge_init_h1_table();
8503859Sml29623 	nxge_crc_ccitt_init();
8513859Sml29623 	nxgep->classifier.tcam_location = nxgep->function_num;
8523859Sml29623 	nxgep->classifier.fragment_bug = 1;
8533859Sml29623 	classify_ptr->state |= NXGE_FFLP_SW_INIT;
8543859Sml29623 
8553859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_classify_init_sw"));
8563859Sml29623 	return (NXGE_OK);
8573859Sml29623 }
8583859Sml29623 
8593859Sml29623 nxge_status_t
8603859Sml29623 nxge_classify_exit_sw(p_nxge_t nxgep)
8613859Sml29623 {
8623859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_classify_exit_sw"));
8633859Sml29623 	nxgep->classifier.state = NULL;
8643859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_classify_exit_sw"));
8653859Sml29623 	return (NXGE_OK);
8663859Sml29623 }
8673859Sml29623 
8683859Sml29623 /*
8693859Sml29623  * Figures out the RDC Group for the entry
8703859Sml29623  *
8713859Sml29623  * The current implementation is just a place holder and it
8723859Sml29623  * returns 0.
8733859Sml29623  * The real location determining algorithm would consider
8743859Sml29623  * the partition etc ... before deciding w
8753859Sml29623  *
8763859Sml29623  */
8773859Sml29623 
8783859Sml29623 /* ARGSUSED */
8793859Sml29623 static uint8_t
880*11304SJanie.Lu@Sun.COM nxge_get_rdc_group(p_nxge_t nxgep, uint8_t class, uint64_t cookie)
8813859Sml29623 {
8823859Sml29623 	int use_port_rdc_grp = 0;
8833859Sml29623 	uint8_t rdc_grp = 0;
8843859Sml29623 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
8853859Sml29623 	p_nxge_hw_pt_cfg_t p_cfgp;
8863859Sml29623 	p_nxge_rdc_grp_t rdc_grp_p;
8873859Sml29623 
8883859Sml29623 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
8893859Sml29623 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
8903859Sml29623 	rdc_grp_p = &p_dma_cfgp->rdc_grps[use_port_rdc_grp];
8916495Sspeer 	rdc_grp = p_cfgp->def_mac_rxdma_grpid;
8923859Sml29623 
8933859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8946929Smisaki 	    "nxge_get_rdc_group: grp 0x%x real_grp %x grpp $%p\n",
8956929Smisaki 	    cookie, rdc_grp, rdc_grp_p));
8963859Sml29623 	return (rdc_grp);
8973859Sml29623 }
8983859Sml29623 
8993859Sml29623 /* ARGSUSED */
9003859Sml29623 static uint8_t
901*11304SJanie.Lu@Sun.COM nxge_get_rdc_offset(p_nxge_t nxgep, uint8_t class, uint64_t cookie)
9023859Sml29623 {
9033859Sml29623 	return ((uint8_t)cookie);
9043859Sml29623 }
9053859Sml29623 
9063859Sml29623 /* ARGSUSED */
9073859Sml29623 static void
9083859Sml29623 nxge_fill_tcam_entry_udp(p_nxge_t nxgep, flow_spec_t *flow_spec,
9093859Sml29623 	tcam_entry_t *tcam_ptr)
9103859Sml29623 {
9113859Sml29623 	udpip4_spec_t *fspec_key;
9123859Sml29623 	udpip4_spec_t *fspec_mask;
9133859Sml29623 
9143859Sml29623 	fspec_key = (udpip4_spec_t *)&flow_spec->uh.udpip4spec;
9153859Sml29623 	fspec_mask = (udpip4_spec_t *)&flow_spec->um.udpip4spec;
9163859Sml29623 	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
9173859Sml29623 	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
9183859Sml29623 	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
9193859Sml29623 	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
9203859Sml29623 	TCAM_IP_PORTS(tcam_ptr->ip4_port_key,
9216929Smisaki 	    fspec_key->pdst, fspec_key->psrc);
9223859Sml29623 	TCAM_IP_PORTS(tcam_ptr->ip4_port_mask,
9236929Smisaki 	    fspec_mask->pdst, fspec_mask->psrc);
9243859Sml29623 	TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
9256929Smisaki 	    tcam_ptr->ip4_class_mask,
9266929Smisaki 	    TCAM_CLASS_UDP_IPV4);
9273859Sml29623 	TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
9286929Smisaki 	    tcam_ptr->ip4_proto_mask,
9296929Smisaki 	    IPPROTO_UDP);
930*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip4_tos_key = fspec_key->tos;
931*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip4_tos_mask = fspec_mask->tos;
9323859Sml29623 }
9333859Sml29623 
9343859Sml29623 static void
9353859Sml29623 nxge_fill_tcam_entry_udp_ipv6(p_nxge_t nxgep, flow_spec_t *flow_spec,
9363859Sml29623 	tcam_entry_t *tcam_ptr)
9373859Sml29623 {
9383859Sml29623 	udpip6_spec_t *fspec_key;
9393859Sml29623 	udpip6_spec_t *fspec_mask;
9403859Sml29623 	p_nxge_class_pt_cfg_t p_class_cfgp;
9413859Sml29623 
9423859Sml29623 	fspec_key = (udpip6_spec_t *)&flow_spec->uh.udpip6spec;
9433859Sml29623 	fspec_mask = (udpip6_spec_t *)&flow_spec->um.udpip6spec;
9443859Sml29623 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
9453859Sml29623 	if (p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV6] &
9466929Smisaki 	    NXGE_CLASS_TCAM_USE_SRC_ADDR) {
9473859Sml29623 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6src);
9483859Sml29623 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6src);
9493859Sml29623 	} else {
9503859Sml29623 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6dst);
9513859Sml29623 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6dst);
9523859Sml29623 	}
9533859Sml29623 
9543859Sml29623 	TCAM_IP_CLASS(tcam_ptr->ip6_class_key,
9556929Smisaki 	    tcam_ptr->ip6_class_mask, TCAM_CLASS_UDP_IPV6);
9563859Sml29623 	TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
9576929Smisaki 	    tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_UDP);
9583859Sml29623 	TCAM_IP_PORTS(tcam_ptr->ip6_port_key,
9596929Smisaki 	    fspec_key->pdst, fspec_key->psrc);
9603859Sml29623 	TCAM_IP_PORTS(tcam_ptr->ip6_port_mask,
9616929Smisaki 	    fspec_mask->pdst, fspec_mask->psrc);
962*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip6_tos_key = fspec_key->tos;
963*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip6_tos_mask = fspec_mask->tos;
9643859Sml29623 }
9653859Sml29623 
9663859Sml29623 /* ARGSUSED */
9673859Sml29623 static void
9683859Sml29623 nxge_fill_tcam_entry_tcp(p_nxge_t nxgep, flow_spec_t *flow_spec,
9693859Sml29623 	tcam_entry_t *tcam_ptr)
9703859Sml29623 {
9713859Sml29623 	tcpip4_spec_t *fspec_key;
9723859Sml29623 	tcpip4_spec_t *fspec_mask;
9733859Sml29623 
9743859Sml29623 	fspec_key = (tcpip4_spec_t *)&flow_spec->uh.tcpip4spec;
9753859Sml29623 	fspec_mask = (tcpip4_spec_t *)&flow_spec->um.tcpip4spec;
9763859Sml29623 
9773859Sml29623 	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
9783859Sml29623 	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
9793859Sml29623 	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
9803859Sml29623 	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
9813859Sml29623 	TCAM_IP_PORTS(tcam_ptr->ip4_port_key,
9826929Smisaki 	    fspec_key->pdst, fspec_key->psrc);
9833859Sml29623 	TCAM_IP_PORTS(tcam_ptr->ip4_port_mask,
9846929Smisaki 	    fspec_mask->pdst, fspec_mask->psrc);
9853859Sml29623 	TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
9866929Smisaki 	    tcam_ptr->ip4_class_mask, TCAM_CLASS_TCP_IPV4);
9873859Sml29623 	TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
9886929Smisaki 	    tcam_ptr->ip4_proto_mask, IPPROTO_TCP);
989*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip4_tos_key = fspec_key->tos;
990*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip4_tos_mask = fspec_mask->tos;
9913859Sml29623 }
9923859Sml29623 
9933859Sml29623 /* ARGSUSED */
9943859Sml29623 static void
9953859Sml29623 nxge_fill_tcam_entry_sctp(p_nxge_t nxgep, flow_spec_t *flow_spec,
9963859Sml29623 	tcam_entry_t *tcam_ptr)
9973859Sml29623 {
9983859Sml29623 	tcpip4_spec_t *fspec_key;
9993859Sml29623 	tcpip4_spec_t *fspec_mask;
10003859Sml29623 
10013859Sml29623 	fspec_key = (tcpip4_spec_t *)&flow_spec->uh.tcpip4spec;
10023859Sml29623 	fspec_mask = (tcpip4_spec_t *)&flow_spec->um.tcpip4spec;
10033859Sml29623 
10043859Sml29623 	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
10053859Sml29623 	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
10063859Sml29623 	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
10073859Sml29623 	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
10083859Sml29623 	TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
10096929Smisaki 	    tcam_ptr->ip4_class_mask, TCAM_CLASS_SCTP_IPV4);
10103859Sml29623 	TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
10116929Smisaki 	    tcam_ptr->ip4_proto_mask, IPPROTO_SCTP);
10123859Sml29623 	TCAM_IP_PORTS(tcam_ptr->ip4_port_key,
10136929Smisaki 	    fspec_key->pdst, fspec_key->psrc);
10143859Sml29623 	TCAM_IP_PORTS(tcam_ptr->ip4_port_mask,
10156929Smisaki 	    fspec_mask->pdst, fspec_mask->psrc);
1016*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip4_tos_key = fspec_key->tos;
1017*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip4_tos_mask = fspec_mask->tos;
10183859Sml29623 }
10193859Sml29623 
10203859Sml29623 static void
10213859Sml29623 nxge_fill_tcam_entry_tcp_ipv6(p_nxge_t nxgep, flow_spec_t *flow_spec,
10223859Sml29623 	tcam_entry_t *tcam_ptr)
10233859Sml29623 {
10243859Sml29623 	tcpip6_spec_t *fspec_key;
10253859Sml29623 	tcpip6_spec_t *fspec_mask;
10263859Sml29623 	p_nxge_class_pt_cfg_t p_class_cfgp;
10273859Sml29623 
10283859Sml29623 	fspec_key = (tcpip6_spec_t *)&flow_spec->uh.tcpip6spec;
10293859Sml29623 	fspec_mask = (tcpip6_spec_t *)&flow_spec->um.tcpip6spec;
10303859Sml29623 
10313859Sml29623 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
10323859Sml29623 	if (p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV6] &
10336929Smisaki 	    NXGE_CLASS_TCAM_USE_SRC_ADDR) {
10343859Sml29623 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6src);
10353859Sml29623 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6src);
10363859Sml29623 	} else {
10373859Sml29623 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6dst);
10383859Sml29623 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6dst);
10393859Sml29623 	}
10403859Sml29623 
10413859Sml29623 	TCAM_IP_CLASS(tcam_ptr->ip6_class_key,
10426929Smisaki 	    tcam_ptr->ip6_class_mask, TCAM_CLASS_TCP_IPV6);
10433859Sml29623 	TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
10446929Smisaki 	    tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_TCP);
10453859Sml29623 	TCAM_IP_PORTS(tcam_ptr->ip6_port_key,
10466929Smisaki 	    fspec_key->pdst, fspec_key->psrc);
10473859Sml29623 	TCAM_IP_PORTS(tcam_ptr->ip6_port_mask,
10486929Smisaki 	    fspec_mask->pdst, fspec_mask->psrc);
1049*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip6_tos_key = fspec_key->tos;
1050*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip6_tos_mask = fspec_mask->tos;
10513859Sml29623 }
10523859Sml29623 
10533859Sml29623 static void
10543859Sml29623 nxge_fill_tcam_entry_sctp_ipv6(p_nxge_t nxgep, flow_spec_t *flow_spec,
10553859Sml29623 	tcam_entry_t *tcam_ptr)
10563859Sml29623 {
10573859Sml29623 	tcpip6_spec_t *fspec_key;
10583859Sml29623 	tcpip6_spec_t *fspec_mask;
10593859Sml29623 	p_nxge_class_pt_cfg_t p_class_cfgp;
10603859Sml29623 
10613859Sml29623 	fspec_key = (tcpip6_spec_t *)&flow_spec->uh.tcpip6spec;
10623859Sml29623 	fspec_mask = (tcpip6_spec_t *)&flow_spec->um.tcpip6spec;
10633859Sml29623 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
10643859Sml29623 
10653859Sml29623 	if (p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV6] &
10666929Smisaki 	    NXGE_CLASS_TCAM_USE_SRC_ADDR) {
10673859Sml29623 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6src);
10683859Sml29623 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6src);
10693859Sml29623 	} else {
10703859Sml29623 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6dst);
10713859Sml29623 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6dst);
10723859Sml29623 	}
10733859Sml29623 
10743859Sml29623 	TCAM_IP_CLASS(tcam_ptr->ip6_class_key,
10756929Smisaki 	    tcam_ptr->ip6_class_mask, TCAM_CLASS_SCTP_IPV6);
10763859Sml29623 	TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
10776929Smisaki 	    tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_SCTP);
10783859Sml29623 	TCAM_IP_PORTS(tcam_ptr->ip6_port_key,
10796929Smisaki 	    fspec_key->pdst, fspec_key->psrc);
10803859Sml29623 	TCAM_IP_PORTS(tcam_ptr->ip6_port_mask,
10816929Smisaki 	    fspec_mask->pdst, fspec_mask->psrc);
1082*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip6_tos_key = fspec_key->tos;
1083*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip6_tos_mask = fspec_mask->tos;
10843859Sml29623 }
10853859Sml29623 
1086*11304SJanie.Lu@Sun.COM /* ARGSUSED */
1087*11304SJanie.Lu@Sun.COM static void
1088*11304SJanie.Lu@Sun.COM nxge_fill_tcam_entry_ah_esp(p_nxge_t nxgep, flow_spec_t *flow_spec,
1089*11304SJanie.Lu@Sun.COM 	tcam_entry_t *tcam_ptr)
1090*11304SJanie.Lu@Sun.COM {
1091*11304SJanie.Lu@Sun.COM 	ahip4_spec_t *fspec_key;
1092*11304SJanie.Lu@Sun.COM 	ahip4_spec_t *fspec_mask;
1093*11304SJanie.Lu@Sun.COM 
1094*11304SJanie.Lu@Sun.COM 	fspec_key = (ahip4_spec_t *)&flow_spec->uh.ahip4spec;
1095*11304SJanie.Lu@Sun.COM 	fspec_mask = (ahip4_spec_t *)&flow_spec->um.ahip4spec;
1096*11304SJanie.Lu@Sun.COM 
1097*11304SJanie.Lu@Sun.COM 	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
1098*11304SJanie.Lu@Sun.COM 	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
1099*11304SJanie.Lu@Sun.COM 	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
1100*11304SJanie.Lu@Sun.COM 	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
1101*11304SJanie.Lu@Sun.COM 
1102*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip4_port_key = fspec_key->spi;
1103*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip4_port_mask = fspec_mask->spi;
1104*11304SJanie.Lu@Sun.COM 
1105*11304SJanie.Lu@Sun.COM 	TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
1106*11304SJanie.Lu@Sun.COM 	    tcam_ptr->ip4_class_mask,
1107*11304SJanie.Lu@Sun.COM 	    TCAM_CLASS_AH_ESP_IPV4);
1108*11304SJanie.Lu@Sun.COM 
1109*11304SJanie.Lu@Sun.COM 	if (flow_spec->flow_type == FSPEC_AHIP4) {
1110*11304SJanie.Lu@Sun.COM 		TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
1111*11304SJanie.Lu@Sun.COM 		    tcam_ptr->ip4_proto_mask, IPPROTO_AH);
1112*11304SJanie.Lu@Sun.COM 	} else {
1113*11304SJanie.Lu@Sun.COM 		TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
1114*11304SJanie.Lu@Sun.COM 		    tcam_ptr->ip4_proto_mask, IPPROTO_ESP);
1115*11304SJanie.Lu@Sun.COM 	}
1116*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip4_tos_key = fspec_key->tos;
1117*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip4_tos_mask = fspec_mask->tos;
1118*11304SJanie.Lu@Sun.COM }
1119*11304SJanie.Lu@Sun.COM 
1120*11304SJanie.Lu@Sun.COM static void
1121*11304SJanie.Lu@Sun.COM nxge_fill_tcam_entry_ah_esp_ipv6(p_nxge_t nxgep, flow_spec_t *flow_spec,
1122*11304SJanie.Lu@Sun.COM 	tcam_entry_t *tcam_ptr)
1123*11304SJanie.Lu@Sun.COM {
1124*11304SJanie.Lu@Sun.COM 	ahip6_spec_t *fspec_key;
1125*11304SJanie.Lu@Sun.COM 	ahip6_spec_t *fspec_mask;
1126*11304SJanie.Lu@Sun.COM 	p_nxge_class_pt_cfg_t p_class_cfgp;
1127*11304SJanie.Lu@Sun.COM 
1128*11304SJanie.Lu@Sun.COM 	fspec_key = (ahip6_spec_t *)&flow_spec->uh.ahip6spec;
1129*11304SJanie.Lu@Sun.COM 	fspec_mask = (ahip6_spec_t *)&flow_spec->um.ahip6spec;
1130*11304SJanie.Lu@Sun.COM 
1131*11304SJanie.Lu@Sun.COM 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
1132*11304SJanie.Lu@Sun.COM 	if (p_class_cfgp->class_cfg[TCAM_CLASS_AH_ESP_IPV6] &
1133*11304SJanie.Lu@Sun.COM 	    NXGE_CLASS_TCAM_USE_SRC_ADDR) {
1134*11304SJanie.Lu@Sun.COM 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6src);
1135*11304SJanie.Lu@Sun.COM 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6src);
1136*11304SJanie.Lu@Sun.COM 	} else {
1137*11304SJanie.Lu@Sun.COM 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6dst);
1138*11304SJanie.Lu@Sun.COM 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6dst);
1139*11304SJanie.Lu@Sun.COM 	}
1140*11304SJanie.Lu@Sun.COM 
1141*11304SJanie.Lu@Sun.COM 	TCAM_IP_CLASS(tcam_ptr->ip6_class_key,
1142*11304SJanie.Lu@Sun.COM 	    tcam_ptr->ip6_class_mask, TCAM_CLASS_AH_ESP_IPV6);
1143*11304SJanie.Lu@Sun.COM 
1144*11304SJanie.Lu@Sun.COM 	if (flow_spec->flow_type == FSPEC_AHIP6) {
1145*11304SJanie.Lu@Sun.COM 		TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
1146*11304SJanie.Lu@Sun.COM 		    tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_AH);
1147*11304SJanie.Lu@Sun.COM 	} else {
1148*11304SJanie.Lu@Sun.COM 		TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
1149*11304SJanie.Lu@Sun.COM 		    tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_ESP);
1150*11304SJanie.Lu@Sun.COM 	}
1151*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip6_port_key = fspec_key->spi;
1152*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip6_port_mask = fspec_mask->spi;
1153*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip6_tos_key = fspec_key->tos;
1154*11304SJanie.Lu@Sun.COM 	tcam_ptr->ip6_tos_mask = fspec_mask->tos;
1155*11304SJanie.Lu@Sun.COM }
1156*11304SJanie.Lu@Sun.COM 
1157*11304SJanie.Lu@Sun.COM /* ARGSUSED */
1158*11304SJanie.Lu@Sun.COM static void
1159*11304SJanie.Lu@Sun.COM nxge_fill_tcam_entry_ip_usr(p_nxge_t nxgep, flow_spec_t *flow_spec,
1160*11304SJanie.Lu@Sun.COM 	tcam_entry_t *tcam_ptr, tcam_class_t class)
1161*11304SJanie.Lu@Sun.COM {
1162*11304SJanie.Lu@Sun.COM 	ip_user_spec_t *fspec_key;
1163*11304SJanie.Lu@Sun.COM 	ip_user_spec_t *fspec_mask;
1164*11304SJanie.Lu@Sun.COM 
1165*11304SJanie.Lu@Sun.COM 	fspec_key = (ip_user_spec_t *)&flow_spec->uh.ip_usr_spec;
1166*11304SJanie.Lu@Sun.COM 	fspec_mask = (ip_user_spec_t *)&flow_spec->um.ip_usr_spec;
1167*11304SJanie.Lu@Sun.COM 
1168*11304SJanie.Lu@Sun.COM 	if (fspec_key->ip_ver == FSPEC_IP4) {
1169*11304SJanie.Lu@Sun.COM 		TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
1170*11304SJanie.Lu@Sun.COM 		TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
1171*11304SJanie.Lu@Sun.COM 		TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
1172*11304SJanie.Lu@Sun.COM 		TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
1173*11304SJanie.Lu@Sun.COM 
1174*11304SJanie.Lu@Sun.COM 		tcam_ptr->ip4_port_key = fspec_key->l4_4_bytes;
1175*11304SJanie.Lu@Sun.COM 		tcam_ptr->ip4_port_mask = fspec_mask->l4_4_bytes;
1176*11304SJanie.Lu@Sun.COM 
1177*11304SJanie.Lu@Sun.COM 		TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
1178*11304SJanie.Lu@Sun.COM 		    tcam_ptr->ip4_class_mask, class);
1179*11304SJanie.Lu@Sun.COM 
1180*11304SJanie.Lu@Sun.COM 		tcam_ptr->ip4_proto_key = fspec_key->proto;
1181*11304SJanie.Lu@Sun.COM 		tcam_ptr->ip4_proto_mask = fspec_mask->proto;
1182*11304SJanie.Lu@Sun.COM 
1183*11304SJanie.Lu@Sun.COM 		tcam_ptr->ip4_tos_key = fspec_key->tos;
1184*11304SJanie.Lu@Sun.COM 		tcam_ptr->ip4_tos_mask = fspec_mask->tos;
1185*11304SJanie.Lu@Sun.COM 	}
1186*11304SJanie.Lu@Sun.COM }
1187*11304SJanie.Lu@Sun.COM 
1188*11304SJanie.Lu@Sun.COM 
11893859Sml29623 nxge_status_t
11903859Sml29623 nxge_flow_get_hash(p_nxge_t nxgep, flow_resource_t *flow_res,
11913859Sml29623 	uint32_t *H1, uint16_t *H2)
11923859Sml29623 {
11933859Sml29623 	flow_spec_t *flow_spec;
11943859Sml29623 	uint32_t class_cfg;
11953859Sml29623 	flow_template_t ft;
11963859Sml29623 	p_nxge_class_pt_cfg_t p_class_cfgp;
11973859Sml29623 
11983859Sml29623 	int ft_size = sizeof (flow_template_t);
11993859Sml29623 
12003859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_flow_get_hash"));
12013859Sml29623 
12023859Sml29623 	flow_spec = (flow_spec_t *)&flow_res->flow_spec;
12033859Sml29623 	bzero((char *)&ft, ft_size);
12043859Sml29623 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
12053859Sml29623 
12063859Sml29623 	switch (flow_spec->flow_type) {
12073859Sml29623 	case FSPEC_TCPIP4:
12083859Sml29623 		class_cfg = p_class_cfgp->class_cfg[TCAM_CLASS_TCP_IPV4];
12093859Sml29623 		if (class_cfg & NXGE_CLASS_FLOW_USE_PROTO)
12103859Sml29623 			ft.ip_proto = IPPROTO_TCP;
12113859Sml29623 		if (class_cfg & NXGE_CLASS_FLOW_USE_IPSRC)
12123859Sml29623 			ft.ip4_saddr = flow_res->flow_spec.uh.tcpip4spec.ip4src;
12133859Sml29623 		if (class_cfg & NXGE_CLASS_FLOW_USE_IPDST)
12143859Sml29623 			ft.ip4_daddr = flow_res->flow_spec.uh.tcpip4spec.ip4dst;
12153859Sml29623 		if (class_cfg & NXGE_CLASS_FLOW_USE_SRC_PORT)
12163859Sml29623 			ft.ip_src_port = flow_res->flow_spec.uh.tcpip4spec.psrc;
12173859Sml29623 		if (class_cfg & NXGE_CLASS_FLOW_USE_DST_PORT)
12183859Sml29623 			ft.ip_dst_port = flow_res->flow_spec.uh.tcpip4spec.pdst;
12193859Sml29623 		break;
12203859Sml29623 
12213859Sml29623 	case FSPEC_UDPIP4:
12223859Sml29623 		class_cfg = p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV4];
12233859Sml29623 		if (class_cfg & NXGE_CLASS_FLOW_USE_PROTO)
12243859Sml29623 			ft.ip_proto = IPPROTO_UDP;
12253859Sml29623 		if (class_cfg & NXGE_CLASS_FLOW_USE_IPSRC)
12263859Sml29623 			ft.ip4_saddr = flow_res->flow_spec.uh.udpip4spec.ip4src;
12273859Sml29623 		if (class_cfg & NXGE_CLASS_FLOW_USE_IPDST)
12283859Sml29623 			ft.ip4_daddr = flow_res->flow_spec.uh.udpip4spec.ip4dst;
12293859Sml29623 		if (class_cfg & NXGE_CLASS_FLOW_USE_SRC_PORT)
12303859Sml29623 			ft.ip_src_port = flow_res->flow_spec.uh.udpip4spec.psrc;
12313859Sml29623 		if (class_cfg & NXGE_CLASS_FLOW_USE_DST_PORT)
12323859Sml29623 			ft.ip_dst_port = flow_res->flow_spec.uh.udpip4spec.pdst;
12333859Sml29623 		break;
12343859Sml29623 
12353859Sml29623 	default:
12363859Sml29623 		return (NXGE_ERROR);
12373859Sml29623 	}
12383859Sml29623 
12393859Sml29623 	*H1 = nxge_compute_h1(p_class_cfgp->init_h1,
12406929Smisaki 	    (uint32_t *)&ft, ft_size) & 0xfffff;
12413859Sml29623 	*H2 = nxge_compute_h2(p_class_cfgp->init_h2,
12426929Smisaki 	    (uint8_t *)&ft, ft_size);
12433859Sml29623 
12443859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_flow_get_hash"));
12453859Sml29623 	return (NXGE_OK);
12463859Sml29623 }
12473859Sml29623 
12483859Sml29623 nxge_status_t
12493859Sml29623 nxge_add_fcram_entry(p_nxge_t nxgep, flow_resource_t *flow_res)
12503859Sml29623 {
12513859Sml29623 	uint32_t H1;
12523859Sml29623 	uint16_t H2;
12533859Sml29623 	nxge_status_t status = NXGE_OK;
12543859Sml29623 
12553859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_add_fcram_entry"));
12563859Sml29623 	status = nxge_flow_get_hash(nxgep, flow_res, &H1, &H2);
12573859Sml29623 	if (status != NXGE_OK) {
12583859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
12596929Smisaki 		    " nxge_add_fcram_entry failed "));
12603859Sml29623 		return (status);
12613859Sml29623 	}
12623859Sml29623 
12633859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_add_fcram_entry"));
12643859Sml29623 	return (NXGE_OK);
12653859Sml29623 }
12663859Sml29623 
12673859Sml29623 /*
12683859Sml29623  * Already decided this flow goes into the tcam
12693859Sml29623  */
12703859Sml29623 
12713859Sml29623 nxge_status_t
12723859Sml29623 nxge_add_tcam_entry(p_nxge_t nxgep, flow_resource_t *flow_res)
12733859Sml29623 {
12743859Sml29623 	npi_handle_t handle;
1275*11304SJanie.Lu@Sun.COM 	uint64_t channel_cookie;
1276*11304SJanie.Lu@Sun.COM 	uint64_t flow_cookie;
12773859Sml29623 	flow_spec_t *flow_spec;
12783859Sml29623 	npi_status_t rs = NPI_SUCCESS;
12793859Sml29623 	tcam_entry_t tcam_ptr;
1280*11304SJanie.Lu@Sun.COM 	tcam_location_t location;
12813859Sml29623 	uint8_t offset, rdc_grp;
12823859Sml29623 	p_nxge_hw_list_t hw_p;
1283*11304SJanie.Lu@Sun.COM 	uint64_t class;
12843859Sml29623 
12853859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_add_tcam_entry"));
12863859Sml29623 	handle = nxgep->npi_reg_handle;
12873859Sml29623 
12883859Sml29623 	bzero((void *)&tcam_ptr, sizeof (tcam_entry_t));
12893859Sml29623 	flow_spec = (flow_spec_t *)&flow_res->flow_spec;
12903859Sml29623 	flow_cookie = flow_res->flow_cookie;
12913859Sml29623 	channel_cookie = flow_res->channel_cookie;
1292*11304SJanie.Lu@Sun.COM 	location = (tcam_location_t)nxge_tcam_get_index(nxgep,
1293*11304SJanie.Lu@Sun.COM 	    (uint16_t)flow_res->location);
1294*11304SJanie.Lu@Sun.COM 
1295*11304SJanie.Lu@Sun.COM 	if ((hw_p = nxgep->nxge_hw_p) == NULL) {
1296*11304SJanie.Lu@Sun.COM 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1297*11304SJanie.Lu@Sun.COM 		    " nxge_add_tcam_entry: common hardware not set",
1298*11304SJanie.Lu@Sun.COM 		    nxgep->niu_type));
1299*11304SJanie.Lu@Sun.COM 		return (NXGE_ERROR);
1300*11304SJanie.Lu@Sun.COM 	}
1301*11304SJanie.Lu@Sun.COM 
1302*11304SJanie.Lu@Sun.COM 	if (flow_spec->flow_type == FSPEC_IP_USR) {
1303*11304SJanie.Lu@Sun.COM 		int i;
1304*11304SJanie.Lu@Sun.COM 		int add_usr_cls = 0;
1305*11304SJanie.Lu@Sun.COM 		int ipv6 = 0;
1306*11304SJanie.Lu@Sun.COM 		ip_user_spec_t *uspec = &flow_spec->uh.ip_usr_spec;
1307*11304SJanie.Lu@Sun.COM 		ip_user_spec_t *umask = &flow_spec->um.ip_usr_spec;
1308*11304SJanie.Lu@Sun.COM 		nxge_usr_l3_cls_t *l3_ucls_p;
1309*11304SJanie.Lu@Sun.COM 
1310*11304SJanie.Lu@Sun.COM 		MUTEX_ENTER(&hw_p->nxge_tcam_lock);
1311*11304SJanie.Lu@Sun.COM 
1312*11304SJanie.Lu@Sun.COM 		for (i = 0; i < NXGE_L3_PROG_CLS; i++) {
1313*11304SJanie.Lu@Sun.COM 			l3_ucls_p = &hw_p->tcam_l3_prog_cls[i];
1314*11304SJanie.Lu@Sun.COM 			if (l3_ucls_p->valid && l3_ucls_p->tcam_ref_cnt) {
1315*11304SJanie.Lu@Sun.COM 				if (uspec->proto == l3_ucls_p->pid) {
1316*11304SJanie.Lu@Sun.COM 					class = l3_ucls_p->cls;
1317*11304SJanie.Lu@Sun.COM 					l3_ucls_p->tcam_ref_cnt++;
1318*11304SJanie.Lu@Sun.COM 					add_usr_cls = 1;
1319*11304SJanie.Lu@Sun.COM 					break;
1320*11304SJanie.Lu@Sun.COM 				}
1321*11304SJanie.Lu@Sun.COM 			} else if (l3_ucls_p->valid == 0) {
1322*11304SJanie.Lu@Sun.COM 				/* Program new user IP class */
1323*11304SJanie.Lu@Sun.COM 				switch (i) {
1324*11304SJanie.Lu@Sun.COM 				case 0:
1325*11304SJanie.Lu@Sun.COM 					class = TCAM_CLASS_IP_USER_4;
1326*11304SJanie.Lu@Sun.COM 					break;
1327*11304SJanie.Lu@Sun.COM 				case 1:
1328*11304SJanie.Lu@Sun.COM 					class = TCAM_CLASS_IP_USER_5;
1329*11304SJanie.Lu@Sun.COM 					break;
1330*11304SJanie.Lu@Sun.COM 				case 2:
1331*11304SJanie.Lu@Sun.COM 					class = TCAM_CLASS_IP_USER_6;
1332*11304SJanie.Lu@Sun.COM 					break;
1333*11304SJanie.Lu@Sun.COM 				case 3:
1334*11304SJanie.Lu@Sun.COM 					class = TCAM_CLASS_IP_USER_7;
1335*11304SJanie.Lu@Sun.COM 					break;
1336*11304SJanie.Lu@Sun.COM 				default:
1337*11304SJanie.Lu@Sun.COM 					break;
1338*11304SJanie.Lu@Sun.COM 				}
1339*11304SJanie.Lu@Sun.COM 				if (uspec->ip_ver == FSPEC_IP6)
1340*11304SJanie.Lu@Sun.COM 					ipv6 = 1;
1341*11304SJanie.Lu@Sun.COM 				rs = npi_fflp_cfg_ip_usr_cls_set(handle,
1342*11304SJanie.Lu@Sun.COM 				    (tcam_class_t)class, uspec->tos,
1343*11304SJanie.Lu@Sun.COM 				    umask->tos, uspec->proto, ipv6);
1344*11304SJanie.Lu@Sun.COM 				if (rs != NPI_SUCCESS)
1345*11304SJanie.Lu@Sun.COM 					goto fail;
1346*11304SJanie.Lu@Sun.COM 
1347*11304SJanie.Lu@Sun.COM 				rs = npi_fflp_cfg_ip_usr_cls_enable(handle,
1348*11304SJanie.Lu@Sun.COM 				    (tcam_class_t)class);
1349*11304SJanie.Lu@Sun.COM 				if (rs != NPI_SUCCESS)
1350*11304SJanie.Lu@Sun.COM 					goto fail;
1351*11304SJanie.Lu@Sun.COM 
1352*11304SJanie.Lu@Sun.COM 				l3_ucls_p->cls = class;
1353*11304SJanie.Lu@Sun.COM 				l3_ucls_p->pid = uspec->proto;
1354*11304SJanie.Lu@Sun.COM 				l3_ucls_p->tcam_ref_cnt++;
1355*11304SJanie.Lu@Sun.COM 				l3_ucls_p->valid = 1;
1356*11304SJanie.Lu@Sun.COM 				add_usr_cls = 1;
1357*11304SJanie.Lu@Sun.COM 				break;
1358*11304SJanie.Lu@Sun.COM 			} else if (l3_ucls_p->tcam_ref_cnt == 0 &&
1359*11304SJanie.Lu@Sun.COM 			    uspec->proto == l3_ucls_p->pid) {
1360*11304SJanie.Lu@Sun.COM 				/*
1361*11304SJanie.Lu@Sun.COM 				 * The class has already been programmed,
1362*11304SJanie.Lu@Sun.COM 				 * probably for flow hash
1363*11304SJanie.Lu@Sun.COM 				 */
1364*11304SJanie.Lu@Sun.COM 				class = l3_ucls_p->cls;
1365*11304SJanie.Lu@Sun.COM 				if (uspec->ip_ver == FSPEC_IP6)
1366*11304SJanie.Lu@Sun.COM 					ipv6 = 1;
1367*11304SJanie.Lu@Sun.COM 				rs = npi_fflp_cfg_ip_usr_cls_set(handle,
1368*11304SJanie.Lu@Sun.COM 				    (tcam_class_t)class, uspec->tos,
1369*11304SJanie.Lu@Sun.COM 				    umask->tos, uspec->proto, ipv6);
1370*11304SJanie.Lu@Sun.COM 				if (rs != NPI_SUCCESS)
1371*11304SJanie.Lu@Sun.COM 					goto fail;
1372*11304SJanie.Lu@Sun.COM 
1373*11304SJanie.Lu@Sun.COM 				rs = npi_fflp_cfg_ip_usr_cls_enable(handle,
1374*11304SJanie.Lu@Sun.COM 				    (tcam_class_t)class);
1375*11304SJanie.Lu@Sun.COM 				if (rs != NPI_SUCCESS)
1376*11304SJanie.Lu@Sun.COM 					goto fail;
1377*11304SJanie.Lu@Sun.COM 
1378*11304SJanie.Lu@Sun.COM 				l3_ucls_p->pid = uspec->proto;
1379*11304SJanie.Lu@Sun.COM 				l3_ucls_p->tcam_ref_cnt++;
1380*11304SJanie.Lu@Sun.COM 				add_usr_cls = 1;
1381*11304SJanie.Lu@Sun.COM 				break;
1382*11304SJanie.Lu@Sun.COM 			}
1383*11304SJanie.Lu@Sun.COM 		}
1384*11304SJanie.Lu@Sun.COM 		if (!add_usr_cls) {
1385*11304SJanie.Lu@Sun.COM 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1386*11304SJanie.Lu@Sun.COM 			    "nxge_add_tcam_entry: Could not find/insert class"
1387*11304SJanie.Lu@Sun.COM 			    "for pid %d", uspec->proto));
1388*11304SJanie.Lu@Sun.COM 			goto fail;
1389*11304SJanie.Lu@Sun.COM 		}
1390*11304SJanie.Lu@Sun.COM 		MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1391*11304SJanie.Lu@Sun.COM 	}
13923859Sml29623 
13933859Sml29623 	switch (flow_spec->flow_type) {
13943859Sml29623 	case FSPEC_TCPIP4:
13953859Sml29623 		nxge_fill_tcam_entry_tcp(nxgep, flow_spec, &tcam_ptr);
13963859Sml29623 		rdc_grp = nxge_get_rdc_group(nxgep, TCAM_CLASS_TCP_IPV4,
13976929Smisaki 		    flow_cookie);
13983859Sml29623 		offset = nxge_get_rdc_offset(nxgep, TCAM_CLASS_TCP_IPV4,
13996929Smisaki 		    channel_cookie);
14003859Sml29623 		break;
14013859Sml29623 
14023859Sml29623 	case FSPEC_UDPIP4:
14033859Sml29623 		nxge_fill_tcam_entry_udp(nxgep, flow_spec, &tcam_ptr);
14043859Sml29623 		rdc_grp = nxge_get_rdc_group(nxgep,
14056929Smisaki 		    TCAM_CLASS_UDP_IPV4,
14066929Smisaki 		    flow_cookie);
14073859Sml29623 		offset = nxge_get_rdc_offset(nxgep,
14086929Smisaki 		    TCAM_CLASS_UDP_IPV4,
14096929Smisaki 		    channel_cookie);
14103859Sml29623 		break;
14113859Sml29623 
14123859Sml29623 	case FSPEC_TCPIP6:
14133859Sml29623 		nxge_fill_tcam_entry_tcp_ipv6(nxgep,
14146929Smisaki 		    flow_spec, &tcam_ptr);
14153859Sml29623 		rdc_grp = nxge_get_rdc_group(nxgep, TCAM_CLASS_TCP_IPV6,
14166929Smisaki 		    flow_cookie);
14173859Sml29623 		offset = nxge_get_rdc_offset(nxgep, TCAM_CLASS_TCP_IPV6,
14186929Smisaki 		    channel_cookie);
14193859Sml29623 		break;
14203859Sml29623 
14213859Sml29623 	case FSPEC_UDPIP6:
14223859Sml29623 		nxge_fill_tcam_entry_udp_ipv6(nxgep,
14236929Smisaki 		    flow_spec, &tcam_ptr);
14243859Sml29623 		rdc_grp = nxge_get_rdc_group(nxgep,
14256929Smisaki 		    TCAM_CLASS_UDP_IPV6,
1426*11304SJanie.Lu@Sun.COM 		    flow_cookie);
14273859Sml29623 		offset = nxge_get_rdc_offset(nxgep,
14286929Smisaki 		    TCAM_CLASS_UDP_IPV6,
1429*11304SJanie.Lu@Sun.COM 		    channel_cookie);
14303859Sml29623 		break;
14313859Sml29623 
14323859Sml29623 	case FSPEC_SCTPIP4:
14333859Sml29623 		nxge_fill_tcam_entry_sctp(nxgep, flow_spec, &tcam_ptr);
14343859Sml29623 		rdc_grp = nxge_get_rdc_group(nxgep,
14356929Smisaki 		    TCAM_CLASS_SCTP_IPV4,
1436*11304SJanie.Lu@Sun.COM 		    flow_cookie);
14373859Sml29623 		offset = nxge_get_rdc_offset(nxgep,
14386929Smisaki 		    TCAM_CLASS_SCTP_IPV4,
1439*11304SJanie.Lu@Sun.COM 		    channel_cookie);
14403859Sml29623 		break;
14413859Sml29623 
14423859Sml29623 	case FSPEC_SCTPIP6:
14433859Sml29623 		nxge_fill_tcam_entry_sctp_ipv6(nxgep,
14446929Smisaki 		    flow_spec, &tcam_ptr);
14453859Sml29623 		rdc_grp = nxge_get_rdc_group(nxgep,
14466929Smisaki 		    TCAM_CLASS_SCTP_IPV6,
1447*11304SJanie.Lu@Sun.COM 		    flow_cookie);
1448*11304SJanie.Lu@Sun.COM 		offset = nxge_get_rdc_offset(nxgep,
1449*11304SJanie.Lu@Sun.COM 		    TCAM_CLASS_SCTP_IPV6,
14506929Smisaki 		    channel_cookie);
1451*11304SJanie.Lu@Sun.COM 		break;
1452*11304SJanie.Lu@Sun.COM 
1453*11304SJanie.Lu@Sun.COM 	case FSPEC_AHIP4:
1454*11304SJanie.Lu@Sun.COM 	case FSPEC_ESPIP4:
1455*11304SJanie.Lu@Sun.COM 		nxge_fill_tcam_entry_ah_esp(nxgep, flow_spec, &tcam_ptr);
1456*11304SJanie.Lu@Sun.COM 		rdc_grp = nxge_get_rdc_group(nxgep,
1457*11304SJanie.Lu@Sun.COM 		    TCAM_CLASS_AH_ESP_IPV4,
1458*11304SJanie.Lu@Sun.COM 		    flow_cookie);
14593859Sml29623 		offset = nxge_get_rdc_offset(nxgep,
1460*11304SJanie.Lu@Sun.COM 		    TCAM_CLASS_AH_ESP_IPV4,
1461*11304SJanie.Lu@Sun.COM 		    channel_cookie);
14623859Sml29623 		break;
14633859Sml29623 
1464*11304SJanie.Lu@Sun.COM 	case FSPEC_AHIP6:
1465*11304SJanie.Lu@Sun.COM 	case FSPEC_ESPIP6:
1466*11304SJanie.Lu@Sun.COM 		nxge_fill_tcam_entry_ah_esp_ipv6(nxgep,
1467*11304SJanie.Lu@Sun.COM 		    flow_spec, &tcam_ptr);
1468*11304SJanie.Lu@Sun.COM 		rdc_grp = nxge_get_rdc_group(nxgep,
1469*11304SJanie.Lu@Sun.COM 		    TCAM_CLASS_AH_ESP_IPV6,
1470*11304SJanie.Lu@Sun.COM 		    flow_cookie);
1471*11304SJanie.Lu@Sun.COM 		offset = nxge_get_rdc_offset(nxgep,
1472*11304SJanie.Lu@Sun.COM 		    TCAM_CLASS_AH_ESP_IPV6,
1473*11304SJanie.Lu@Sun.COM 		    channel_cookie);
1474*11304SJanie.Lu@Sun.COM 		break;
1475*11304SJanie.Lu@Sun.COM 
1476*11304SJanie.Lu@Sun.COM 	case FSPEC_IP_USR:
1477*11304SJanie.Lu@Sun.COM 		nxge_fill_tcam_entry_ip_usr(nxgep, flow_spec, &tcam_ptr,
1478*11304SJanie.Lu@Sun.COM 		    (tcam_class_t)class);
1479*11304SJanie.Lu@Sun.COM 		rdc_grp = nxge_get_rdc_group(nxgep,
1480*11304SJanie.Lu@Sun.COM 		    (tcam_class_t)class, flow_cookie);
1481*11304SJanie.Lu@Sun.COM 		offset = nxge_get_rdc_offset(nxgep,
1482*11304SJanie.Lu@Sun.COM 		    (tcam_class_t)class, channel_cookie);
1483*11304SJanie.Lu@Sun.COM 		break;
14843859Sml29623 	default:
1485*11304SJanie.Lu@Sun.COM 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1486*11304SJanie.Lu@Sun.COM 		    "nxge_add_tcam_entry: Unknown flow spec 0x%x",
1487*11304SJanie.Lu@Sun.COM 		    flow_spec->flow_type));
1488*11304SJanie.Lu@Sun.COM 		return (NXGE_ERROR);
14893859Sml29623 	}
14903859Sml29623 
14913859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
14926929Smisaki 	    " nxge_add_tcam_entry write"
14936929Smisaki 	    " for location %d offset %d", location, offset));
14943859Sml29623 
14953859Sml29623 	MUTEX_ENTER(&hw_p->nxge_tcam_lock);
14963859Sml29623 	rs = npi_fflp_tcam_entry_write(handle, location, &tcam_ptr);
14973859Sml29623 
14983859Sml29623 	if (rs & NPI_FFLP_ERROR) {
14993859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15006929Smisaki 		    " nxge_add_tcam_entry write"
15016929Smisaki 		    " failed for location %d", location));
1502*11304SJanie.Lu@Sun.COM 		goto fail;
15033859Sml29623 	}
15043859Sml29623 
15053859Sml29623 	tcam_ptr.match_action.value = 0;
15063859Sml29623 	tcam_ptr.match_action.bits.ldw.rdctbl = rdc_grp;
15073859Sml29623 	tcam_ptr.match_action.bits.ldw.offset = offset;
15083859Sml29623 	tcam_ptr.match_action.bits.ldw.tres =
15096929Smisaki 	    TRES_TERM_OVRD_L2RDC;
1510*11304SJanie.Lu@Sun.COM 	if (channel_cookie == NXGE_PKT_DISCARD)
15113859Sml29623 		tcam_ptr.match_action.bits.ldw.disc = 1;
15123859Sml29623 	rs = npi_fflp_tcam_asc_ram_entry_write(handle,
15136929Smisaki 	    location, tcam_ptr.match_action.value);
15143859Sml29623 	if (rs & NPI_FFLP_ERROR) {
15153859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15166929Smisaki 		    " nxge_add_tcam_entry write"
15176929Smisaki 		    " failed for ASC RAM location %d", location));
1518*11304SJanie.Lu@Sun.COM 		goto fail;
15193859Sml29623 	}
15203859Sml29623 	bcopy((void *) &tcam_ptr,
15216929Smisaki 	    (void *) &nxgep->classifier.tcam_entries[location].tce,
15226929Smisaki 	    sizeof (tcam_entry_t));
1523*11304SJanie.Lu@Sun.COM 	nxgep->classifier.tcam_entry_cnt++;
1524*11304SJanie.Lu@Sun.COM 	nxgep->classifier.tcam_entries[location].valid = 1;
15253859Sml29623 
15263859Sml29623 	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
15273859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_add_tcam_entry"));
15283859Sml29623 	return (NXGE_OK);
1529*11304SJanie.Lu@Sun.COM fail:
1530*11304SJanie.Lu@Sun.COM 	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1531*11304SJanie.Lu@Sun.COM 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_tcam_entry FAILED"));
1532*11304SJanie.Lu@Sun.COM 	return (NXGE_ERROR);
15333859Sml29623 }
15343859Sml29623 
15353859Sml29623 static nxge_status_t
15363859Sml29623 nxge_tcam_handle_ip_fragment(p_nxge_t nxgep)
15373859Sml29623 {
15383859Sml29623 	tcam_entry_t tcam_ptr;
15393859Sml29623 	tcam_location_t location;
15403859Sml29623 	uint8_t class;
15413859Sml29623 	uint32_t class_config;
15423859Sml29623 	npi_handle_t handle;
15433859Sml29623 	npi_status_t rs = NPI_SUCCESS;
15443859Sml29623 	p_nxge_hw_list_t hw_p;
15453859Sml29623 	nxge_status_t status = NXGE_OK;
15463859Sml29623 
15473859Sml29623 	handle = nxgep->npi_reg_handle;
15483859Sml29623 	class = 0;
15493859Sml29623 	bzero((void *)&tcam_ptr, sizeof (tcam_entry_t));
15503859Sml29623 	tcam_ptr.ip4_noport_key = 1;
15513859Sml29623 	tcam_ptr.ip4_noport_mask = 1;
15523859Sml29623 	location = nxgep->function_num;
15533859Sml29623 	nxgep->classifier.fragment_bug_location = location;
15543859Sml29623 
15553859Sml29623 	if ((hw_p = nxgep->nxge_hw_p) == NULL) {
15563859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15576929Smisaki 		    " nxge_tcam_handle_ip_fragment: common hardware not set",
15586929Smisaki 		    nxgep->niu_type));
15593859Sml29623 		return (NXGE_ERROR);
15603859Sml29623 	}
15613859Sml29623 	MUTEX_ENTER(&hw_p->nxge_tcam_lock);
15623859Sml29623 	rs = npi_fflp_tcam_entry_write(handle,
15636929Smisaki 	    location, &tcam_ptr);
15643859Sml29623 
15653859Sml29623 	if (rs & NPI_FFLP_ERROR) {
15663859Sml29623 		MUTEX_EXIT(&hw_p->nxge_tcam_lock);
15673859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15686929Smisaki 		    " nxge_tcam_handle_ip_fragment "
15696929Smisaki 		    " tcam_entry write"
15706929Smisaki 		    " failed for location %d", location));
15713859Sml29623 		return (NXGE_ERROR);
15723859Sml29623 	}
15733859Sml29623 	tcam_ptr.match_action.bits.ldw.rdctbl = nxgep->class_config.mac_rdcgrp;
15743859Sml29623 	tcam_ptr.match_action.bits.ldw.offset = 0;	/* use the default */
15753859Sml29623 	tcam_ptr.match_action.bits.ldw.tres =
15766929Smisaki 	    TRES_TERM_USE_OFFSET;
15773859Sml29623 	rs = npi_fflp_tcam_asc_ram_entry_write(handle,
15786929Smisaki 	    location, tcam_ptr.match_action.value);
15793859Sml29623 
15803859Sml29623 	if (rs & NPI_FFLP_ERROR) {
15813859Sml29623 		MUTEX_EXIT(&hw_p->nxge_tcam_lock);
15823859Sml29623 		NXGE_DEBUG_MSG((nxgep,
15836929Smisaki 		    FFLP_CTL,
15846929Smisaki 		    " nxge_tcam_handle_ip_fragment "
15856929Smisaki 		    " tcam_entry write"
15866929Smisaki 		    " failed for ASC RAM location %d", location));
15873859Sml29623 		return (NXGE_ERROR);
15883859Sml29623 	}
15893859Sml29623 	bcopy((void *) &tcam_ptr,
15906929Smisaki 	    (void *) &nxgep->classifier.tcam_entries[location].tce,
15916929Smisaki 	    sizeof (tcam_entry_t));
1592*11304SJanie.Lu@Sun.COM 	nxgep->classifier.tcam_entry_cnt++;
1593*11304SJanie.Lu@Sun.COM 	nxgep->classifier.tcam_entries[location].valid = 1;
15943859Sml29623 	for (class = TCAM_CLASS_TCP_IPV4;
15956929Smisaki 	    class <= TCAM_CLASS_SCTP_IPV6; class++) {
15963859Sml29623 		class_config = nxgep->class_config.class_cfg[class];
15973859Sml29623 		class_config |= NXGE_CLASS_TCAM_LOOKUP;
15983859Sml29623 		status = nxge_fflp_ip_class_config(nxgep, class, class_config);
15993859Sml29623 
16003859Sml29623 		if (status & NPI_FFLP_ERROR) {
16013859Sml29623 			MUTEX_EXIT(&hw_p->nxge_tcam_lock);
16023859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16036929Smisaki 			    "nxge_tcam_handle_ip_fragment "
16046929Smisaki 			    "nxge_fflp_ip_class_config failed "
16056929Smisaki 			    " class %d config %x ", class, class_config));
16063859Sml29623 			return (NXGE_ERROR);
16073859Sml29623 		}
16083859Sml29623 	}
16093859Sml29623 
16103859Sml29623 	rs = npi_fflp_cfg_tcam_enable(handle);
16113859Sml29623 	if (rs & NPI_FFLP_ERROR) {
16123859Sml29623 		MUTEX_EXIT(&hw_p->nxge_tcam_lock);
16133859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16146929Smisaki 		    "nxge_tcam_handle_ip_fragment "
16156929Smisaki 		    " nxge_fflp_config_tcam_enable failed"));
16163859Sml29623 		return (NXGE_ERROR);
16173859Sml29623 	}
16183859Sml29623 	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
16193859Sml29623 	return (NXGE_OK);
16203859Sml29623 }
16213859Sml29623 
16223859Sml29623 /* ARGSUSED */
16233859Sml29623 static int
16243859Sml29623 nxge_flow_need_hash_lookup(p_nxge_t nxgep, flow_resource_t *flow_res)
16253859Sml29623 {
16263859Sml29623 	return (0);
16273859Sml29623 }
16283859Sml29623 
16293859Sml29623 nxge_status_t
16303859Sml29623 nxge_add_flow(p_nxge_t nxgep, flow_resource_t *flow_res)
16313859Sml29623 {
16323859Sml29623 
16333859Sml29623 	int insert_hash = 0;
16343859Sml29623 	nxge_status_t status = NXGE_OK;
16353859Sml29623 
16364977Sraghus 	if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
16373859Sml29623 		/* determine whether to do TCAM or Hash flow */
16383859Sml29623 		insert_hash = nxge_flow_need_hash_lookup(nxgep, flow_res);
16393859Sml29623 	}
16403859Sml29623 	if (insert_hash) {
16413859Sml29623 		status = nxge_add_fcram_entry(nxgep, flow_res);
16423859Sml29623 	} else {
16433859Sml29623 		status = nxge_add_tcam_entry(nxgep, flow_res);
16443859Sml29623 	}
16453859Sml29623 	return (status);
16463859Sml29623 }
16473859Sml29623 
16483859Sml29623 void
16493859Sml29623 nxge_put_tcam(p_nxge_t nxgep, p_mblk_t mp)
16503859Sml29623 {
16513859Sml29623 	flow_resource_t *fs;
16523859Sml29623 
16533859Sml29623 	fs = (flow_resource_t *)mp->b_rptr;
16543859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16556929Smisaki 	    "nxge_put_tcam addr fs $%p  type %x offset %x",
16566929Smisaki 	    fs, fs->flow_spec.flow_type, fs->channel_cookie));
16573859Sml29623 	(void) nxge_add_tcam_entry(nxgep, fs);
16583859Sml29623 }
16593859Sml29623 
16603859Sml29623 nxge_status_t
16613859Sml29623 nxge_fflp_config_tcam_enable(p_nxge_t nxgep)
16623859Sml29623 {
16633859Sml29623 	npi_handle_t handle = nxgep->npi_reg_handle;
16643859Sml29623 	npi_status_t rs = NPI_SUCCESS;
16653859Sml29623 
16663859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_config_tcam_enable"));
16673859Sml29623 	rs = npi_fflp_cfg_tcam_enable(handle);
16683859Sml29623 	if (rs & NPI_FFLP_ERROR) {
16693859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16706929Smisaki 		    " nxge_fflp_config_tcam_enable failed"));
16713859Sml29623 		return (NXGE_ERROR | rs);
16723859Sml29623 	}
16733859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_fflp_config_tcam_enable"));
16743859Sml29623 	return (NXGE_OK);
16753859Sml29623 }
16763859Sml29623 
16773859Sml29623 nxge_status_t
16783859Sml29623 nxge_fflp_config_tcam_disable(p_nxge_t nxgep)
16793859Sml29623 {
16803859Sml29623 	npi_handle_t handle = nxgep->npi_reg_handle;
16813859Sml29623 	npi_status_t rs = NPI_SUCCESS;
16823859Sml29623 
16833859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
16846929Smisaki 	    " ==> nxge_fflp_config_tcam_disable"));
16853859Sml29623 	rs = npi_fflp_cfg_tcam_disable(handle);
16863859Sml29623 	if (rs & NPI_FFLP_ERROR) {
16873859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16886929Smisaki 		    " nxge_fflp_config_tcam_disable failed"));
16893859Sml29623 		return (NXGE_ERROR | rs);
16903859Sml29623 	}
16913859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
16926929Smisaki 	    " <== nxge_fflp_config_tcam_disable"));
16933859Sml29623 	return (NXGE_OK);
16943859Sml29623 }
16953859Sml29623 
16963859Sml29623 nxge_status_t
16973859Sml29623 nxge_fflp_config_hash_lookup_enable(p_nxge_t nxgep)
16983859Sml29623 {
16993859Sml29623 	npi_handle_t handle = nxgep->npi_reg_handle;
17003859Sml29623 	npi_status_t rs = NPI_SUCCESS;
17013859Sml29623 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
17023859Sml29623 	p_nxge_hw_pt_cfg_t p_cfgp;
17033859Sml29623 	uint8_t partition;
17043859Sml29623 
17053859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
17066929Smisaki 	    " ==> nxge_fflp_config_hash_lookup_enable"));
17073859Sml29623 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
17083859Sml29623 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
17093859Sml29623 
17106495Sspeer 	for (partition = 0; partition < NXGE_MAX_RDC_GROUPS; partition++) {
17116495Sspeer 		if (p_cfgp->grpids[partition]) {
17126495Sspeer 			rs = npi_fflp_cfg_fcram_partition_enable(
17136929Smisaki 			    handle, partition);
17146495Sspeer 			if (rs != NPI_SUCCESS) {
17156495Sspeer 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
17166495Sspeer 				    " nxge_fflp_config_hash_lookup_enable"
17176495Sspeer 				    "failed FCRAM partition"
17186495Sspeer 				    " enable for partition %d ", partition));
17196495Sspeer 				return (NXGE_ERROR | rs);
17206495Sspeer 			}
17213859Sml29623 		}
17223859Sml29623 	}
17233859Sml29623 
17243859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
17256929Smisaki 	    " <== nxge_fflp_config_hash_lookup_enable"));
17263859Sml29623 	return (NXGE_OK);
17273859Sml29623 }
17283859Sml29623 
17293859Sml29623 nxge_status_t
17303859Sml29623 nxge_fflp_config_hash_lookup_disable(p_nxge_t nxgep)
17313859Sml29623 {
17323859Sml29623 	npi_handle_t handle = nxgep->npi_reg_handle;
17333859Sml29623 	npi_status_t rs = NPI_SUCCESS;
17343859Sml29623 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
17353859Sml29623 	p_nxge_hw_pt_cfg_t p_cfgp;
17363859Sml29623 	uint8_t partition;
17373859Sml29623 
17383859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
17396929Smisaki 	    " ==> nxge_fflp_config_hash_lookup_disable"));
17403859Sml29623 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
17413859Sml29623 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
17423859Sml29623 
17436495Sspeer 	for (partition = 0; partition < NXGE_MAX_RDC_GROUPS; partition++) {
17446495Sspeer 		if (p_cfgp->grpids[partition]) {
17456495Sspeer 			rs = npi_fflp_cfg_fcram_partition_disable(handle,
17466495Sspeer 			    partition);
17476495Sspeer 			if (rs != NPI_SUCCESS) {
17486495Sspeer 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
17496495Sspeer 				    " nxge_fflp_config_hash_lookup_disable"
17506495Sspeer 				    " failed FCRAM partition"
17516495Sspeer 				    " disable for partition %d ", partition));
17526495Sspeer 				return (NXGE_ERROR | rs);
17536495Sspeer 			}
17543859Sml29623 		}
17553859Sml29623 	}
17563859Sml29623 
17573859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
17586929Smisaki 	    " <== nxge_fflp_config_hash_lookup_disable"));
17593859Sml29623 	return (NXGE_OK);
17603859Sml29623 }
17613859Sml29623 
17623859Sml29623 nxge_status_t
17633859Sml29623 nxge_fflp_config_llc_snap_enable(p_nxge_t nxgep)
17643859Sml29623 {
17653859Sml29623 	npi_handle_t handle = nxgep->npi_reg_handle;
17663859Sml29623 	npi_status_t rs = NPI_SUCCESS;
17673859Sml29623 
17683859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
17696929Smisaki 	    " ==> nxge_fflp_config_llc_snap_enable"));
17703859Sml29623 	rs = npi_fflp_cfg_llcsnap_enable(handle);
17713859Sml29623 	if (rs & NPI_FFLP_ERROR) {
17723859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
17736929Smisaki 		    " nxge_fflp_config_llc_snap_enable failed"));
17743859Sml29623 		return (NXGE_ERROR | rs);
17753859Sml29623 	}
17763859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
17776929Smisaki 	    " <== nxge_fflp_config_llc_snap_enable"));
17783859Sml29623 	return (NXGE_OK);
17793859Sml29623 }
17803859Sml29623 
17813859Sml29623 nxge_status_t
17823859Sml29623 nxge_fflp_config_llc_snap_disable(p_nxge_t nxgep)
17833859Sml29623 {
17843859Sml29623 	npi_handle_t handle = nxgep->npi_reg_handle;
17853859Sml29623 	npi_status_t rs = NPI_SUCCESS;
17863859Sml29623 
17873859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
17886929Smisaki 	    " ==> nxge_fflp_config_llc_snap_disable"));
17893859Sml29623 	rs = npi_fflp_cfg_llcsnap_disable(handle);
17903859Sml29623 	if (rs & NPI_FFLP_ERROR) {
17913859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
17926929Smisaki 		    " nxge_fflp_config_llc_snap_disable failed"));
17933859Sml29623 		return (NXGE_ERROR | rs);
17943859Sml29623 	}
17953859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
17966929Smisaki 	    " <== nxge_fflp_config_llc_snap_disable"));
17973859Sml29623 	return (NXGE_OK);
17983859Sml29623 }
17993859Sml29623 
18003859Sml29623 nxge_status_t
18013859Sml29623 nxge_fflp_ip_usr_class_config(p_nxge_t nxgep, tcam_class_t class,
18023859Sml29623 	uint32_t config)
18033859Sml29623 {
18043859Sml29623 	npi_status_t rs = NPI_SUCCESS;
18053859Sml29623 	npi_handle_t handle = nxgep->npi_reg_handle;
18063859Sml29623 	uint8_t tos, tos_mask, proto, ver = 0;
18073859Sml29623 	uint8_t class_enable = 0;
18083859Sml29623 
18093859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_ip_usr_class_config"));
18103859Sml29623 
18113859Sml29623 	tos = (config & NXGE_CLASS_CFG_IP_TOS_MASK) >>
18126929Smisaki 	    NXGE_CLASS_CFG_IP_TOS_SHIFT;
18133859Sml29623 	tos_mask = (config & NXGE_CLASS_CFG_IP_TOS_MASK_MASK) >>
18146929Smisaki 	    NXGE_CLASS_CFG_IP_TOS_MASK_SHIFT;
18153859Sml29623 	proto = (config & NXGE_CLASS_CFG_IP_PROTO_MASK) >>
18166929Smisaki 	    NXGE_CLASS_CFG_IP_PROTO_SHIFT;
18173859Sml29623 	if (config & NXGE_CLASS_CFG_IP_IPV6_MASK)
18183859Sml29623 		ver = 1;
18193859Sml29623 	if (config & NXGE_CLASS_CFG_IP_ENABLE_MASK)
18203859Sml29623 		class_enable = 1;
18213859Sml29623 	rs = npi_fflp_cfg_ip_usr_cls_set(handle, class, tos, tos_mask,
18226929Smisaki 	    proto, ver);
18233859Sml29623 	if (rs & NPI_FFLP_ERROR) {
18243859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18256929Smisaki 		    " nxge_fflp_ip_usr_class_config"
18266929Smisaki 		    " for class %d failed ", class));
18273859Sml29623 		return (NXGE_ERROR | rs);
18283859Sml29623 	}
18293859Sml29623 	if (class_enable)
18303859Sml29623 		rs = npi_fflp_cfg_ip_usr_cls_enable(handle, class);
18313859Sml29623 	else
18323859Sml29623 		rs = npi_fflp_cfg_ip_usr_cls_disable(handle, class);
18333859Sml29623 
18343859Sml29623 	if (rs & NPI_FFLP_ERROR) {
18353859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18366929Smisaki 		    " nxge_fflp_ip_usr_class_config"
18376929Smisaki 		    " TCAM enable/disable for class %d failed ", class));
18383859Sml29623 		return (NXGE_ERROR | rs);
18393859Sml29623 	}
18403859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_usr_class_config"));
18413859Sml29623 	return (NXGE_OK);
18423859Sml29623 }
18433859Sml29623 
18443859Sml29623 nxge_status_t
18453859Sml29623 nxge_fflp_ip_class_config(p_nxge_t nxgep, tcam_class_t class, uint32_t config)
18463859Sml29623 {
18473859Sml29623 	uint32_t class_config;
18483859Sml29623 	nxge_status_t t_status = NXGE_OK;
18493859Sml29623 	nxge_status_t f_status = NXGE_OK;
18503859Sml29623 	p_nxge_class_pt_cfg_t p_class_cfgp;
18513859Sml29623 
18523859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_ip_class_config"));
18533859Sml29623 
18543859Sml29623 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
18553859Sml29623 	class_config = p_class_cfgp->class_cfg[class];
18563859Sml29623 
18573859Sml29623 	if (class_config != config) {
18583859Sml29623 		p_class_cfgp->class_cfg[class] = config;
18593859Sml29623 		class_config = config;
18603859Sml29623 	}
18613859Sml29623 
18623859Sml29623 	t_status = nxge_cfg_tcam_ip_class(nxgep, class, class_config);
18633859Sml29623 	f_status = nxge_cfg_ip_cls_flow_key(nxgep, class, class_config);
18643859Sml29623 
18653859Sml29623 	if (t_status & NPI_FFLP_ERROR) {
18663859Sml29623 		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
18676929Smisaki 		    " nxge_fflp_ip_class_config %x"
18686929Smisaki 		    " for class %d tcam failed", config, class));
18693859Sml29623 		return (t_status);
18703859Sml29623 	}
18713859Sml29623 	if (f_status & NPI_FFLP_ERROR) {
18723859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18736929Smisaki 		    " nxge_fflp_ip_class_config %x"
18746929Smisaki 		    " for class %d flow key failed", config, class));
18753859Sml29623 		return (f_status);
18763859Sml29623 	}
18773859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_class_config"));
18783859Sml29623 	return (NXGE_OK);
18793859Sml29623 }
18803859Sml29623 
18813859Sml29623 nxge_status_t
18823859Sml29623 nxge_fflp_ip_class_config_get(p_nxge_t nxgep, tcam_class_t class,
18833859Sml29623 	uint32_t *config)
18843859Sml29623 {
18853859Sml29623 	uint32_t t_class_config, f_class_config;
18863859Sml29623 	int t_status = NXGE_OK;
18873859Sml29623 	int f_status = NXGE_OK;
18883859Sml29623 
18893859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_ip_class_config"));
18903859Sml29623 
18913859Sml29623 	t_class_config = f_class_config = 0;
18923859Sml29623 	t_status = nxge_cfg_tcam_ip_class_get(nxgep, class, &t_class_config);
18933859Sml29623 	f_status = nxge_cfg_ip_cls_flow_key_get(nxgep, class, &f_class_config);
18943859Sml29623 
18953859Sml29623 	if (t_status & NPI_FFLP_ERROR) {
18963859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18976929Smisaki 		    " nxge_fflp_ip_class_config_get  "
18986929Smisaki 		    " for class %d tcam failed", class));
18993859Sml29623 		return (t_status);
19003859Sml29623 	}
19013859Sml29623 
19023859Sml29623 	if (f_status & NPI_FFLP_ERROR) {
19033859Sml29623 		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
19046929Smisaki 		    " nxge_fflp_ip_class_config_get  "
19056929Smisaki 		    " for class %d flow key failed", class));
19063859Sml29623 		return (f_status);
19073859Sml29623 	}
19083859Sml29623 
19093859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
19106929Smisaki 	    " nxge_fflp_ip_class_config tcam %x flow %x",
19116929Smisaki 	    t_class_config, f_class_config));
19123859Sml29623 
19133859Sml29623 	*config = t_class_config | f_class_config;
19143859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_class_config_get"));
19153859Sml29623 	return (NXGE_OK);
19163859Sml29623 }
19173859Sml29623 
19183859Sml29623 nxge_status_t
19193859Sml29623 nxge_fflp_ip_class_config_all(p_nxge_t nxgep)
19203859Sml29623 {
19213859Sml29623 	uint32_t class_config;
19223859Sml29623 	tcam_class_t class;
19233859Sml29623 
19243859Sml29623 #ifdef	NXGE_DEBUG
19253859Sml29623 	int status = NXGE_OK;
19263859Sml29623 #endif
19273859Sml29623 
19283859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_ip_class_config"));
19293859Sml29623 	for (class = TCAM_CLASS_TCP_IPV4;
19306929Smisaki 	    class <= TCAM_CLASS_SCTP_IPV6; class++) {
19313859Sml29623 		class_config = nxgep->class_config.class_cfg[class];
19323859Sml29623 #ifndef	NXGE_DEBUG
19333859Sml29623 		(void) nxge_fflp_ip_class_config(nxgep, class, class_config);
19343859Sml29623 #else
19353859Sml29623 		status = nxge_fflp_ip_class_config(nxgep, class, class_config);
19363859Sml29623 		if (status & NPI_FFLP_ERROR) {
19373859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
19386929Smisaki 			    "nxge_fflp_ip_class_config failed "
19396929Smisaki 			    " class %d config %x ",
19406929Smisaki 			    class, class_config));
19413859Sml29623 		}
19423859Sml29623 #endif
19433859Sml29623 	}
19443859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_class_config"));
19453859Sml29623 	return (NXGE_OK);
19463859Sml29623 }
19473859Sml29623 
19483859Sml29623 nxge_status_t
19493859Sml29623 nxge_fflp_config_vlan_table(p_nxge_t nxgep, uint16_t vlan_id)
19503859Sml29623 {
19513859Sml29623 	uint8_t port, rdc_grp;
19523859Sml29623 	npi_handle_t handle;
19533859Sml29623 	npi_status_t rs = NPI_SUCCESS;
19543859Sml29623 	uint8_t priority = 1;
19553859Sml29623 	p_nxge_mv_cfg_t vlan_table;
19563859Sml29623 	p_nxge_class_pt_cfg_t p_class_cfgp;
19573859Sml29623 	p_nxge_hw_list_t hw_p;
19583859Sml29623 
19593859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_config_vlan_table"));
19603859Sml29623 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
19613859Sml29623 	handle = nxgep->npi_reg_handle;
19623859Sml29623 	vlan_table = p_class_cfgp->vlan_tbl;
19633859Sml29623 	port = nxgep->function_num;
19643859Sml29623 
19653859Sml29623 	if (vlan_table[vlan_id].flag == 0) {
19663859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
19676929Smisaki 		    " nxge_fflp_config_vlan_table"
19686929Smisaki 		    " vlan id is not configured %d", vlan_id));
19693859Sml29623 		return (NXGE_ERROR);
19703859Sml29623 	}
19713859Sml29623 
19723859Sml29623 	if ((hw_p = nxgep->nxge_hw_p) == NULL) {
19733859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
19746929Smisaki 		    " nxge_fflp_config_vlan_table:"
19756929Smisaki 		    " common hardware not set", nxgep->niu_type));
19763859Sml29623 		return (NXGE_ERROR);
19773859Sml29623 	}
19783859Sml29623 	MUTEX_ENTER(&hw_p->nxge_vlan_lock);
19793859Sml29623 	rdc_grp = vlan_table[vlan_id].rdctbl;
19803859Sml29623 	rs = npi_fflp_cfg_enet_vlan_table_assoc(handle,
19816929Smisaki 	    port, vlan_id,
19826929Smisaki 	    rdc_grp, priority);
19833859Sml29623 
19843859Sml29623 	MUTEX_EXIT(&hw_p->nxge_vlan_lock);
19853859Sml29623 	if (rs & NPI_FFLP_ERROR) {
19863859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
19876929Smisaki 		    "nxge_fflp_config_vlan_table failed "
19886929Smisaki 		    " Port %d vlan_id %d rdc_grp %d",
19896929Smisaki 		    port, vlan_id, rdc_grp));
19903859Sml29623 		return (NXGE_ERROR | rs);
19913859Sml29623 	}
19923859Sml29623 
19933859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_config_vlan_table"));
19943859Sml29623 	return (NXGE_OK);
19953859Sml29623 }
19963859Sml29623 
19973859Sml29623 nxge_status_t
19983859Sml29623 nxge_fflp_update_hw(p_nxge_t nxgep)
19993859Sml29623 {
20003859Sml29623 	nxge_status_t status = NXGE_OK;
20013859Sml29623 	p_nxge_param_t pa;
20023859Sml29623 	uint64_t cfgd_vlans;
20033859Sml29623 	uint64_t *val_ptr;
20043859Sml29623 	int i;
20053859Sml29623 	int num_macs;
20063859Sml29623 	uint8_t alt_mac;
20073859Sml29623 	nxge_param_map_t *p_map;
20083859Sml29623 	p_nxge_mv_cfg_t vlan_table;
20093859Sml29623 	p_nxge_class_pt_cfg_t p_class_cfgp;
20103859Sml29623 	p_nxge_dma_pt_cfg_t p_all_cfgp;
20113859Sml29623 	p_nxge_hw_pt_cfg_t p_cfgp;
20123859Sml29623 
20133859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_update_hw"));
20143859Sml29623 
20153859Sml29623 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
20163859Sml29623 	p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
20173859Sml29623 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
20183859Sml29623 
20193859Sml29623 	status = nxge_fflp_set_hash1(nxgep, p_class_cfgp->init_h1);
20203859Sml29623 	if (status != NXGE_OK) {
20213859Sml29623 		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
20226929Smisaki 		    "nxge_fflp_set_hash1 Failed"));
20233859Sml29623 		return (NXGE_ERROR);
20243859Sml29623 	}
20253859Sml29623 
20263859Sml29623 	status = nxge_fflp_set_hash2(nxgep, p_class_cfgp->init_h2);
20273859Sml29623 	if (status != NXGE_OK) {
20283859Sml29623 		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
20296929Smisaki 		    "nxge_fflp_set_hash2 Failed"));
20303859Sml29623 		return (NXGE_ERROR);
20313859Sml29623 	}
20323859Sml29623 	vlan_table = p_class_cfgp->vlan_tbl;
20333859Sml29623 
20343859Sml29623 	/* configure vlan tables */
20353859Sml29623 	pa = (p_nxge_param_t)&nxgep->param_arr[param_vlan_2rdc_grp];
20365125Sjoycey #if defined(__i386)
20375125Sjoycey 	val_ptr = (uint64_t *)(uint32_t)pa->value;
20385125Sjoycey #else
20393859Sml29623 	val_ptr = (uint64_t *)pa->value;
20405125Sjoycey #endif
20413859Sml29623 	cfgd_vlans = ((pa->type & NXGE_PARAM_ARRAY_CNT_MASK) >>
20426929Smisaki 	    NXGE_PARAM_ARRAY_CNT_SHIFT);
20433859Sml29623 
20443859Sml29623 	for (i = 0; i < cfgd_vlans; i++) {
20453859Sml29623 		p_map = (nxge_param_map_t *)&val_ptr[i];
20463859Sml29623 		if (vlan_table[p_map->param_id].flag) {
20473859Sml29623 			status = nxge_fflp_config_vlan_table(nxgep,
20486929Smisaki 			    p_map->param_id);
20493859Sml29623 			if (status != NXGE_OK) {
20503859Sml29623 				NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
20516929Smisaki 				    "nxge_fflp_config_vlan_table Failed"));
20523859Sml29623 				return (NXGE_ERROR);
20533859Sml29623 			}
20543859Sml29623 		}
20553859Sml29623 	}
20563859Sml29623 
20573859Sml29623 	/* config MAC addresses */
20583859Sml29623 	num_macs = p_cfgp->max_macs;
20593859Sml29623 	pa = (p_nxge_param_t)&nxgep->param_arr[param_mac_2rdc_grp];
20605125Sjoycey #if defined(__i386)
20615125Sjoycey 	val_ptr = (uint64_t *)(uint32_t)pa->value;
20625125Sjoycey #else
20633859Sml29623 	val_ptr = (uint64_t *)pa->value;
20645125Sjoycey #endif
20653859Sml29623 
20663859Sml29623 	for (alt_mac = 0; alt_mac < num_macs; alt_mac++) {
20673859Sml29623 		if (p_class_cfgp->mac_host_info[alt_mac].flag) {
20683859Sml29623 			status = nxge_logical_mac_assign_rdc_table(nxgep,
20696929Smisaki 			    alt_mac);
20703859Sml29623 			if (status != NXGE_OK) {
20713859Sml29623 				NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
20726929Smisaki 				    "nxge_logical_mac_assign_rdc_table"
20736929Smisaki 				    " Failed"));
20743859Sml29623 				return (NXGE_ERROR);
20753859Sml29623 			}
20763859Sml29623 		}
20773859Sml29623 	}
20783859Sml29623 
20793859Sml29623 	/* Config Hash values */
20805523Syc148097 	/* config classes */
20813859Sml29623 	status = nxge_fflp_ip_class_config_all(nxgep);
20823859Sml29623 	if (status != NXGE_OK) {
20833859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20846929Smisaki 		    "nxge_fflp_ip_class_config_all Failed"));
20853859Sml29623 		return (NXGE_ERROR);
20863859Sml29623 	}
20873859Sml29623 	return (NXGE_OK);
20883859Sml29623 }
20893859Sml29623 
20903859Sml29623 nxge_status_t
20913859Sml29623 nxge_classify_init_hw(p_nxge_t nxgep)
20923859Sml29623 {
20933859Sml29623 	nxge_status_t status = NXGE_OK;
20943859Sml29623 
20953859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_classify_init_hw"));
20963859Sml29623 
20973859Sml29623 	if (nxgep->classifier.state & NXGE_FFLP_HW_INIT) {
20983859Sml29623 		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
20996929Smisaki 		    "nxge_classify_init_hw already init"));
21003859Sml29623 		return (NXGE_OK);
21013859Sml29623 	}
21023859Sml29623 
21033859Sml29623 	/* Now do a real configuration */
21043859Sml29623 	status = nxge_fflp_update_hw(nxgep);
21053859Sml29623 	if (status != NXGE_OK) {
21063859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21076929Smisaki 		    "nxge_fflp_update_hw failed"));
21083859Sml29623 		return (NXGE_ERROR);
21093859Sml29623 	}
21103859Sml29623 
21113859Sml29623 	/* Init RDC tables? ? who should do that? rxdma or fflp ? */
21123859Sml29623 	/* attach rdc table to the MAC port. */
21133859Sml29623 	status = nxge_main_mac_assign_rdc_table(nxgep);
21143859Sml29623 	if (status != NXGE_OK) {
21153859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21166929Smisaki 		    "nxge_main_mac_assign_rdc_table failed"));
21173859Sml29623 		return (NXGE_ERROR);
21183859Sml29623 	}
21193859Sml29623 
21203859Sml29623 	status = nxge_alt_mcast_mac_assign_rdc_table(nxgep);
21213859Sml29623 	if (status != NXGE_OK) {
21223859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21236929Smisaki 		    "nxge_multicast_mac_assign_rdc_table failed"));
21243859Sml29623 		return (NXGE_ERROR);
21253859Sml29623 	}
21263859Sml29623 
2127*11304SJanie.Lu@Sun.COM 	if (nxgep->classifier.fragment_bug == 1) {
2128*11304SJanie.Lu@Sun.COM 		status = nxge_tcam_handle_ip_fragment(nxgep);
2129*11304SJanie.Lu@Sun.COM 		if (status != NXGE_OK) {
2130*11304SJanie.Lu@Sun.COM 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2131*11304SJanie.Lu@Sun.COM 			    "nxge_tcam_handle_ip_fragment failed"));
2132*11304SJanie.Lu@Sun.COM 			return (NXGE_ERROR);
2133*11304SJanie.Lu@Sun.COM 		}
21343859Sml29623 	}
21353859Sml29623 
21363859Sml29623 	nxgep->classifier.state |= NXGE_FFLP_HW_INIT;
21373859Sml29623 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_classify_init_hw"));
21383859Sml29623 	return (NXGE_OK);
21393859Sml29623 }
21403859Sml29623 
21413859Sml29623 nxge_status_t
21423859Sml29623 nxge_fflp_handle_sys_errors(p_nxge_t nxgep)
21433859Sml29623 {
21443859Sml29623 	npi_handle_t handle;
21453859Sml29623 	p_nxge_fflp_stats_t statsp;
21463859Sml29623 	uint8_t portn, rdc_grp;
21473859Sml29623 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
21483859Sml29623 	p_nxge_hw_pt_cfg_t p_cfgp;
21493859Sml29623 	vlan_par_err_t vlan_err;
21503859Sml29623 	tcam_err_t tcam_err;
21513859Sml29623 	hash_lookup_err_log1_t fcram1_err;
21523859Sml29623 	hash_lookup_err_log2_t fcram2_err;
21533859Sml29623 	hash_tbl_data_log_t fcram_err;
21543859Sml29623 
21553859Sml29623 	handle = nxgep->npi_handle;
21563859Sml29623 	statsp = (p_nxge_fflp_stats_t)&nxgep->statsp->fflp_stats;
21573859Sml29623 	portn = nxgep->mac.portnum;
21583859Sml29623 
21593859Sml29623 	/*
21603859Sml29623 	 * need to read the fflp error registers to figure out what the error
21613859Sml29623 	 * is
21623859Sml29623 	 */
21633859Sml29623 	npi_fflp_vlan_error_get(handle, &vlan_err);
21643859Sml29623 	npi_fflp_tcam_error_get(handle, &tcam_err);
21653859Sml29623 
21663859Sml29623 	if (vlan_err.bits.ldw.m_err || vlan_err.bits.ldw.err) {
21673859Sml29623 		NXGE_ERROR_MSG((nxgep, FFLP_CTL,
21686929Smisaki 		    " vlan table parity error on port %d"
21696929Smisaki 		    " addr: 0x%x data: 0x%x",
21706929Smisaki 		    portn, vlan_err.bits.ldw.addr,
21716929Smisaki 		    vlan_err.bits.ldw.data));
21723859Sml29623 		statsp->vlan_parity_err++;
21733859Sml29623 
21743859Sml29623 		if (vlan_err.bits.ldw.m_err) {
21753859Sml29623 			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
21766929Smisaki 			    " vlan table multiple errors on port %d",
21776929Smisaki 			    portn));
21783859Sml29623 		}
21793859Sml29623 		statsp->errlog.vlan = (uint32_t)vlan_err.value;
21803859Sml29623 		NXGE_FM_REPORT_ERROR(nxgep, NULL, NULL,
21816929Smisaki 		    NXGE_FM_EREPORT_FFLP_VLAN_PAR_ERR);
21823859Sml29623 		npi_fflp_vlan_error_clear(handle);
21833859Sml29623 	}
21843859Sml29623 
21853859Sml29623 	if (tcam_err.bits.ldw.err) {
21863859Sml29623 		if (tcam_err.bits.ldw.p_ecc != 0) {
21873859Sml29623 			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
21886929Smisaki 			    " TCAM ECC error on port %d"
21896929Smisaki 			    " TCAM entry: 0x%x syndrome: 0x%x",
21906929Smisaki 			    portn, tcam_err.bits.ldw.addr,
21916929Smisaki 			    tcam_err.bits.ldw.syndrome));
21923859Sml29623 			statsp->tcam_ecc_err++;
21933859Sml29623 		} else {
21943859Sml29623 			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
21956929Smisaki 			    " TCAM Parity error on port %d"
21966929Smisaki 			    " addr: 0x%x parity value: 0x%x",
21976929Smisaki 			    portn, tcam_err.bits.ldw.addr,
21986929Smisaki 			    tcam_err.bits.ldw.syndrome));
21993859Sml29623 			statsp->tcam_parity_err++;
22003859Sml29623 		}
22013859Sml29623 
22023859Sml29623 		if (tcam_err.bits.ldw.mult) {
22033859Sml29623 			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
22046929Smisaki 			    " TCAM Multiple errors on port %d", portn));
22053859Sml29623 		} else {
22063859Sml29623 			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
22076929Smisaki 			    " TCAM PIO error on port %d", portn));
22083859Sml29623 		}
22093859Sml29623 
22103859Sml29623 		statsp->errlog.tcam = (uint32_t)tcam_err.value;
22113859Sml29623 		NXGE_FM_REPORT_ERROR(nxgep, NULL, NULL,
22126929Smisaki 		    NXGE_FM_EREPORT_FFLP_TCAM_ERR);
22133859Sml29623 		npi_fflp_tcam_error_clear(handle);
22143859Sml29623 	}
22153859Sml29623 
22163859Sml29623 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
22173859Sml29623 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
22183859Sml29623 
22196495Sspeer 	for (rdc_grp = 0; rdc_grp < NXGE_MAX_RDC_GROUPS; rdc_grp++) {
22206495Sspeer 		if (p_cfgp->grpids[rdc_grp]) {
22216495Sspeer 			npi_fflp_fcram_error_get(handle, &fcram_err, rdc_grp);
22226495Sspeer 			if (fcram_err.bits.ldw.pio_err) {
22236495Sspeer 				NXGE_ERROR_MSG((nxgep, FFLP_CTL,
22246929Smisaki 				    " FCRAM PIO ECC error on port %d"
22256929Smisaki 				    " rdc group: %d Hash Table addr: 0x%x"
22266929Smisaki 				    " syndrome: 0x%x",
22276929Smisaki 				    portn, rdc_grp,
22286929Smisaki 				    fcram_err.bits.ldw.fcram_addr,
22296929Smisaki 				    fcram_err.bits.ldw.syndrome));
22306495Sspeer 				statsp->hash_pio_err[rdc_grp]++;
22316495Sspeer 				statsp->errlog.hash_pio[rdc_grp] =
22326495Sspeer 				    (uint32_t)fcram_err.value;
22336495Sspeer 				NXGE_FM_REPORT_ERROR(nxgep, NULL, NULL,
22346495Sspeer 				    NXGE_FM_EREPORT_FFLP_HASHT_DATA_ERR);
22356495Sspeer 				npi_fflp_fcram_error_clear(handle, rdc_grp);
22366495Sspeer 			}
22373859Sml29623 		}
22383859Sml29623 	}
22393859Sml29623 
22403859Sml29623 	npi_fflp_fcram_error_log1_get(handle, &fcram1_err);
22413859Sml29623 	if (fcram1_err.bits.ldw.ecc_err) {
22423859Sml29623 		char *multi_str = "";
22433859Sml29623 		char *multi_bit_str = "";
22443859Sml29623 
22453859Sml29623 		npi_fflp_fcram_error_log2_get(handle, &fcram2_err);
22463859Sml29623 		if (fcram1_err.bits.ldw.mult_lk) {
22473859Sml29623 			multi_str = "multiple";
22483859Sml29623 		}
22493859Sml29623 		if (fcram1_err.bits.ldw.mult_bit) {
22503859Sml29623 			multi_bit_str = "multiple bits";
22513859Sml29623 		}
22525523Syc148097 		statsp->hash_lookup_err++;
22533859Sml29623 		NXGE_ERROR_MSG((nxgep, FFLP_CTL,
22546929Smisaki 		    " FCRAM %s lookup %s ECC error on port %d"
22556929Smisaki 		    " H1: 0x%x Subarea: 0x%x Syndrome: 0x%x",
22566929Smisaki 		    multi_str, multi_bit_str, portn,
22576929Smisaki 		    fcram2_err.bits.ldw.h1,
22586929Smisaki 		    fcram2_err.bits.ldw.subarea,
22596929Smisaki 		    fcram2_err.bits.ldw.syndrome));
22603859Sml29623 		NXGE_FM_REPORT_ERROR(nxgep, NULL, NULL,
22616929Smisaki 		    NXGE_FM_EREPORT_FFLP_HASHT_LOOKUP_ERR);
22623859Sml29623 	}
22633859Sml29623 	statsp->errlog.hash_lookup1 = (uint32_t)fcram1_err.value;
22643859Sml29623 	statsp->errlog.hash_lookup2 = (uint32_t)fcram2_err.value;
22653859Sml29623 	return (NXGE_OK);
22663859Sml29623 }
2267*11304SJanie.Lu@Sun.COM 
2268*11304SJanie.Lu@Sun.COM int
2269*11304SJanie.Lu@Sun.COM nxge_get_valid_tcam_cnt(p_nxge_t nxgep) {
2270*11304SJanie.Lu@Sun.COM 	return ((nxgep->classifier.fragment_bug == 1) ?
2271*11304SJanie.Lu@Sun.COM 		nxgep->classifier.tcam_entry_cnt - 1 :
2272*11304SJanie.Lu@Sun.COM 		nxgep->classifier.tcam_entry_cnt);
2273*11304SJanie.Lu@Sun.COM }
2274*11304SJanie.Lu@Sun.COM 
2275*11304SJanie.Lu@Sun.COM int
2276*11304SJanie.Lu@Sun.COM nxge_rxdma_channel_cnt(p_nxge_t nxgep)
2277*11304SJanie.Lu@Sun.COM {
2278*11304SJanie.Lu@Sun.COM 	p_nxge_dma_pt_cfg_t p_dma_cfgp;
2279*11304SJanie.Lu@Sun.COM 	p_nxge_hw_pt_cfg_t p_cfgp;
2280*11304SJanie.Lu@Sun.COM 
2281*11304SJanie.Lu@Sun.COM 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2282*11304SJanie.Lu@Sun.COM 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
2283*11304SJanie.Lu@Sun.COM 	return (p_cfgp->max_rdcs);
2284*11304SJanie.Lu@Sun.COM }
2285*11304SJanie.Lu@Sun.COM 
2286*11304SJanie.Lu@Sun.COM /* ARGSUSED */
2287*11304SJanie.Lu@Sun.COM int
2288*11304SJanie.Lu@Sun.COM nxge_rxclass_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp)
2289*11304SJanie.Lu@Sun.COM {
2290*11304SJanie.Lu@Sun.COM 	uint32_t cmd;
2291*11304SJanie.Lu@Sun.COM 	rx_class_cfg_t *cfg_info = (rx_class_cfg_t *)mp->b_rptr;
2292*11304SJanie.Lu@Sun.COM 
2293*11304SJanie.Lu@Sun.COM 	if (nxgep == NULL) {
2294*11304SJanie.Lu@Sun.COM 		return (-1);
2295*11304SJanie.Lu@Sun.COM 	}
2296*11304SJanie.Lu@Sun.COM 	cmd = cfg_info->cmd;
2297*11304SJanie.Lu@Sun.COM 	switch (cmd) {
2298*11304SJanie.Lu@Sun.COM 	default:
2299*11304SJanie.Lu@Sun.COM 		return (-1);
2300*11304SJanie.Lu@Sun.COM 
2301*11304SJanie.Lu@Sun.COM 	case NXGE_RX_CLASS_GCHAN:
2302*11304SJanie.Lu@Sun.COM 		cfg_info->data = nxge_rxdma_channel_cnt(nxgep);
2303*11304SJanie.Lu@Sun.COM 		break;
2304*11304SJanie.Lu@Sun.COM 	case NXGE_RX_CLASS_GRULE_CNT:
2305*11304SJanie.Lu@Sun.COM 		MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_tcam_lock);
2306*11304SJanie.Lu@Sun.COM 		cfg_info->rule_cnt = nxge_get_valid_tcam_cnt(nxgep);
2307*11304SJanie.Lu@Sun.COM 		MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_tcam_lock);
2308*11304SJanie.Lu@Sun.COM 		break;
2309*11304SJanie.Lu@Sun.COM 	case NXGE_RX_CLASS_GRULE:
2310*11304SJanie.Lu@Sun.COM 		nxge_get_tcam_entry(nxgep, &cfg_info->fs);
2311*11304SJanie.Lu@Sun.COM 		break;
2312*11304SJanie.Lu@Sun.COM 	case NXGE_RX_CLASS_GRULE_ALL:
2313*11304SJanie.Lu@Sun.COM 		nxge_get_tcam_entry_all(nxgep, cfg_info);
2314*11304SJanie.Lu@Sun.COM 		break;
2315*11304SJanie.Lu@Sun.COM 	case NXGE_RX_CLASS_RULE_DEL:
2316*11304SJanie.Lu@Sun.COM 		nxge_del_tcam_entry(nxgep, cfg_info->fs.location);
2317*11304SJanie.Lu@Sun.COM 		break;
2318*11304SJanie.Lu@Sun.COM 	case NXGE_RX_CLASS_RULE_INS:
2319*11304SJanie.Lu@Sun.COM 		(void) nxge_add_tcam_entry(nxgep, &cfg_info->fs);
2320*11304SJanie.Lu@Sun.COM 		break;
2321*11304SJanie.Lu@Sun.COM 	}
2322*11304SJanie.Lu@Sun.COM 	return (0);
2323*11304SJanie.Lu@Sun.COM }
2324*11304SJanie.Lu@Sun.COM /* ARGSUSED */
2325*11304SJanie.Lu@Sun.COM int
2326*11304SJanie.Lu@Sun.COM nxge_rxhash_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp)
2327*11304SJanie.Lu@Sun.COM {
2328*11304SJanie.Lu@Sun.COM 	uint32_t cmd;
2329*11304SJanie.Lu@Sun.COM 	cfg_cmd_t	*cfg_info = (cfg_cmd_t *)mp->b_rptr;
2330*11304SJanie.Lu@Sun.COM 
2331*11304SJanie.Lu@Sun.COM 	if (nxgep == NULL) {
2332*11304SJanie.Lu@Sun.COM 		return (-1);
2333*11304SJanie.Lu@Sun.COM 	}
2334*11304SJanie.Lu@Sun.COM 	cmd = cfg_info->cmd;
2335*11304SJanie.Lu@Sun.COM 
2336*11304SJanie.Lu@Sun.COM 	switch (cmd) {
2337*11304SJanie.Lu@Sun.COM 	default:
2338*11304SJanie.Lu@Sun.COM 		return (-1);
2339*11304SJanie.Lu@Sun.COM 	case NXGE_IPTUN_CFG_ADD_CLS:
2340*11304SJanie.Lu@Sun.COM 		nxge_add_iptun_class(nxgep, &cfg_info->iptun_cfg,
2341*11304SJanie.Lu@Sun.COM 		    &cfg_info->class_id);
2342*11304SJanie.Lu@Sun.COM 		break;
2343*11304SJanie.Lu@Sun.COM 	case NXGE_IPTUN_CFG_SET_HASH:
2344*11304SJanie.Lu@Sun.COM 		nxge_cfg_iptun_hash(nxgep, &cfg_info->iptun_cfg,
2345*11304SJanie.Lu@Sun.COM 		    cfg_info->class_id);
2346*11304SJanie.Lu@Sun.COM 		break;
2347*11304SJanie.Lu@Sun.COM 	case NXGE_IPTUN_CFG_DEL_CLS:
2348*11304SJanie.Lu@Sun.COM 		nxge_del_iptun_class(nxgep, cfg_info->class_id);
2349*11304SJanie.Lu@Sun.COM 		break;
2350*11304SJanie.Lu@Sun.COM 	case NXGE_IPTUN_CFG_GET_CLS:
2351*11304SJanie.Lu@Sun.COM 		nxge_get_iptun_class(nxgep, &cfg_info->iptun_cfg,
2352*11304SJanie.Lu@Sun.COM 		    cfg_info->class_id);
2353*11304SJanie.Lu@Sun.COM 		break;
2354*11304SJanie.Lu@Sun.COM 	case NXGE_CLS_CFG_SET_SYM:
2355*11304SJanie.Lu@Sun.COM 		nxge_set_ip_cls_sym(nxgep, cfg_info->class_id, cfg_info->sym);
2356*11304SJanie.Lu@Sun.COM 		break;
2357*11304SJanie.Lu@Sun.COM 	case NXGE_CLS_CFG_GET_SYM:
2358*11304SJanie.Lu@Sun.COM 		nxge_get_ip_cls_sym(nxgep, cfg_info->class_id, &cfg_info->sym);
2359*11304SJanie.Lu@Sun.COM 		break;
2360*11304SJanie.Lu@Sun.COM 	}
2361*11304SJanie.Lu@Sun.COM 	return (0);
2362*11304SJanie.Lu@Sun.COM }
2363*11304SJanie.Lu@Sun.COM 
2364*11304SJanie.Lu@Sun.COM void
2365*11304SJanie.Lu@Sun.COM nxge_get_tcam_entry_all(p_nxge_t nxgep, rx_class_cfg_t *cfgp)
2366*11304SJanie.Lu@Sun.COM {
2367*11304SJanie.Lu@Sun.COM 	nxge_classify_t *clasp = &nxgep->classifier;
2368*11304SJanie.Lu@Sun.COM 	uint16_t	n_entries;
2369*11304SJanie.Lu@Sun.COM 	int		i, j, k;
2370*11304SJanie.Lu@Sun.COM 	tcam_flow_spec_t	*tcam_entryp;
2371*11304SJanie.Lu@Sun.COM 
2372*11304SJanie.Lu@Sun.COM 	cfgp->data = clasp->tcam_size;
2373*11304SJanie.Lu@Sun.COM 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_tcam_lock);
2374*11304SJanie.Lu@Sun.COM 	n_entries = cfgp->rule_cnt;
2375*11304SJanie.Lu@Sun.COM 
2376*11304SJanie.Lu@Sun.COM 	for (i = 0, j = 0; j < cfgp->data; j++) {
2377*11304SJanie.Lu@Sun.COM 		k = nxge_tcam_get_index(nxgep, j);
2378*11304SJanie.Lu@Sun.COM 		tcam_entryp = &clasp->tcam_entries[k];
2379*11304SJanie.Lu@Sun.COM 		if (tcam_entryp->valid != 1)
2380*11304SJanie.Lu@Sun.COM 			continue;
2381*11304SJanie.Lu@Sun.COM 		cfgp->rule_locs[i] = j;
2382*11304SJanie.Lu@Sun.COM 		i++;
2383*11304SJanie.Lu@Sun.COM 	};
2384*11304SJanie.Lu@Sun.COM 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_tcam_lock);
2385*11304SJanie.Lu@Sun.COM 
2386*11304SJanie.Lu@Sun.COM 	if (n_entries != i) {
2387*11304SJanie.Lu@Sun.COM 		/* print warning, this should not happen */
2388*11304SJanie.Lu@Sun.COM 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_get_tcam_entry_all"
2389*11304SJanie.Lu@Sun.COM 		    "n_entries[%d] != i[%d]!!!", n_entries, i));
2390*11304SJanie.Lu@Sun.COM 	}
2391*11304SJanie.Lu@Sun.COM }
2392*11304SJanie.Lu@Sun.COM 
2393*11304SJanie.Lu@Sun.COM 
2394*11304SJanie.Lu@Sun.COM /* Entries for the ports are interleaved in the TCAM */
2395*11304SJanie.Lu@Sun.COM static uint16_t
2396*11304SJanie.Lu@Sun.COM nxge_tcam_get_index(p_nxge_t nxgep, uint16_t index)
2397*11304SJanie.Lu@Sun.COM {
2398*11304SJanie.Lu@Sun.COM 	/* One entry reserved for IP fragment rule */
2399*11304SJanie.Lu@Sun.COM 	if (index >= (nxgep->classifier.tcam_size - 1))
2400*11304SJanie.Lu@Sun.COM 		index = 0;
2401*11304SJanie.Lu@Sun.COM 	if (nxgep->classifier.fragment_bug == 1)
2402*11304SJanie.Lu@Sun.COM 		index++;
2403*11304SJanie.Lu@Sun.COM 	return (nxgep->classifier.tcam_top + (index * nxgep->nports));
2404*11304SJanie.Lu@Sun.COM }
2405*11304SJanie.Lu@Sun.COM 
2406*11304SJanie.Lu@Sun.COM static uint32_t
2407*11304SJanie.Lu@Sun.COM nxge_tcam_cls_to_flow(uint32_t class_code) {
2408*11304SJanie.Lu@Sun.COM 	switch (class_code) {
2409*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_TCP_IPV4:
2410*11304SJanie.Lu@Sun.COM 		return (FSPEC_TCPIP4);
2411*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_UDP_IPV4:
2412*11304SJanie.Lu@Sun.COM 		return (FSPEC_UDPIP4);
2413*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_AH_ESP_IPV4:
2414*11304SJanie.Lu@Sun.COM 		return (FSPEC_AHIP4);
2415*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_SCTP_IPV4:
2416*11304SJanie.Lu@Sun.COM 		return (FSPEC_SCTPIP4);
2417*11304SJanie.Lu@Sun.COM 	case  TCAM_CLASS_TCP_IPV6:
2418*11304SJanie.Lu@Sun.COM 		return (FSPEC_TCPIP6);
2419*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_UDP_IPV6:
2420*11304SJanie.Lu@Sun.COM 		return (FSPEC_UDPIP6);
2421*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_AH_ESP_IPV6:
2422*11304SJanie.Lu@Sun.COM 		return (FSPEC_AHIP6);
2423*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_SCTP_IPV6:
2424*11304SJanie.Lu@Sun.COM 		return (FSPEC_SCTPIP6);
2425*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_IP_USER_4:
2426*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_IP_USER_5:
2427*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_IP_USER_6:
2428*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_IP_USER_7:
2429*11304SJanie.Lu@Sun.COM 		return (FSPEC_IP_USR);
2430*11304SJanie.Lu@Sun.COM 	default:
2431*11304SJanie.Lu@Sun.COM 		NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "nxge_tcam_cls_to_flow"
2432*11304SJanie.Lu@Sun.COM 		    ": Unknown class code [0x%x]", class_code));
2433*11304SJanie.Lu@Sun.COM 		break;
2434*11304SJanie.Lu@Sun.COM 	}
2435*11304SJanie.Lu@Sun.COM 	return (0);
2436*11304SJanie.Lu@Sun.COM }
2437*11304SJanie.Lu@Sun.COM 
2438*11304SJanie.Lu@Sun.COM void
2439*11304SJanie.Lu@Sun.COM nxge_get_tcam_entry(p_nxge_t nxgep, flow_resource_t *fs)
2440*11304SJanie.Lu@Sun.COM {
2441*11304SJanie.Lu@Sun.COM 	uint16_t 	index;
2442*11304SJanie.Lu@Sun.COM 	tcam_flow_spec_t *tcam_ep;
2443*11304SJanie.Lu@Sun.COM 	tcam_entry_t	*tp;
2444*11304SJanie.Lu@Sun.COM 	flow_spec_t	*fspec;
2445*11304SJanie.Lu@Sun.COM 	tcpip4_spec_t 	*fspec_key;
2446*11304SJanie.Lu@Sun.COM 	tcpip4_spec_t 	*fspec_mask;
2447*11304SJanie.Lu@Sun.COM 
2448*11304SJanie.Lu@Sun.COM 	index = nxge_tcam_get_index(nxgep, (uint16_t)fs->location);
2449*11304SJanie.Lu@Sun.COM 	tcam_ep = &nxgep->classifier.tcam_entries[index];
2450*11304SJanie.Lu@Sun.COM 	if (tcam_ep->valid != 1) {
2451*11304SJanie.Lu@Sun.COM 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_get_tcam_entry: :"
2452*11304SJanie.Lu@Sun.COM 		    "Entry [%d] invalid for index [%d]", fs->location, index));
2453*11304SJanie.Lu@Sun.COM 		return;
2454*11304SJanie.Lu@Sun.COM 	}
2455*11304SJanie.Lu@Sun.COM 
2456*11304SJanie.Lu@Sun.COM 	/* Fill the flow spec entry */
2457*11304SJanie.Lu@Sun.COM 	tp = &tcam_ep->tce;
2458*11304SJanie.Lu@Sun.COM 	fspec = &fs->flow_spec;
2459*11304SJanie.Lu@Sun.COM 	fspec->flow_type = nxge_tcam_cls_to_flow(tp->ip4_class_key);
2460*11304SJanie.Lu@Sun.COM 
2461*11304SJanie.Lu@Sun.COM 	/* TODO - look at proto field to differentiate between AH and ESP */
2462*11304SJanie.Lu@Sun.COM 	if (fspec->flow_type == FSPEC_AHIP4) {
2463*11304SJanie.Lu@Sun.COM 		if (tp->ip4_proto_key == IPPROTO_ESP)
2464*11304SJanie.Lu@Sun.COM 			fspec->flow_type = FSPEC_ESPIP4;
2465*11304SJanie.Lu@Sun.COM 	}
2466*11304SJanie.Lu@Sun.COM 
2467*11304SJanie.Lu@Sun.COM 	switch (tp->ip4_class_key) {
2468*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_TCP_IPV4:
2469*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_UDP_IPV4:
2470*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_AH_ESP_IPV4:
2471*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_SCTP_IPV4:
2472*11304SJanie.Lu@Sun.COM 		fspec_key = (tcpip4_spec_t *)&fspec->uh.tcpip4spec;
2473*11304SJanie.Lu@Sun.COM 		fspec_mask = (tcpip4_spec_t *)&fspec->um.tcpip4spec;
2474*11304SJanie.Lu@Sun.COM 		FSPEC_IPV4_ADDR(fspec_key->ip4dst, tp->ip4_dest_key);
2475*11304SJanie.Lu@Sun.COM 		FSPEC_IPV4_ADDR(fspec_mask->ip4dst, tp->ip4_dest_mask);
2476*11304SJanie.Lu@Sun.COM 		FSPEC_IPV4_ADDR(fspec_key->ip4src, tp->ip4_src_key);
2477*11304SJanie.Lu@Sun.COM 		FSPEC_IPV4_ADDR(fspec_mask->ip4src, tp->ip4_src_mask);
2478*11304SJanie.Lu@Sun.COM 		fspec_key->tos = tp->ip4_tos_key;
2479*11304SJanie.Lu@Sun.COM 		fspec_mask->tos = tp->ip4_tos_mask;
2480*11304SJanie.Lu@Sun.COM 		break;
2481*11304SJanie.Lu@Sun.COM 	default:
2482*11304SJanie.Lu@Sun.COM 		break;
2483*11304SJanie.Lu@Sun.COM 	}
2484*11304SJanie.Lu@Sun.COM 
2485*11304SJanie.Lu@Sun.COM 	switch (tp->ip4_class_key) {
2486*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_TCP_IPV4:
2487*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_UDP_IPV4:
2488*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_SCTP_IPV4:
2489*11304SJanie.Lu@Sun.COM 		FSPEC_IP_PORTS(fspec_key->pdst, fspec_key->psrc,
2490*11304SJanie.Lu@Sun.COM 		    tp->ip4_port_key);
2491*11304SJanie.Lu@Sun.COM 		FSPEC_IP_PORTS(fspec_mask->pdst, fspec_mask->psrc,
2492*11304SJanie.Lu@Sun.COM 		    tp->ip4_port_mask);
2493*11304SJanie.Lu@Sun.COM 		break;
2494*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_AH_ESP_IPV4:
2495*11304SJanie.Lu@Sun.COM 		fspec->uh.ahip4spec.spi = tp->ip4_port_key;
2496*11304SJanie.Lu@Sun.COM 		fspec->um.ahip4spec.spi = tp->ip4_port_mask;
2497*11304SJanie.Lu@Sun.COM 		break;
2498*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_IP_USER_4:
2499*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_IP_USER_5:
2500*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_IP_USER_6:
2501*11304SJanie.Lu@Sun.COM 	case TCAM_CLASS_IP_USER_7:
2502*11304SJanie.Lu@Sun.COM 		fspec->uh.ip_usr_spec.l4_4_bytes = tp->ip4_port_key;
2503*11304SJanie.Lu@Sun.COM 		fspec->um.ip_usr_spec.l4_4_bytes = tp->ip4_port_mask;
2504*11304SJanie.Lu@Sun.COM 		fspec->uh.ip_usr_spec.ip_ver = FSPEC_IP4;
2505*11304SJanie.Lu@Sun.COM 		fspec->uh.ip_usr_spec.proto = tp->ip4_proto_key;
2506*11304SJanie.Lu@Sun.COM 		fspec->um.ip_usr_spec.proto = tp->ip4_proto_mask;
2507*11304SJanie.Lu@Sun.COM 		break;
2508*11304SJanie.Lu@Sun.COM 	default:
2509*11304SJanie.Lu@Sun.COM 		break;
2510*11304SJanie.Lu@Sun.COM 	}
2511*11304SJanie.Lu@Sun.COM 
2512*11304SJanie.Lu@Sun.COM 	if (tp->match_action.bits.ldw.disc == 1) {
2513*11304SJanie.Lu@Sun.COM 		fs->channel_cookie = NXGE_PKT_DISCARD;
2514*11304SJanie.Lu@Sun.COM 	} else {
2515*11304SJanie.Lu@Sun.COM 		fs->channel_cookie = tp->match_action.bits.ldw.offset;
2516*11304SJanie.Lu@Sun.COM 	}
2517*11304SJanie.Lu@Sun.COM }
2518*11304SJanie.Lu@Sun.COM 
2519*11304SJanie.Lu@Sun.COM void
2520*11304SJanie.Lu@Sun.COM nxge_del_tcam_entry(p_nxge_t nxgep, uint32_t location)
2521*11304SJanie.Lu@Sun.COM {
2522*11304SJanie.Lu@Sun.COM 	npi_status_t rs = NPI_SUCCESS;
2523*11304SJanie.Lu@Sun.COM 	uint16_t 	index;
2524*11304SJanie.Lu@Sun.COM 	tcam_flow_spec_t *tcam_ep;
2525*11304SJanie.Lu@Sun.COM 	tcam_entry_t	*tp;
2526*11304SJanie.Lu@Sun.COM 	tcam_class_t	class;
2527*11304SJanie.Lu@Sun.COM 
2528*11304SJanie.Lu@Sun.COM 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_tcam_lock);
2529*11304SJanie.Lu@Sun.COM 	index = nxge_tcam_get_index(nxgep, (uint16_t)location);
2530*11304SJanie.Lu@Sun.COM 	tcam_ep = &nxgep->classifier.tcam_entries[index];
2531*11304SJanie.Lu@Sun.COM 	if (tcam_ep->valid != 1) {
2532*11304SJanie.Lu@Sun.COM 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_tcam_entry: :"
2533*11304SJanie.Lu@Sun.COM 		    "Entry [%d] invalid for index [%d]", location, index));
2534*11304SJanie.Lu@Sun.COM 		goto fail;
2535*11304SJanie.Lu@Sun.COM 	}
2536*11304SJanie.Lu@Sun.COM 
2537*11304SJanie.Lu@Sun.COM 	/* Fill the flow spec entry */
2538*11304SJanie.Lu@Sun.COM 	tp = &tcam_ep->tce;
2539*11304SJanie.Lu@Sun.COM 	class = tp->ip4_class_key;
2540*11304SJanie.Lu@Sun.COM 	if (class >= TCAM_CLASS_IP_USER_4 && class <= TCAM_CLASS_IP_USER_7) {
2541*11304SJanie.Lu@Sun.COM 		int i;
2542*11304SJanie.Lu@Sun.COM 		nxge_usr_l3_cls_t *l3_ucls_p;
2543*11304SJanie.Lu@Sun.COM 		p_nxge_hw_list_t hw_p = nxgep->nxge_hw_p;
2544*11304SJanie.Lu@Sun.COM 
2545*11304SJanie.Lu@Sun.COM 		for (i = 0; i < NXGE_L3_PROG_CLS; i++) {
2546*11304SJanie.Lu@Sun.COM 			l3_ucls_p = &hw_p->tcam_l3_prog_cls[i];
2547*11304SJanie.Lu@Sun.COM 			if (l3_ucls_p->valid) {
2548*11304SJanie.Lu@Sun.COM 				if (l3_ucls_p->cls == class &&
2549*11304SJanie.Lu@Sun.COM 				    l3_ucls_p->tcam_ref_cnt) {
2550*11304SJanie.Lu@Sun.COM 					l3_ucls_p->tcam_ref_cnt--;
2551*11304SJanie.Lu@Sun.COM 					if (l3_ucls_p->tcam_ref_cnt > 0)
2552*11304SJanie.Lu@Sun.COM 						continue;
2553*11304SJanie.Lu@Sun.COM 					/* disable class */
2554*11304SJanie.Lu@Sun.COM 					rs = npi_fflp_cfg_ip_usr_cls_disable(
2555*11304SJanie.Lu@Sun.COM 					    nxgep->npi_reg_handle,
2556*11304SJanie.Lu@Sun.COM 					    (tcam_class_t)class);
2557*11304SJanie.Lu@Sun.COM 					if (rs != NPI_SUCCESS)
2558*11304SJanie.Lu@Sun.COM 						goto fail;
2559*11304SJanie.Lu@Sun.COM 					l3_ucls_p->cls = 0;
2560*11304SJanie.Lu@Sun.COM 					l3_ucls_p->pid = 0;
2561*11304SJanie.Lu@Sun.COM 					l3_ucls_p->valid = 0;
2562*11304SJanie.Lu@Sun.COM 					break;
2563*11304SJanie.Lu@Sun.COM 				}
2564*11304SJanie.Lu@Sun.COM 			}
2565*11304SJanie.Lu@Sun.COM 		}
2566*11304SJanie.Lu@Sun.COM 		if (i == NXGE_L3_PROG_CLS) {
2567*11304SJanie.Lu@Sun.COM 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2568*11304SJanie.Lu@Sun.COM 			    "nxge_del_tcam_entry: Usr class "
2569*11304SJanie.Lu@Sun.COM 			    "0x%llx not found", (unsigned long long) class));
2570*11304SJanie.Lu@Sun.COM 			goto fail;
2571*11304SJanie.Lu@Sun.COM 		}
2572*11304SJanie.Lu@Sun.COM 	}
2573*11304SJanie.Lu@Sun.COM 
2574*11304SJanie.Lu@Sun.COM 	rs = npi_fflp_tcam_entry_invalidate(nxgep->npi_reg_handle, index);
2575*11304SJanie.Lu@Sun.COM 	if (rs != NPI_SUCCESS) {
2576*11304SJanie.Lu@Sun.COM 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2577*11304SJanie.Lu@Sun.COM 		    "nxge_del_tcam_entry: TCAM invalidate failed "
2578*11304SJanie.Lu@Sun.COM 		    "at loc %d ", location));
2579*11304SJanie.Lu@Sun.COM 		goto fail;
2580*11304SJanie.Lu@Sun.COM 	}
2581*11304SJanie.Lu@Sun.COM 
2582*11304SJanie.Lu@Sun.COM 	nxgep->classifier.tcam_entries[index].valid = 0;
2583*11304SJanie.Lu@Sun.COM 	nxgep->classifier.tcam_entry_cnt--;
2584*11304SJanie.Lu@Sun.COM 
2585*11304SJanie.Lu@Sun.COM 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_tcam_lock);
2586*11304SJanie.Lu@Sun.COM 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_del_tcam_entry"));
2587*11304SJanie.Lu@Sun.COM 	return;
2588*11304SJanie.Lu@Sun.COM fail:
2589*11304SJanie.Lu@Sun.COM 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_tcam_lock);
2590*11304SJanie.Lu@Sun.COM 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2591*11304SJanie.Lu@Sun.COM 	    "<== nxge_del_tcam_entry FAILED"));
2592*11304SJanie.Lu@Sun.COM }
2593*11304SJanie.Lu@Sun.COM 
2594*11304SJanie.Lu@Sun.COM static uint8_t
2595*11304SJanie.Lu@Sun.COM nxge_iptun_pkt_type_to_pid(uint8_t pkt_type)
2596*11304SJanie.Lu@Sun.COM {
2597*11304SJanie.Lu@Sun.COM 	uint8_t pid = 0;
2598*11304SJanie.Lu@Sun.COM 
2599*11304SJanie.Lu@Sun.COM 	switch (pkt_type) {
2600*11304SJanie.Lu@Sun.COM 	case IPTUN_PKT_IPV4:
2601*11304SJanie.Lu@Sun.COM 		pid = 4;
2602*11304SJanie.Lu@Sun.COM 		break;
2603*11304SJanie.Lu@Sun.COM 	case IPTUN_PKT_IPV6:
2604*11304SJanie.Lu@Sun.COM 		pid = 41;
2605*11304SJanie.Lu@Sun.COM 		break;
2606*11304SJanie.Lu@Sun.COM 	case IPTUN_PKT_GRE:
2607*11304SJanie.Lu@Sun.COM 		pid = 47;
2608*11304SJanie.Lu@Sun.COM 		break;
2609*11304SJanie.Lu@Sun.COM 	case IPTUN_PKT_GTP:
2610*11304SJanie.Lu@Sun.COM 		pid = 17;
2611*11304SJanie.Lu@Sun.COM 		break;
2612*11304SJanie.Lu@Sun.COM 	default:
2613*11304SJanie.Lu@Sun.COM 		NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL,
2614*11304SJanie.Lu@Sun.COM 		    "nxge_iptun_pkt_type_to_pid: Unknown pkt type 0x%x",
2615*11304SJanie.Lu@Sun.COM 		    pkt_type));
2616*11304SJanie.Lu@Sun.COM 		break;
2617*11304SJanie.Lu@Sun.COM 	}
2618*11304SJanie.Lu@Sun.COM 
2619*11304SJanie.Lu@Sun.COM 	return (pid);
2620*11304SJanie.Lu@Sun.COM }
2621*11304SJanie.Lu@Sun.COM 
2622*11304SJanie.Lu@Sun.COM static npi_status_t
2623*11304SJanie.Lu@Sun.COM nxge_set_iptun_usr_cls_reg(p_nxge_t nxgep, uint64_t class,
2624*11304SJanie.Lu@Sun.COM 		iptun_cfg_t *iptunp)
2625*11304SJanie.Lu@Sun.COM {
2626*11304SJanie.Lu@Sun.COM 	npi_handle_t handle = nxgep->npi_reg_handle;
2627*11304SJanie.Lu@Sun.COM 	npi_status_t rs = NPI_SUCCESS;
2628*11304SJanie.Lu@Sun.COM 
2629*11304SJanie.Lu@Sun.COM 	switch (iptunp->in_pkt_type) {
2630*11304SJanie.Lu@Sun.COM 	case IPTUN_PKT_IPV4:
2631*11304SJanie.Lu@Sun.COM 	case IPTUN_PKT_IPV6:
2632*11304SJanie.Lu@Sun.COM 		rs = npi_fflp_cfg_ip_usr_cls_set_iptun(handle,
2633*11304SJanie.Lu@Sun.COM 		    (tcam_class_t)class, 0, 0, 0, 0);
2634*11304SJanie.Lu@Sun.COM 		break;
2635*11304SJanie.Lu@Sun.COM 	case IPTUN_PKT_GRE:
2636*11304SJanie.Lu@Sun.COM 		rs = npi_fflp_cfg_ip_usr_cls_set_iptun(handle,
2637*11304SJanie.Lu@Sun.COM 		    (tcam_class_t)class, iptunp->l4b0_val,
2638*11304SJanie.Lu@Sun.COM 		    iptunp->l4b0_mask, 0, 0);
2639*11304SJanie.Lu@Sun.COM 		break;
2640*11304SJanie.Lu@Sun.COM 	case IPTUN_PKT_GTP:
2641*11304SJanie.Lu@Sun.COM 		rs = npi_fflp_cfg_ip_usr_cls_set_iptun(handle,
2642*11304SJanie.Lu@Sun.COM 		    (tcam_class_t)class, 0, 0, iptunp->l4b23_val,
2643*11304SJanie.Lu@Sun.COM 		    (iptunp->l4b23_sel & 0x01));
2644*11304SJanie.Lu@Sun.COM 		break;
2645*11304SJanie.Lu@Sun.COM 	default:
2646*11304SJanie.Lu@Sun.COM 		rs = NPI_FFLP_TCAM_CLASS_INVALID;
2647*11304SJanie.Lu@Sun.COM 		break;
2648*11304SJanie.Lu@Sun.COM 	}
2649*11304SJanie.Lu@Sun.COM 	return (rs);
2650*11304SJanie.Lu@Sun.COM }
2651*11304SJanie.Lu@Sun.COM 
2652*11304SJanie.Lu@Sun.COM void
2653*11304SJanie.Lu@Sun.COM nxge_add_iptun_class(p_nxge_t nxgep, iptun_cfg_t *iptunp,
2654*11304SJanie.Lu@Sun.COM 		uint8_t *cls_idp)
2655*11304SJanie.Lu@Sun.COM {
2656*11304SJanie.Lu@Sun.COM 	int i, add_cls;
2657*11304SJanie.Lu@Sun.COM 	uint8_t pid;
2658*11304SJanie.Lu@Sun.COM 	uint64_t class;
2659*11304SJanie.Lu@Sun.COM 	p_nxge_hw_list_t hw_p = nxgep->nxge_hw_p;
2660*11304SJanie.Lu@Sun.COM 	npi_handle_t handle = nxgep->npi_reg_handle;
2661*11304SJanie.Lu@Sun.COM 	npi_status_t rs = NPI_SUCCESS;
2662*11304SJanie.Lu@Sun.COM 
2663*11304SJanie.Lu@Sun.COM 	pid = nxge_iptun_pkt_type_to_pid(iptunp->in_pkt_type);
2664*11304SJanie.Lu@Sun.COM 	if (pid == 0)
2665*11304SJanie.Lu@Sun.COM 		return;
2666*11304SJanie.Lu@Sun.COM 
2667*11304SJanie.Lu@Sun.COM 	add_cls = 0;
2668*11304SJanie.Lu@Sun.COM 	MUTEX_ENTER(&hw_p->nxge_tcam_lock);
2669*11304SJanie.Lu@Sun.COM 
2670*11304SJanie.Lu@Sun.COM 	/* Get an user programmable class ID */
2671*11304SJanie.Lu@Sun.COM 	for (i = 0; i < NXGE_L3_PROG_CLS; i++) {
2672*11304SJanie.Lu@Sun.COM 		if (hw_p->tcam_l3_prog_cls[i].valid == 0) {
2673*11304SJanie.Lu@Sun.COM 			/* todo add new usr class reg */
2674*11304SJanie.Lu@Sun.COM 			switch (i) {
2675*11304SJanie.Lu@Sun.COM 			case 0:
2676*11304SJanie.Lu@Sun.COM 				class = TCAM_CLASS_IP_USER_4;
2677*11304SJanie.Lu@Sun.COM 				break;
2678*11304SJanie.Lu@Sun.COM 			case 1:
2679*11304SJanie.Lu@Sun.COM 				class = TCAM_CLASS_IP_USER_5;
2680*11304SJanie.Lu@Sun.COM 				break;
2681*11304SJanie.Lu@Sun.COM 			case 2:
2682*11304SJanie.Lu@Sun.COM 				class = TCAM_CLASS_IP_USER_6;
2683*11304SJanie.Lu@Sun.COM 				break;
2684*11304SJanie.Lu@Sun.COM 			case 3:
2685*11304SJanie.Lu@Sun.COM 				class = TCAM_CLASS_IP_USER_7;
2686*11304SJanie.Lu@Sun.COM 				break;
2687*11304SJanie.Lu@Sun.COM 			default:
2688*11304SJanie.Lu@Sun.COM 				break;
2689*11304SJanie.Lu@Sun.COM 			}
2690*11304SJanie.Lu@Sun.COM 			rs = npi_fflp_cfg_ip_usr_cls_set(handle,
2691*11304SJanie.Lu@Sun.COM 			    (tcam_class_t)class, 0, 0, pid, 0);
2692*11304SJanie.Lu@Sun.COM 			if (rs != NPI_SUCCESS)
2693*11304SJanie.Lu@Sun.COM 				goto fail;
2694*11304SJanie.Lu@Sun.COM 
2695*11304SJanie.Lu@Sun.COM 			rs = nxge_set_iptun_usr_cls_reg(nxgep, class, iptunp);
2696*11304SJanie.Lu@Sun.COM 
2697*11304SJanie.Lu@Sun.COM 			if (rs != NPI_SUCCESS)
2698*11304SJanie.Lu@Sun.COM 				goto fail;
2699*11304SJanie.Lu@Sun.COM 
2700*11304SJanie.Lu@Sun.COM 			rs = npi_fflp_cfg_ip_usr_cls_enable(handle,
2701*11304SJanie.Lu@Sun.COM 			    (tcam_class_t)class);
2702*11304SJanie.Lu@Sun.COM 			if (rs != NPI_SUCCESS)
2703*11304SJanie.Lu@Sun.COM 				goto fail;
2704*11304SJanie.Lu@Sun.COM 
2705*11304SJanie.Lu@Sun.COM 			hw_p->tcam_l3_prog_cls[i].cls = class;
2706*11304SJanie.Lu@Sun.COM 			hw_p->tcam_l3_prog_cls[i].pid = pid;
2707*11304SJanie.Lu@Sun.COM 			hw_p->tcam_l3_prog_cls[i].flow_pkt_type =
2708*11304SJanie.Lu@Sun.COM 			    iptunp->in_pkt_type;
2709*11304SJanie.Lu@Sun.COM 			hw_p->tcam_l3_prog_cls[i].valid = 1;
2710*11304SJanie.Lu@Sun.COM 			*cls_idp = (uint8_t)class;
2711*11304SJanie.Lu@Sun.COM 			add_cls = 1;
2712*11304SJanie.Lu@Sun.COM 			break;
2713*11304SJanie.Lu@Sun.COM 		} else if (hw_p->tcam_l3_prog_cls[i].pid == pid) {
2714*11304SJanie.Lu@Sun.COM 			if (hw_p->tcam_l3_prog_cls[i].flow_pkt_type == 0) {
2715*11304SJanie.Lu@Sun.COM 				/* there is no flow key */
2716*11304SJanie.Lu@Sun.COM 				/* todo program the existing usr class reg */
2717*11304SJanie.Lu@Sun.COM 
2718*11304SJanie.Lu@Sun.COM 				rs = nxge_set_iptun_usr_cls_reg(nxgep, class,
2719*11304SJanie.Lu@Sun.COM 				    iptunp);
2720*11304SJanie.Lu@Sun.COM 				if (rs != NPI_SUCCESS)
2721*11304SJanie.Lu@Sun.COM 					goto fail;
2722*11304SJanie.Lu@Sun.COM 
2723*11304SJanie.Lu@Sun.COM 				rs = npi_fflp_cfg_ip_usr_cls_enable(handle,
2724*11304SJanie.Lu@Sun.COM 				    (tcam_class_t)class);
2725*11304SJanie.Lu@Sun.COM 				if (rs != NPI_SUCCESS)
2726*11304SJanie.Lu@Sun.COM 					goto fail;
2727*11304SJanie.Lu@Sun.COM 
2728*11304SJanie.Lu@Sun.COM 				hw_p->tcam_l3_prog_cls[i].flow_pkt_type =
2729*11304SJanie.Lu@Sun.COM 				    iptunp->in_pkt_type;
2730*11304SJanie.Lu@Sun.COM 				*cls_idp = (uint8_t)class;
2731*11304SJanie.Lu@Sun.COM 				add_cls = 1;
2732*11304SJanie.Lu@Sun.COM 			} else {
2733*11304SJanie.Lu@Sun.COM 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2734*11304SJanie.Lu@Sun.COM 				    "nxge_add_iptun_class: L3 usr "
2735*11304SJanie.Lu@Sun.COM 				    "programmable class with pid %d "
2736*11304SJanie.Lu@Sun.COM 				    "already exists", pid));
2737*11304SJanie.Lu@Sun.COM 			}
2738*11304SJanie.Lu@Sun.COM 			break;
2739*11304SJanie.Lu@Sun.COM 		}
2740*11304SJanie.Lu@Sun.COM 	}
2741*11304SJanie.Lu@Sun.COM 	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
2742*11304SJanie.Lu@Sun.COM 
2743*11304SJanie.Lu@Sun.COM 	if (add_cls != 1) {
2744*11304SJanie.Lu@Sun.COM 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2745*11304SJanie.Lu@Sun.COM 		    "nxge_add_iptun_class: Could not add IP tunneling class"));
2746*11304SJanie.Lu@Sun.COM 	}
2747*11304SJanie.Lu@Sun.COM 	return;
2748*11304SJanie.Lu@Sun.COM fail:
2749*11304SJanie.Lu@Sun.COM 	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
2750*11304SJanie.Lu@Sun.COM 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_iptun_class: FAILED"));
2751*11304SJanie.Lu@Sun.COM }
2752*11304SJanie.Lu@Sun.COM 
2753*11304SJanie.Lu@Sun.COM static boolean_t
2754*11304SJanie.Lu@Sun.COM nxge_is_iptun_cls_present(p_nxge_t nxgep, uint8_t cls_id, int *idx)
2755*11304SJanie.Lu@Sun.COM {
2756*11304SJanie.Lu@Sun.COM 	int i;
2757*11304SJanie.Lu@Sun.COM 	p_nxge_hw_list_t hw_p = nxgep->nxge_hw_p;
2758*11304SJanie.Lu@Sun.COM 
2759*11304SJanie.Lu@Sun.COM 	MUTEX_ENTER(&hw_p->nxge_tcam_lock);
2760*11304SJanie.Lu@Sun.COM 	for (i = 0; i < NXGE_L3_PROG_CLS; i++) {
2761*11304SJanie.Lu@Sun.COM 		if (hw_p->tcam_l3_prog_cls[i].valid &&
2762*11304SJanie.Lu@Sun.COM 		    hw_p->tcam_l3_prog_cls[i].flow_pkt_type != 0) {
2763*11304SJanie.Lu@Sun.COM 			if (hw_p->tcam_l3_prog_cls[i].cls == cls_id)
2764*11304SJanie.Lu@Sun.COM 				break;
2765*11304SJanie.Lu@Sun.COM 		}
2766*11304SJanie.Lu@Sun.COM 	}
2767*11304SJanie.Lu@Sun.COM 	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
2768*11304SJanie.Lu@Sun.COM 
2769*11304SJanie.Lu@Sun.COM 	if (i == NXGE_L3_PROG_CLS) {
2770*11304SJanie.Lu@Sun.COM 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2771*11304SJanie.Lu@Sun.COM 		    "nxge_is_iptun_cls_present: Invalid class %d", cls_id));
2772*11304SJanie.Lu@Sun.COM 		return (B_FALSE);
2773*11304SJanie.Lu@Sun.COM 	} else {
2774*11304SJanie.Lu@Sun.COM 		*idx = i;
2775*11304SJanie.Lu@Sun.COM 		return (B_TRUE);
2776*11304SJanie.Lu@Sun.COM 	}
2777*11304SJanie.Lu@Sun.COM }
2778*11304SJanie.Lu@Sun.COM 
2779*11304SJanie.Lu@Sun.COM void
2780*11304SJanie.Lu@Sun.COM nxge_cfg_iptun_hash(p_nxge_t nxgep, iptun_cfg_t *iptunp, uint8_t cls_id)
2781*11304SJanie.Lu@Sun.COM {
2782*11304SJanie.Lu@Sun.COM 	int idx;
2783*11304SJanie.Lu@Sun.COM 	npi_handle_t handle = nxgep->npi_reg_handle;
2784*11304SJanie.Lu@Sun.COM 	flow_key_cfg_t cfg;
2785*11304SJanie.Lu@Sun.COM 
2786*11304SJanie.Lu@Sun.COM 	/* check to see that this is a valid class ID */
2787*11304SJanie.Lu@Sun.COM 	if (!nxge_is_iptun_cls_present(nxgep, cls_id, &idx)) {
2788*11304SJanie.Lu@Sun.COM 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2789*11304SJanie.Lu@Sun.COM 		    "nxge_cfg_iptun_hash: nxge_is_iptun_cls_present "
2790*11304SJanie.Lu@Sun.COM 		    "failed for cls_id %d", cls_id));
2791*11304SJanie.Lu@Sun.COM 		return;
2792*11304SJanie.Lu@Sun.COM 	}
2793*11304SJanie.Lu@Sun.COM 
2794*11304SJanie.Lu@Sun.COM 	bzero((void *)&cfg, sizeof (flow_key_cfg_t));
2795*11304SJanie.Lu@Sun.COM 
2796*11304SJanie.Lu@Sun.COM 	/*
2797*11304SJanie.Lu@Sun.COM 	 * This ensures that all 4 bytes of the XOR value are loaded to the
2798*11304SJanie.Lu@Sun.COM 	 * hash key.
2799*11304SJanie.Lu@Sun.COM 	 */
2800*11304SJanie.Lu@Sun.COM 	cfg.use_dport = cfg.use_sport = cfg.ip_opts_exist = 1;
2801*11304SJanie.Lu@Sun.COM 
2802*11304SJanie.Lu@Sun.COM 	cfg.l4_xor_sel = (iptunp->l4xor_sel & FL_KEY_USR_L4XOR_MSK);
2803*11304SJanie.Lu@Sun.COM 	cfg.use_l4_md = 1;
2804*11304SJanie.Lu@Sun.COM 
2805*11304SJanie.Lu@Sun.COM 	if (iptunp->hash_flags & HASH_L3PROTO)
2806*11304SJanie.Lu@Sun.COM 		cfg.use_proto = 1;
2807*11304SJanie.Lu@Sun.COM 	else if (iptunp->hash_flags & HASH_IPDA)
2808*11304SJanie.Lu@Sun.COM 		cfg.use_daddr = 1;
2809*11304SJanie.Lu@Sun.COM 	else if (iptunp->hash_flags & HASH_IPSA)
2810*11304SJanie.Lu@Sun.COM 		cfg.use_saddr = 1;
2811*11304SJanie.Lu@Sun.COM 	else if (iptunp->hash_flags & HASH_VLAN)
2812*11304SJanie.Lu@Sun.COM 		cfg.use_vlan = 1;
2813*11304SJanie.Lu@Sun.COM 	else if (iptunp->hash_flags & HASH_L2DA)
2814*11304SJanie.Lu@Sun.COM 		cfg.use_l2da = 1;
2815*11304SJanie.Lu@Sun.COM 	else if (iptunp->hash_flags & HASH_IFPORT)
2816*11304SJanie.Lu@Sun.COM 		cfg.use_portnum = 1;
2817*11304SJanie.Lu@Sun.COM 
2818*11304SJanie.Lu@Sun.COM 	(void) npi_fflp_cfg_ip_cls_flow_key_rfnl(handle, (tcam_class_t)cls_id,
2819*11304SJanie.Lu@Sun.COM 	    &cfg);
2820*11304SJanie.Lu@Sun.COM }
2821*11304SJanie.Lu@Sun.COM 
2822*11304SJanie.Lu@Sun.COM void
2823*11304SJanie.Lu@Sun.COM nxge_del_iptun_class(p_nxge_t nxgep, uint8_t cls_id)
2824*11304SJanie.Lu@Sun.COM {
2825*11304SJanie.Lu@Sun.COM 	int i;
2826*11304SJanie.Lu@Sun.COM 	npi_handle_t handle = nxgep->npi_reg_handle;
2827*11304SJanie.Lu@Sun.COM 	npi_status_t rs = NPI_SUCCESS;
2828*11304SJanie.Lu@Sun.COM 
2829*11304SJanie.Lu@Sun.COM 
2830*11304SJanie.Lu@Sun.COM 	/* check to see that this is a valid class ID */
2831*11304SJanie.Lu@Sun.COM 	if (!nxge_is_iptun_cls_present(nxgep, cls_id, &i)) {
2832*11304SJanie.Lu@Sun.COM 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2833*11304SJanie.Lu@Sun.COM 		    "nxge_del_iptun_class: Invalid class ID 0x%x", cls_id));
2834*11304SJanie.Lu@Sun.COM 		return;
2835*11304SJanie.Lu@Sun.COM 	}
2836*11304SJanie.Lu@Sun.COM 
2837*11304SJanie.Lu@Sun.COM 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_tcam_lock);
2838*11304SJanie.Lu@Sun.COM 	rs = npi_fflp_cfg_ip_usr_cls_disable(handle, (tcam_class_t)cls_id);
2839*11304SJanie.Lu@Sun.COM 	if (rs != NPI_SUCCESS)
2840*11304SJanie.Lu@Sun.COM 		goto fail;
2841*11304SJanie.Lu@Sun.COM 	nxgep->nxge_hw_p->tcam_l3_prog_cls[i].flow_pkt_type = 0;
2842*11304SJanie.Lu@Sun.COM 	if (nxgep->nxge_hw_p->tcam_l3_prog_cls[i].tcam_ref_cnt == 0)
2843*11304SJanie.Lu@Sun.COM 		nxgep->nxge_hw_p->tcam_l3_prog_cls[i].valid = 0;
2844*11304SJanie.Lu@Sun.COM 
2845*11304SJanie.Lu@Sun.COM 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_tcam_lock);
2846*11304SJanie.Lu@Sun.COM 	return;
2847*11304SJanie.Lu@Sun.COM fail:
2848*11304SJanie.Lu@Sun.COM 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_tcam_lock);
2849*11304SJanie.Lu@Sun.COM 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_iptun_class: FAILED"));
2850*11304SJanie.Lu@Sun.COM }
2851*11304SJanie.Lu@Sun.COM 
2852*11304SJanie.Lu@Sun.COM void
2853*11304SJanie.Lu@Sun.COM nxge_get_iptun_class(p_nxge_t nxgep, iptun_cfg_t *iptunp, uint8_t cls_id)
2854*11304SJanie.Lu@Sun.COM {
2855*11304SJanie.Lu@Sun.COM 	int i;
2856*11304SJanie.Lu@Sun.COM 	uint8_t pid;
2857*11304SJanie.Lu@Sun.COM 	npi_handle_t handle = nxgep->npi_reg_handle;
2858*11304SJanie.Lu@Sun.COM 	npi_status_t rs = NPI_SUCCESS;
2859*11304SJanie.Lu@Sun.COM 	flow_key_cfg_t cfg;
2860*11304SJanie.Lu@Sun.COM 
2861*11304SJanie.Lu@Sun.COM 
2862*11304SJanie.Lu@Sun.COM 	/* check to see that this is a valid class ID */
2863*11304SJanie.Lu@Sun.COM 	if (!nxge_is_iptun_cls_present(nxgep, cls_id, &i))
2864*11304SJanie.Lu@Sun.COM 		return;
2865*11304SJanie.Lu@Sun.COM 
2866*11304SJanie.Lu@Sun.COM 	bzero((void *)iptunp, sizeof (iptun_cfg_t));
2867*11304SJanie.Lu@Sun.COM 
2868*11304SJanie.Lu@Sun.COM 	pid = nxgep->nxge_hw_p->tcam_l3_prog_cls[i].pid;
2869*11304SJanie.Lu@Sun.COM 
2870*11304SJanie.Lu@Sun.COM 	rs = npi_fflp_cfg_ip_usr_cls_get_iptun(handle, (tcam_class_t)cls_id,
2871*11304SJanie.Lu@Sun.COM 	    &iptunp->l4b0_val, &iptunp->l4b0_mask, &iptunp->l4b23_val,
2872*11304SJanie.Lu@Sun.COM 	    &iptunp->l4b23_sel);
2873*11304SJanie.Lu@Sun.COM 	if (rs != NPI_SUCCESS)
2874*11304SJanie.Lu@Sun.COM 		goto fail;
2875*11304SJanie.Lu@Sun.COM 
2876*11304SJanie.Lu@Sun.COM 	rs = npi_fflp_cfg_ip_cls_flow_key_get_rfnl(handle,
2877*11304SJanie.Lu@Sun.COM 	    (tcam_class_t)cls_id, &cfg);
2878*11304SJanie.Lu@Sun.COM 	if (rs != NPI_SUCCESS)
2879*11304SJanie.Lu@Sun.COM 		goto fail;
2880*11304SJanie.Lu@Sun.COM 
2881*11304SJanie.Lu@Sun.COM 	iptunp->l4xor_sel = cfg.l4_xor_sel;
2882*11304SJanie.Lu@Sun.COM 	if (cfg.use_proto)
2883*11304SJanie.Lu@Sun.COM 		iptunp->hash_flags |= HASH_L3PROTO;
2884*11304SJanie.Lu@Sun.COM 	else if (cfg.use_daddr)
2885*11304SJanie.Lu@Sun.COM 		iptunp->hash_flags |= HASH_IPDA;
2886*11304SJanie.Lu@Sun.COM 	else if (cfg.use_saddr)
2887*11304SJanie.Lu@Sun.COM 		iptunp->hash_flags |= HASH_IPSA;
2888*11304SJanie.Lu@Sun.COM 	else if (cfg.use_vlan)
2889*11304SJanie.Lu@Sun.COM 		iptunp->hash_flags |= HASH_VLAN;
2890*11304SJanie.Lu@Sun.COM 	else if (cfg.use_l2da)
2891*11304SJanie.Lu@Sun.COM 		iptunp->hash_flags |= HASH_L2DA;
2892*11304SJanie.Lu@Sun.COM 	else if (cfg.use_portnum)
2893*11304SJanie.Lu@Sun.COM 		iptunp->hash_flags |= HASH_IFPORT;
2894*11304SJanie.Lu@Sun.COM 
2895*11304SJanie.Lu@Sun.COM 	switch (pid) {
2896*11304SJanie.Lu@Sun.COM 	case 4:
2897*11304SJanie.Lu@Sun.COM 		iptunp->in_pkt_type = IPTUN_PKT_IPV4;
2898*11304SJanie.Lu@Sun.COM 		break;
2899*11304SJanie.Lu@Sun.COM 	case 41:
2900*11304SJanie.Lu@Sun.COM 		iptunp->in_pkt_type = IPTUN_PKT_IPV6;
2901*11304SJanie.Lu@Sun.COM 		break;
2902*11304SJanie.Lu@Sun.COM 	case 47:
2903*11304SJanie.Lu@Sun.COM 		iptunp->in_pkt_type = IPTUN_PKT_GRE;
2904*11304SJanie.Lu@Sun.COM 		break;
2905*11304SJanie.Lu@Sun.COM 	case 17:
2906*11304SJanie.Lu@Sun.COM 		iptunp->in_pkt_type = IPTUN_PKT_GTP;
2907*11304SJanie.Lu@Sun.COM 		break;
2908*11304SJanie.Lu@Sun.COM 	default:
2909*11304SJanie.Lu@Sun.COM 		iptunp->in_pkt_type = 0;
2910*11304SJanie.Lu@Sun.COM 		break;
2911*11304SJanie.Lu@Sun.COM 	}
2912*11304SJanie.Lu@Sun.COM 
2913*11304SJanie.Lu@Sun.COM 	return;
2914*11304SJanie.Lu@Sun.COM fail:
2915*11304SJanie.Lu@Sun.COM 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_get_iptun_class: FAILED"));
2916*11304SJanie.Lu@Sun.COM }
2917*11304SJanie.Lu@Sun.COM 
2918*11304SJanie.Lu@Sun.COM void
2919*11304SJanie.Lu@Sun.COM nxge_set_ip_cls_sym(p_nxge_t nxgep, uint8_t cls_id, uint8_t sym)
2920*11304SJanie.Lu@Sun.COM {
2921*11304SJanie.Lu@Sun.COM 	npi_handle_t handle = nxgep->npi_reg_handle;
2922*11304SJanie.Lu@Sun.COM 	npi_status_t rs = NPI_SUCCESS;
2923*11304SJanie.Lu@Sun.COM 	boolean_t sym_en = (sym == 1) ? B_TRUE : B_FALSE;
2924*11304SJanie.Lu@Sun.COM 
2925*11304SJanie.Lu@Sun.COM 	rs = npi_fflp_cfg_sym_ip_cls_flow_key(handle, (tcam_class_t)cls_id,
2926*11304SJanie.Lu@Sun.COM 	    sym_en);
2927*11304SJanie.Lu@Sun.COM 	if (rs != NPI_SUCCESS)
2928*11304SJanie.Lu@Sun.COM 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2929*11304SJanie.Lu@Sun.COM 		    "nxge_set_ip_cls_sym: FAILED"));
2930*11304SJanie.Lu@Sun.COM }
2931*11304SJanie.Lu@Sun.COM 
2932*11304SJanie.Lu@Sun.COM void
2933*11304SJanie.Lu@Sun.COM nxge_get_ip_cls_sym(p_nxge_t nxgep, uint8_t cls_id, uint8_t *sym)
2934*11304SJanie.Lu@Sun.COM {
2935*11304SJanie.Lu@Sun.COM 	npi_handle_t handle = nxgep->npi_reg_handle;
2936*11304SJanie.Lu@Sun.COM 	npi_status_t rs = NPI_SUCCESS;
2937*11304SJanie.Lu@Sun.COM 	flow_key_cfg_t cfg;
2938*11304SJanie.Lu@Sun.COM 
2939*11304SJanie.Lu@Sun.COM 	rs = npi_fflp_cfg_ip_cls_flow_key_get_rfnl(handle,
2940*11304SJanie.Lu@Sun.COM 	    (tcam_class_t)cls_id, &cfg);
2941*11304SJanie.Lu@Sun.COM 	if (rs != NPI_SUCCESS)
2942*11304SJanie.Lu@Sun.COM 		goto fail;
2943*11304SJanie.Lu@Sun.COM 
2944*11304SJanie.Lu@Sun.COM 	if (cfg.use_sym)
2945*11304SJanie.Lu@Sun.COM 		*sym = 1;
2946*11304SJanie.Lu@Sun.COM 	else
2947*11304SJanie.Lu@Sun.COM 		*sym = 0;
2948*11304SJanie.Lu@Sun.COM 	return;
2949*11304SJanie.Lu@Sun.COM fail:
2950*11304SJanie.Lu@Sun.COM 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_get_ip_cls_sym: FAILED"));
2951*11304SJanie.Lu@Sun.COM }
2952