1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#include <npi_fflp.h>
28#include <npi_mac.h>
29#include <nxge_defs.h>
30#include <nxge_flow.h>
31#include <nxge_fflp.h>
32#include <nxge_impl.h>
33#include <nxge_fflp_hash.h>
34#include <nxge_common.h>
35
36
37/*
38 * Function prototypes
39 */
40static nxge_status_t nxge_fflp_vlan_tbl_clear_all(p_nxge_t);
41static nxge_status_t nxge_fflp_tcam_invalidate_all(p_nxge_t);
42static nxge_status_t nxge_fflp_tcam_init(p_nxge_t);
43static nxge_status_t nxge_fflp_fcram_invalidate_all(p_nxge_t);
44static nxge_status_t nxge_fflp_fcram_init(p_nxge_t);
45static int nxge_flow_need_hash_lookup(p_nxge_t, flow_resource_t *);
46static void nxge_fill_tcam_entry_tcp(p_nxge_t, flow_spec_t *, tcam_entry_t *);
47static void nxge_fill_tcam_entry_udp(p_nxge_t, flow_spec_t *, tcam_entry_t *);
48static void nxge_fill_tcam_entry_sctp(p_nxge_t, flow_spec_t *, tcam_entry_t *);
49static void nxge_fill_tcam_entry_tcp_ipv6(p_nxge_t, flow_spec_t *,
50	tcam_entry_t *);
51static void nxge_fill_tcam_entry_udp_ipv6(p_nxge_t, flow_spec_t *,
52	tcam_entry_t *);
53static void nxge_fill_tcam_entry_sctp_ipv6(p_nxge_t, flow_spec_t *,
54	tcam_entry_t *);
55static uint8_t nxge_get_rdc_offset(p_nxge_t, uint8_t, uint64_t);
56static uint8_t nxge_get_rdc_group(p_nxge_t, uint8_t, uint64_t);
57static uint16_t nxge_tcam_get_index(p_nxge_t, uint16_t);
58static uint32_t nxge_tcam_cls_to_flow(uint32_t);
59static uint8_t nxge_iptun_pkt_type_to_pid(uint8_t);
60static npi_status_t nxge_set_iptun_usr_cls_reg(p_nxge_t, uint64_t,
61					iptun_cfg_t *);
62static boolean_t nxge_is_iptun_cls_present(p_nxge_t, uint8_t, int *);
63
64/*
65 * functions used outside this file
66 */
67nxge_status_t nxge_fflp_config_vlan_table(p_nxge_t, uint16_t);
68nxge_status_t nxge_fflp_ip_class_config_all(p_nxge_t);
69nxge_status_t nxge_add_flow(p_nxge_t, flow_resource_t *);
70static nxge_status_t nxge_tcam_handle_ip_fragment(p_nxge_t);
71nxge_status_t nxge_add_tcam_entry(p_nxge_t, flow_resource_t *);
72nxge_status_t nxge_add_fcram_entry(p_nxge_t, flow_resource_t *);
73nxge_status_t nxge_flow_get_hash(p_nxge_t, flow_resource_t *,
74	uint32_t *, uint16_t *);
75int nxge_get_valid_tcam_cnt(p_nxge_t);
76void nxge_get_tcam_entry_all(p_nxge_t, rx_class_cfg_t *);
77void nxge_get_tcam_entry(p_nxge_t, flow_resource_t *);
78void nxge_del_tcam_entry(p_nxge_t, uint32_t);
79void nxge_add_iptun_class(p_nxge_t, iptun_cfg_t *, uint8_t *);
80void nxge_cfg_iptun_hash(p_nxge_t, iptun_cfg_t *, uint8_t);
81void nxge_del_iptun_class(p_nxge_t, uint8_t);
82void nxge_get_iptun_class(p_nxge_t, iptun_cfg_t *, uint8_t);
83void nxge_set_ip_cls_sym(p_nxge_t, uint8_t, uint8_t);
84void nxge_get_ip_cls_sym(p_nxge_t, uint8_t, uint8_t *);
85
86
87nxge_status_t
88nxge_tcam_dump_entry(p_nxge_t nxgep, uint32_t location)
89{
90	tcam_entry_t tcam_rdptr;
91	uint64_t asc_ram = 0;
92	npi_handle_t handle;
93	npi_status_t status;
94
95	handle = nxgep->npi_reg_handle;
96
97	bzero((char *)&tcam_rdptr, sizeof (struct tcam_entry));
98	status = npi_fflp_tcam_entry_read(handle, (tcam_location_t)location,
99	    (struct tcam_entry *)&tcam_rdptr);
100	if (status & NPI_FAILURE) {
101		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
102		    " nxge_tcam_dump_entry:"
103		    "  tcam read failed at location %d ", location));
104		return (NXGE_ERROR);
105	}
106	status = npi_fflp_tcam_asc_ram_entry_read(handle,
107	    (tcam_location_t)location, &asc_ram);
108
109	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "location %x\n"
110	    " key:  %llx %llx %llx %llx \n"
111	    " mask: %llx %llx %llx %llx \n"
112	    " ASC RAM %llx \n", location,
113	    tcam_rdptr.key0, tcam_rdptr.key1,
114	    tcam_rdptr.key2, tcam_rdptr.key3,
115	    tcam_rdptr.mask0, tcam_rdptr.mask1,
116	    tcam_rdptr.mask2, tcam_rdptr.mask3, asc_ram));
117	return (NXGE_OK);
118}
119
120void
121nxge_get_tcam(p_nxge_t nxgep, p_mblk_t mp)
122{
123	uint32_t tcam_loc;
124	int *lptr;
125	int location;
126
127	uint32_t start_location = 0;
128	uint32_t stop_location = nxgep->classifier.tcam_size;
129	lptr = (int *)mp->b_rptr;
130	location = *lptr;
131
132	if ((location >= nxgep->classifier.tcam_size) || (location < -1)) {
133		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
134		    "nxge_tcam_dump: Invalid location %d \n", location));
135		return;
136	}
137	if (location == -1) {
138		start_location = 0;
139		stop_location = nxgep->classifier.tcam_size;
140	} else {
141		start_location = location;
142		stop_location = location + 1;
143	}
144	for (tcam_loc = start_location; tcam_loc < stop_location; tcam_loc++)
145		(void) nxge_tcam_dump_entry(nxgep, tcam_loc);
146}
147
148/*
149 * nxge_fflp_vlan_table_invalidate_all
150 * invalidates the vlan RDC table entries.
151 * INPUT
152 * nxge    soft state data structure
153 * Return
154 *      NXGE_OK
155 *      NXGE_ERROR
156 *
157 */
158
159static nxge_status_t
160nxge_fflp_vlan_tbl_clear_all(p_nxge_t nxgep)
161{
162	vlan_id_t vlan_id;
163	npi_handle_t handle;
164	npi_status_t rs = NPI_SUCCESS;
165	vlan_id_t start = 0, stop = NXGE_MAX_VLANS;
166
167	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_vlan_tbl_clear_all "));
168	handle = nxgep->npi_reg_handle;
169	for (vlan_id = start; vlan_id < stop; vlan_id++) {
170		rs = npi_fflp_cfg_vlan_table_clear(handle, vlan_id);
171		if (rs != NPI_SUCCESS) {
172			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
173			    "VLAN Table invalidate failed for vlan id %d ",
174			    vlan_id));
175			return (NXGE_ERROR | rs);
176		}
177	}
178	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_vlan_tbl_clear_all "));
179	return (NXGE_OK);
180}
181
182/*
183 * The following functions are used by other modules to init
184 * the fflp module.
185 * these functions are the basic API used to init
186 * the fflp modules (tcam, fcram etc ......)
187 *
188 * The TCAM search future would be disabled  by default.
189 */
190
191static nxge_status_t
192nxge_fflp_tcam_init(p_nxge_t nxgep)
193{
194	uint8_t access_ratio;
195	tcam_class_t class;
196	npi_status_t rs = NPI_SUCCESS;
197	npi_handle_t handle;
198
199	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_tcam_init"));
200	handle = nxgep->npi_reg_handle;
201
202	rs = npi_fflp_cfg_tcam_disable(handle);
203	if (rs != NPI_SUCCESS) {
204		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "failed TCAM Disable\n"));
205		return (NXGE_ERROR | rs);
206	}
207
208	access_ratio = nxgep->param_arr[param_tcam_access_ratio].value;
209	rs = npi_fflp_cfg_tcam_access(handle, access_ratio);
210	if (rs != NPI_SUCCESS) {
211		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
212		    "failed TCAM Access cfg\n"));
213		return (NXGE_ERROR | rs);
214	}
215
216	/* disable configurable classes */
217	/* disable the configurable ethernet classes; */
218	for (class = TCAM_CLASS_ETYPE_1;
219	    class <= TCAM_CLASS_ETYPE_2; class++) {
220		rs = npi_fflp_cfg_enet_usr_cls_disable(handle, class);
221		if (rs != NPI_SUCCESS) {
222			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
223			    "TCAM USR Ether Class config failed."));
224			return (NXGE_ERROR | rs);
225		}
226	}
227
228	/* disable the configurable ip classes; */
229	for (class = TCAM_CLASS_IP_USER_4;
230	    class <= TCAM_CLASS_IP_USER_7; class++) {
231		rs = npi_fflp_cfg_ip_usr_cls_disable(handle, class);
232		if (rs != NPI_SUCCESS) {
233			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
234			    "TCAM USR IP Class cnfg failed."));
235			return (NXGE_ERROR | rs);
236		}
237	}
238	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_tcam_init"));
239	return (NXGE_OK);
240}
241
242/*
243 * nxge_fflp_tcam_invalidate_all
244 * invalidates all the tcam entries.
245 * INPUT
246 * nxge    soft state data structure
247 * Return
248 *      NXGE_OK
249 *      NXGE_ERROR
250 *
251 */
252
253
254static nxge_status_t
255nxge_fflp_tcam_invalidate_all(p_nxge_t nxgep)
256{
257	uint16_t location;
258	npi_status_t rs = NPI_SUCCESS;
259	npi_handle_t handle;
260	uint16_t start = 0, stop = nxgep->classifier.tcam_size;
261	p_nxge_hw_list_t hw_p;
262
263	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
264	    "==> nxge_fflp_tcam_invalidate_all"));
265	handle = nxgep->npi_reg_handle;
266	if ((hw_p = nxgep->nxge_hw_p) == NULL) {
267		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
268		    " nxge_fflp_tcam_invalidate_all:"
269		    " common hardware not set", nxgep->niu_type));
270		return (NXGE_ERROR);
271	}
272	MUTEX_ENTER(&hw_p->nxge_tcam_lock);
273	for (location = start; location < stop; location++) {
274		rs = npi_fflp_tcam_entry_invalidate(handle, location);
275		if (rs != NPI_SUCCESS) {
276			MUTEX_EXIT(&hw_p->nxge_tcam_lock);
277			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
278			    "TCAM invalidate failed at loc %d ", location));
279			return (NXGE_ERROR | rs);
280		}
281	}
282	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
283	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
284	    "<== nxge_fflp_tcam_invalidate_all"));
285	return (NXGE_OK);
286}
287
288/*
289 * nxge_fflp_fcram_entry_invalidate_all
290 * invalidates all the FCRAM entries.
291 * INPUT
292 * nxge    soft state data structure
293 * Return
294 *      NXGE_OK
295 *      NXGE_ERROR
296 *
297 */
298
299static nxge_status_t
300nxge_fflp_fcram_invalidate_all(p_nxge_t nxgep)
301{
302	npi_handle_t handle;
303	npi_status_t rs = NPI_SUCCESS;
304	part_id_t pid = 0;
305	uint8_t base_mask, base_reloc;
306	fcram_entry_t fc;
307	uint32_t location;
308	uint32_t increment, last_location;
309
310	/*
311	 * (1) configure and enable partition 0 with no relocation
312	 * (2) Assume the FCRAM is used as IPv4 exact match entry cells
313	 * (3) Invalidate these cells by clearing the valid bit in
314	 * the subareas 0 and 4
315	 * (4) disable the partition
316	 *
317	 */
318
319	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_fcram_invalidate_all"));
320
321	base_mask = base_reloc = 0x0;
322	handle = nxgep->npi_reg_handle;
323	rs = npi_fflp_cfg_fcram_partition(handle, pid, base_mask, base_reloc);
324
325	if (rs != NPI_SUCCESS) {
326		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "failed partition cfg\n"));
327		return (NXGE_ERROR | rs);
328	}
329	rs = npi_fflp_cfg_fcram_partition_disable(handle, pid);
330
331	if (rs != NPI_SUCCESS) {
332		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
333		    "failed partition enable\n"));
334		return (NXGE_ERROR | rs);
335	}
336	fc.dreg[0].value = 0;
337	fc.hash_hdr_valid = 0;
338	fc.hash_hdr_ext = 1;	/* specify as IPV4 exact match entry */
339	increment = sizeof (hash_ipv4_t);
340	last_location = FCRAM_SIZE * 0x40;
341
342	for (location = 0; location < last_location; location += increment) {
343		rs = npi_fflp_fcram_subarea_write(handle, pid,
344		    location, fc.value[0]);
345		if (rs != NPI_SUCCESS) {
346			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
347			    "failed write at location %x ", location));
348			return (NXGE_ERROR | rs);
349		}
350	}
351	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_fcram_invalidate_all"));
352	return (NXGE_OK);
353}
354
355static nxge_status_t
356nxge_fflp_fcram_init(p_nxge_t nxgep)
357{
358	fflp_fcram_output_drive_t strength;
359	fflp_fcram_qs_t qs;
360	npi_status_t rs = NPI_SUCCESS;
361	uint8_t access_ratio;
362	int partition;
363	npi_handle_t handle;
364	uint32_t min_time, max_time, sys_time;
365
366	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_fcram_init"));
367
368	/*
369	 * Recommended values are needed.
370	 */
371	min_time = FCRAM_REFRESH_DEFAULT_MIN_TIME;
372	max_time = FCRAM_REFRESH_DEFAULT_MAX_TIME;
373	sys_time = FCRAM_REFRESH_DEFAULT_SYS_TIME;
374
375	handle = nxgep->npi_reg_handle;
376	strength = FCRAM_OUTDR_NORMAL;
377	qs = FCRAM_QS_MODE_QS;
378	rs = npi_fflp_cfg_fcram_reset(handle, strength, qs);
379	if (rs != NPI_SUCCESS) {
380		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "failed FCRAM Reset. "));
381		return (NXGE_ERROR | rs);
382	}
383
384	access_ratio = nxgep->param_arr[param_fcram_access_ratio].value;
385	rs = npi_fflp_cfg_fcram_access(handle, access_ratio);
386	if (rs != NPI_SUCCESS) {
387		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "failed FCRAM Access ratio"
388		    "configuration \n"));
389		return (NXGE_ERROR | rs);
390	}
391	rs = npi_fflp_cfg_fcram_refresh_time(handle, min_time,
392	    max_time, sys_time);
393	if (rs != NPI_SUCCESS) {
394		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
395		    "failed FCRAM refresh cfg"));
396		return (NXGE_ERROR);
397	}
398
399	/* disable all the partitions until explicitly enabled */
400	for (partition = 0; partition < FFLP_FCRAM_MAX_PARTITION; partition++) {
401		rs = npi_fflp_cfg_fcram_partition_disable(handle, partition);
402		if (rs != NPI_SUCCESS) {
403			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
404			    "failed FCRAM partition"
405			    " enable for partition %d ", partition));
406			return (NXGE_ERROR | rs);
407		}
408	}
409
410	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_fcram_init"));
411	return (NXGE_OK);
412}
413
414nxge_status_t
415nxge_logical_mac_assign_rdc_table(p_nxge_t nxgep, uint8_t alt_mac)
416{
417	npi_status_t rs = NPI_SUCCESS;
418	hostinfo_t mac_rdc;
419	npi_handle_t handle;
420	p_nxge_class_pt_cfg_t p_class_cfgp;
421
422	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
423	if (p_class_cfgp->mac_host_info[alt_mac].flag == 0) {
424		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
425		    " nxge_logical_mac_assign_rdc_table"
426		    " unconfigured alt MAC addr %d ", alt_mac));
427		return (NXGE_ERROR);
428	}
429	handle = nxgep->npi_reg_handle;
430	mac_rdc.value = 0;
431	mac_rdc.bits.w0.rdc_tbl_num =
432	    p_class_cfgp->mac_host_info[alt_mac].rdctbl;
433	mac_rdc.bits.w0.mac_pref = p_class_cfgp->mac_host_info[alt_mac].mpr_npr;
434
435	rs = npi_mac_hostinfo_entry(handle, OP_SET,
436	    nxgep->function_num, alt_mac, &mac_rdc);
437
438	if (rs != NPI_SUCCESS) {
439		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
440		    "failed Assign RDC table"));
441		return (NXGE_ERROR | rs);
442	}
443	return (NXGE_OK);
444}
445
446nxge_status_t
447nxge_main_mac_assign_rdc_table(p_nxge_t nxgep)
448{
449	npi_status_t rs = NPI_SUCCESS;
450	hostinfo_t mac_rdc;
451	npi_handle_t handle;
452	int i;
453
454	handle = nxgep->npi_reg_handle;
455	mac_rdc.value = 0;
456	mac_rdc.bits.w0.rdc_tbl_num = nxgep->class_config.mac_rdcgrp;
457	mac_rdc.bits.w0.mac_pref = 1;
458	switch (nxgep->function_num) {
459	case 0:
460	case 1:
461		/*
462		 * Tests indicate that it is OK not to re-initialize the
463		 * hostinfo registers for the XMAC's alternate MAC
464		 * addresses. But that is necessary for BMAC (case 2
465		 * and case 3 below)
466		 */
467		rs = npi_mac_hostinfo_entry(handle, OP_SET,
468		    nxgep->function_num, XMAC_UNIQUE_HOST_INFO_ENTRY, &mac_rdc);
469		break;
470	case 2:
471	case 3:
472		rs = npi_mac_hostinfo_entry(handle, OP_SET,
473		    nxgep->function_num, BMAC_UNIQUE_HOST_INFO_ENTRY, &mac_rdc);
474		for (i = 1; i <= BMAC_MAX_ALT_ADDR_ENTRY; i++)
475			rs |= npi_mac_hostinfo_entry(handle, OP_SET,
476			    nxgep->function_num, i, &mac_rdc);
477		break;
478	default:
479		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
480		    "failed Assign RDC table (invalid function #)"));
481		return (NXGE_ERROR);
482	}
483
484	if (rs != NPI_SUCCESS) {
485		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
486		    "failed Assign RDC table"));
487		return (NXGE_ERROR | rs);
488	}
489	return (NXGE_OK);
490}
491
492/*
493 * Initialize hostinfo registers for alternate MAC addresses and
494 * multicast MAC address.
495 */
496nxge_status_t
497nxge_alt_mcast_mac_assign_rdc_table(p_nxge_t nxgep)
498{
499	npi_status_t rs = NPI_SUCCESS;
500	hostinfo_t mac_rdc;
501	npi_handle_t handle;
502
503	handle = nxgep->npi_reg_handle;
504	mac_rdc.value = 0;
505	mac_rdc.bits.w0.rdc_tbl_num = nxgep->class_config.mcast_rdcgrp;
506	mac_rdc.bits.w0.mac_pref = 1;
507	switch (nxgep->function_num) {
508	case 0:
509	case 1:
510		rs = npi_mac_hostinfo_entry(handle, OP_SET,
511		    nxgep->function_num, XMAC_MULTI_HOST_INFO_ENTRY, &mac_rdc);
512		break;
513	case 2:
514	case 3:
515		rs = npi_mac_hostinfo_entry(handle, OP_SET,
516		    nxgep->function_num, BMAC_MULTI_HOST_INFO_ENTRY, &mac_rdc);
517		break;
518	default:
519		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
520		    "failed Assign RDC table (invalid function #)"));
521		return (NXGE_ERROR);
522	}
523
524	if (rs != NPI_SUCCESS) {
525		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
526		    "failed Assign RDC table"));
527		return (NXGE_ERROR | rs);
528	}
529	return (NXGE_OK);
530}
531
532nxge_status_t
533nxge_fflp_init_hostinfo(p_nxge_t nxgep)
534{
535	nxge_status_t status = NXGE_OK;
536
537	status = nxge_alt_mcast_mac_assign_rdc_table(nxgep);
538	status |= nxge_main_mac_assign_rdc_table(nxgep);
539	return (status);
540}
541
542nxge_status_t
543nxge_fflp_hw_reset(p_nxge_t nxgep)
544{
545	npi_handle_t handle;
546	npi_status_t rs = NPI_SUCCESS;
547	nxge_status_t status = NXGE_OK;
548
549	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_hw_reset"));
550
551	if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
552		status = nxge_fflp_fcram_init(nxgep);
553		if (status != NXGE_OK) {
554			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
555			    " failed FCRAM init. "));
556			return (status);
557		}
558	}
559
560	status = nxge_fflp_tcam_init(nxgep);
561	if (status != NXGE_OK) {
562		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
563		    "failed TCAM init."));
564		return (status);
565	}
566
567	handle = nxgep->npi_reg_handle;
568	rs = npi_fflp_cfg_llcsnap_enable(handle);
569	if (rs != NPI_SUCCESS) {
570		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
571		    "failed LLCSNAP enable. "));
572		return (NXGE_ERROR | rs);
573	}
574
575	rs = npi_fflp_cfg_cam_errorcheck_disable(handle);
576	if (rs != NPI_SUCCESS) {
577		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
578		    "failed CAM Error Check enable. "));
579		return (NXGE_ERROR | rs);
580	}
581
582	/* init the hash generators */
583	rs = npi_fflp_cfg_hash_h1poly(handle, 0);
584	if (rs != NPI_SUCCESS) {
585		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
586		    "failed H1 Poly Init. "));
587		return (NXGE_ERROR | rs);
588	}
589
590	rs = npi_fflp_cfg_hash_h2poly(handle, 0);
591	if (rs != NPI_SUCCESS) {
592		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
593		    "failed H2 Poly Init. "));
594		return (NXGE_ERROR | rs);
595	}
596
597	/* invalidate TCAM entries */
598	status = nxge_fflp_tcam_invalidate_all(nxgep);
599	if (status != NXGE_OK) {
600		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
601		    "failed TCAM Entry Invalidate. "));
602		return (status);
603	}
604
605	/* invalidate FCRAM entries */
606	if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
607		status = nxge_fflp_fcram_invalidate_all(nxgep);
608		if (status != NXGE_OK) {
609			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
610			    "failed FCRAM Entry Invalidate."));
611			return (status);
612		}
613	}
614
615	/* invalidate VLAN RDC tables */
616	status = nxge_fflp_vlan_tbl_clear_all(nxgep);
617	if (status != NXGE_OK) {
618		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
619		    "failed VLAN Table Invalidate. "));
620		return (status);
621	}
622	nxgep->classifier.state |= NXGE_FFLP_HW_RESET;
623
624	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_hw_reset"));
625	return (NXGE_OK);
626}
627
628nxge_status_t
629nxge_cfg_ip_cls_flow_key(p_nxge_t nxgep, tcam_class_t l3_class,
630	uint32_t class_config)
631{
632	flow_key_cfg_t fcfg;
633	npi_handle_t handle;
634	npi_status_t rs = NPI_SUCCESS;
635
636	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_cfg_ip_cls_flow_key"));
637	handle = nxgep->npi_reg_handle;
638	bzero(&fcfg, sizeof (flow_key_cfg_t));
639
640	if (class_config & NXGE_CLASS_FLOW_USE_PROTO)
641		fcfg.use_proto = 1;
642	if (class_config & NXGE_CLASS_FLOW_USE_DST_PORT)
643		fcfg.use_dport = 1;
644	if (class_config & NXGE_CLASS_FLOW_USE_SRC_PORT)
645		fcfg.use_sport = 1;
646	if (class_config & NXGE_CLASS_FLOW_USE_IPDST)
647		fcfg.use_daddr = 1;
648	if (class_config & NXGE_CLASS_FLOW_USE_IPSRC)
649		fcfg.use_saddr = 1;
650	if (class_config & NXGE_CLASS_FLOW_USE_VLAN)
651		fcfg.use_vlan = 1;
652	if (class_config & NXGE_CLASS_FLOW_USE_L2DA)
653		fcfg.use_l2da = 1;
654	if (class_config & NXGE_CLASS_FLOW_USE_PORTNUM)
655		fcfg.use_portnum = 1;
656	fcfg.ip_opts_exist = 0;
657
658	rs = npi_fflp_cfg_ip_cls_flow_key(handle, l3_class, &fcfg);
659	if (rs & NPI_FFLP_ERROR) {
660		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_ip_cls_flow_key"
661		    " opt %x for class %d failed ", class_config, l3_class));
662		return (NXGE_ERROR | rs);
663	}
664	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_cfg_ip_cls_flow_key"));
665	return (NXGE_OK);
666}
667
668nxge_status_t
669nxge_cfg_ip_cls_flow_key_get(p_nxge_t nxgep, tcam_class_t l3_class,
670	uint32_t *class_config)
671{
672	flow_key_cfg_t fcfg;
673	npi_handle_t handle;
674	npi_status_t rs = NPI_SUCCESS;
675	uint32_t ccfg = 0;
676
677	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_cfg_ip_cls_flow_key_get"));
678	handle = nxgep->npi_reg_handle;
679	bzero(&fcfg, sizeof (flow_key_cfg_t));
680
681	rs = npi_fflp_cfg_ip_cls_flow_key_get(handle, l3_class, &fcfg);
682	if (rs & NPI_FFLP_ERROR) {
683		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_ip_cls_flow_key"
684		    " opt %x for class %d failed ", class_config, l3_class));
685		return (NXGE_ERROR | rs);
686	}
687
688	if (fcfg.use_proto)
689		ccfg |= NXGE_CLASS_FLOW_USE_PROTO;
690	if (fcfg.use_dport)
691		ccfg |= NXGE_CLASS_FLOW_USE_DST_PORT;
692	if (fcfg.use_sport)
693		ccfg |= NXGE_CLASS_FLOW_USE_SRC_PORT;
694	if (fcfg.use_daddr)
695		ccfg |= NXGE_CLASS_FLOW_USE_IPDST;
696	if (fcfg.use_saddr)
697		ccfg |= NXGE_CLASS_FLOW_USE_IPSRC;
698	if (fcfg.use_vlan)
699		ccfg |= NXGE_CLASS_FLOW_USE_VLAN;
700	if (fcfg.use_l2da)
701		ccfg |= NXGE_CLASS_FLOW_USE_L2DA;
702	if (fcfg.use_portnum)
703		ccfg |= NXGE_CLASS_FLOW_USE_PORTNUM;
704
705	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
706	    " nxge_cfg_ip_cls_flow_key_get %x", ccfg));
707	*class_config = ccfg;
708
709	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
710	    " <== nxge_cfg_ip_cls_flow_key_get"));
711	return (NXGE_OK);
712}
713
714static nxge_status_t
715nxge_cfg_tcam_ip_class_get(p_nxge_t nxgep, tcam_class_t class,
716	uint32_t *class_config)
717{
718	npi_status_t rs = NPI_SUCCESS;
719	tcam_key_cfg_t cfg;
720	npi_handle_t handle;
721	uint32_t ccfg = 0;
722
723	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_cfg_tcam_ip_class"));
724
725	bzero(&cfg, sizeof (tcam_key_cfg_t));
726	handle = nxgep->npi_reg_handle;
727
728	rs = npi_fflp_cfg_ip_cls_tcam_key_get(handle, class, &cfg);
729	if (rs & NPI_FFLP_ERROR) {
730		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_tcam_ip_class"
731		    " opt %x for class %d failed ", class_config, class));
732		return (NXGE_ERROR | rs);
733	}
734	if (cfg.discard)
735		ccfg |= NXGE_CLASS_DISCARD;
736	if (cfg.lookup_enable)
737		ccfg |= NXGE_CLASS_TCAM_LOOKUP;
738	if (cfg.use_ip_daddr)
739		ccfg |= NXGE_CLASS_TCAM_USE_SRC_ADDR;
740	*class_config = ccfg;
741	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
742	    " ==> nxge_cfg_tcam_ip_class %x", ccfg));
743	return (NXGE_OK);
744}
745
746static nxge_status_t
747nxge_cfg_tcam_ip_class(p_nxge_t nxgep, tcam_class_t class,
748	uint32_t class_config)
749{
750	npi_status_t rs = NPI_SUCCESS;
751	tcam_key_cfg_t cfg;
752	npi_handle_t handle;
753	p_nxge_class_pt_cfg_t p_class_cfgp;
754
755	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_cfg_tcam_ip_class"));
756
757	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
758	p_class_cfgp->class_cfg[class] = class_config;
759
760	bzero(&cfg, sizeof (tcam_key_cfg_t));
761	handle = nxgep->npi_reg_handle;
762	cfg.discard = 0;
763	cfg.lookup_enable = 0;
764	cfg.use_ip_daddr = 0;
765	if (class_config & NXGE_CLASS_DISCARD)
766		cfg.discard = 1;
767	if (class_config & NXGE_CLASS_TCAM_LOOKUP)
768		cfg.lookup_enable = 1;
769	if (class_config & NXGE_CLASS_TCAM_USE_SRC_ADDR)
770		cfg.use_ip_daddr = 1;
771
772	rs = npi_fflp_cfg_ip_cls_tcam_key(handle, class, &cfg);
773	if (rs & NPI_FFLP_ERROR) {
774		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_tcam_ip_class"
775		    " opt %x for class %d failed ", class_config, class));
776		return (NXGE_ERROR | rs);
777	}
778	return (NXGE_OK);
779}
780
781nxge_status_t
782nxge_fflp_set_hash1(p_nxge_t nxgep, uint32_t h1)
783{
784	npi_status_t rs = NPI_SUCCESS;
785	npi_handle_t handle;
786	p_nxge_class_pt_cfg_t p_class_cfgp;
787
788	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_init_h1"));
789	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
790	p_class_cfgp->init_h1 = h1;
791	handle = nxgep->npi_reg_handle;
792	rs = npi_fflp_cfg_hash_h1poly(handle, h1);
793	if (rs & NPI_FFLP_ERROR) {
794		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
795		    " nxge_fflp_init_h1 %x failed ", h1));
796		return (NXGE_ERROR | rs);
797	}
798	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_fflp_init_h1"));
799	return (NXGE_OK);
800}
801
802nxge_status_t
803nxge_fflp_set_hash2(p_nxge_t nxgep, uint16_t h2)
804{
805	npi_status_t rs = NPI_SUCCESS;
806	npi_handle_t handle;
807	p_nxge_class_pt_cfg_t p_class_cfgp;
808
809	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_init_h2"));
810	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
811	p_class_cfgp->init_h2 = h2;
812
813	handle = nxgep->npi_reg_handle;
814	rs = npi_fflp_cfg_hash_h2poly(handle, h2);
815	if (rs & NPI_FFLP_ERROR) {
816		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
817		    " nxge_fflp_init_h2 %x failed ", h2));
818		return (NXGE_ERROR | rs);
819	}
820	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_fflp_init_h2"));
821	return (NXGE_OK);
822}
823
824nxge_status_t
825nxge_classify_init_sw(p_nxge_t nxgep)
826{
827	nxge_classify_t *classify_ptr;
828
829	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_classify_init_sw"));
830	classify_ptr = &nxgep->classifier;
831
832	if (classify_ptr->state & NXGE_FFLP_SW_INIT) {
833		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
834		    "nxge_classify_init_sw already init"));
835		return (NXGE_OK);
836	}
837
838	classify_ptr->tcam_size = nxgep->nxge_hw_p->tcam_size / nxgep->nports;
839	classify_ptr->tcam_entries = (tcam_flow_spec_t *)nxgep->nxge_hw_p->tcam;
840	classify_ptr->tcam_top = nxgep->function_num;
841
842	/* Init defaults */
843	/*
844	 * add hacks required for HW shortcomings for example, code to handle
845	 * fragmented packets
846	 */
847	nxge_init_h1_table();
848	nxge_crc_ccitt_init();
849	nxgep->classifier.tcam_location = nxgep->function_num;
850	nxgep->classifier.fragment_bug = 1;
851	classify_ptr->state |= NXGE_FFLP_SW_INIT;
852
853	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_classify_init_sw"));
854	return (NXGE_OK);
855}
856
857nxge_status_t
858nxge_classify_exit_sw(p_nxge_t nxgep)
859{
860	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_classify_exit_sw"));
861	nxgep->classifier.state = 0;
862	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_classify_exit_sw"));
863	return (NXGE_OK);
864}
865
866/*
867 * Figures out the RDC Group for the entry
868 *
869 * The current implementation is just a place holder and it
870 * returns 0.
871 * The real location determining algorithm would consider
872 * the partition etc ... before deciding w
873 *
874 */
875
876/* ARGSUSED */
877static uint8_t
878nxge_get_rdc_group(p_nxge_t nxgep, uint8_t class, uint64_t cookie)
879{
880	int use_port_rdc_grp = 0;
881	uint8_t rdc_grp = 0;
882	p_nxge_dma_pt_cfg_t p_dma_cfgp;
883	p_nxge_hw_pt_cfg_t p_cfgp;
884	p_nxge_rdc_grp_t rdc_grp_p;
885
886	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
887	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
888	rdc_grp_p = &p_dma_cfgp->rdc_grps[use_port_rdc_grp];
889	rdc_grp = p_cfgp->def_mac_rxdma_grpid;
890
891	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
892	    "nxge_get_rdc_group: grp 0x%x real_grp %x grpp $%p\n",
893	    cookie, rdc_grp, rdc_grp_p));
894	return (rdc_grp);
895}
896
897/* ARGSUSED */
898static uint8_t
899nxge_get_rdc_offset(p_nxge_t nxgep, uint8_t class, uint64_t cookie)
900{
901	return ((uint8_t)cookie);
902}
903
904/* ARGSUSED */
905static void
906nxge_fill_tcam_entry_udp(p_nxge_t nxgep, flow_spec_t *flow_spec,
907	tcam_entry_t *tcam_ptr)
908{
909	udpip4_spec_t *fspec_key;
910	udpip4_spec_t *fspec_mask;
911
912	fspec_key = (udpip4_spec_t *)&flow_spec->uh.udpip4spec;
913	fspec_mask = (udpip4_spec_t *)&flow_spec->um.udpip4spec;
914	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
915	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
916	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
917	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
918	TCAM_IP_PORTS(tcam_ptr->ip4_port_key,
919	    fspec_key->pdst, fspec_key->psrc);
920	TCAM_IP_PORTS(tcam_ptr->ip4_port_mask,
921	    fspec_mask->pdst, fspec_mask->psrc);
922	TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
923	    tcam_ptr->ip4_class_mask,
924	    TCAM_CLASS_UDP_IPV4);
925	TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
926	    tcam_ptr->ip4_proto_mask,
927	    IPPROTO_UDP);
928	tcam_ptr->ip4_tos_key = fspec_key->tos;
929	tcam_ptr->ip4_tos_mask = fspec_mask->tos;
930}
931
932static void
933nxge_fill_tcam_entry_udp_ipv6(p_nxge_t nxgep, flow_spec_t *flow_spec,
934	tcam_entry_t *tcam_ptr)
935{
936	udpip6_spec_t *fspec_key;
937	udpip6_spec_t *fspec_mask;
938	p_nxge_class_pt_cfg_t p_class_cfgp;
939
940	fspec_key = (udpip6_spec_t *)&flow_spec->uh.udpip6spec;
941	fspec_mask = (udpip6_spec_t *)&flow_spec->um.udpip6spec;
942	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
943	if (p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV6] &
944	    NXGE_CLASS_TCAM_USE_SRC_ADDR) {
945		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6src);
946		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6src);
947	} else {
948		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6dst);
949		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6dst);
950	}
951
952	TCAM_IP_CLASS(tcam_ptr->ip6_class_key,
953	    tcam_ptr->ip6_class_mask, TCAM_CLASS_UDP_IPV6);
954	TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
955	    tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_UDP);
956	TCAM_IP_PORTS(tcam_ptr->ip6_port_key,
957	    fspec_key->pdst, fspec_key->psrc);
958	TCAM_IP_PORTS(tcam_ptr->ip6_port_mask,
959	    fspec_mask->pdst, fspec_mask->psrc);
960	tcam_ptr->ip6_tos_key = fspec_key->tos;
961	tcam_ptr->ip6_tos_mask = fspec_mask->tos;
962}
963
964/* ARGSUSED */
965static void
966nxge_fill_tcam_entry_tcp(p_nxge_t nxgep, flow_spec_t *flow_spec,
967	tcam_entry_t *tcam_ptr)
968{
969	tcpip4_spec_t *fspec_key;
970	tcpip4_spec_t *fspec_mask;
971
972	fspec_key = (tcpip4_spec_t *)&flow_spec->uh.tcpip4spec;
973	fspec_mask = (tcpip4_spec_t *)&flow_spec->um.tcpip4spec;
974
975	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
976	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
977	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
978	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
979	TCAM_IP_PORTS(tcam_ptr->ip4_port_key,
980	    fspec_key->pdst, fspec_key->psrc);
981	TCAM_IP_PORTS(tcam_ptr->ip4_port_mask,
982	    fspec_mask->pdst, fspec_mask->psrc);
983	TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
984	    tcam_ptr->ip4_class_mask, TCAM_CLASS_TCP_IPV4);
985	TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
986	    tcam_ptr->ip4_proto_mask, IPPROTO_TCP);
987	tcam_ptr->ip4_tos_key = fspec_key->tos;
988	tcam_ptr->ip4_tos_mask = fspec_mask->tos;
989}
990
991/* ARGSUSED */
992static void
993nxge_fill_tcam_entry_sctp(p_nxge_t nxgep, flow_spec_t *flow_spec,
994	tcam_entry_t *tcam_ptr)
995{
996	tcpip4_spec_t *fspec_key;
997	tcpip4_spec_t *fspec_mask;
998
999	fspec_key = (tcpip4_spec_t *)&flow_spec->uh.tcpip4spec;
1000	fspec_mask = (tcpip4_spec_t *)&flow_spec->um.tcpip4spec;
1001
1002	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
1003	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
1004	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
1005	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
1006	TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
1007	    tcam_ptr->ip4_class_mask, TCAM_CLASS_SCTP_IPV4);
1008	TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
1009	    tcam_ptr->ip4_proto_mask, IPPROTO_SCTP);
1010	TCAM_IP_PORTS(tcam_ptr->ip4_port_key,
1011	    fspec_key->pdst, fspec_key->psrc);
1012	TCAM_IP_PORTS(tcam_ptr->ip4_port_mask,
1013	    fspec_mask->pdst, fspec_mask->psrc);
1014	tcam_ptr->ip4_tos_key = fspec_key->tos;
1015	tcam_ptr->ip4_tos_mask = fspec_mask->tos;
1016}
1017
1018static void
1019nxge_fill_tcam_entry_tcp_ipv6(p_nxge_t nxgep, flow_spec_t *flow_spec,
1020	tcam_entry_t *tcam_ptr)
1021{
1022	tcpip6_spec_t *fspec_key;
1023	tcpip6_spec_t *fspec_mask;
1024	p_nxge_class_pt_cfg_t p_class_cfgp;
1025
1026	fspec_key = (tcpip6_spec_t *)&flow_spec->uh.tcpip6spec;
1027	fspec_mask = (tcpip6_spec_t *)&flow_spec->um.tcpip6spec;
1028
1029	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
1030	if (p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV6] &
1031	    NXGE_CLASS_TCAM_USE_SRC_ADDR) {
1032		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6src);
1033		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6src);
1034	} else {
1035		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6dst);
1036		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6dst);
1037	}
1038
1039	TCAM_IP_CLASS(tcam_ptr->ip6_class_key,
1040	    tcam_ptr->ip6_class_mask, TCAM_CLASS_TCP_IPV6);
1041	TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
1042	    tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_TCP);
1043	TCAM_IP_PORTS(tcam_ptr->ip6_port_key,
1044	    fspec_key->pdst, fspec_key->psrc);
1045	TCAM_IP_PORTS(tcam_ptr->ip6_port_mask,
1046	    fspec_mask->pdst, fspec_mask->psrc);
1047	tcam_ptr->ip6_tos_key = fspec_key->tos;
1048	tcam_ptr->ip6_tos_mask = fspec_mask->tos;
1049}
1050
1051static void
1052nxge_fill_tcam_entry_sctp_ipv6(p_nxge_t nxgep, flow_spec_t *flow_spec,
1053	tcam_entry_t *tcam_ptr)
1054{
1055	tcpip6_spec_t *fspec_key;
1056	tcpip6_spec_t *fspec_mask;
1057	p_nxge_class_pt_cfg_t p_class_cfgp;
1058
1059	fspec_key = (tcpip6_spec_t *)&flow_spec->uh.tcpip6spec;
1060	fspec_mask = (tcpip6_spec_t *)&flow_spec->um.tcpip6spec;
1061	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
1062
1063	if (p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV6] &
1064	    NXGE_CLASS_TCAM_USE_SRC_ADDR) {
1065		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6src);
1066		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6src);
1067	} else {
1068		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6dst);
1069		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6dst);
1070	}
1071
1072	TCAM_IP_CLASS(tcam_ptr->ip6_class_key,
1073	    tcam_ptr->ip6_class_mask, TCAM_CLASS_SCTP_IPV6);
1074	TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
1075	    tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_SCTP);
1076	TCAM_IP_PORTS(tcam_ptr->ip6_port_key,
1077	    fspec_key->pdst, fspec_key->psrc);
1078	TCAM_IP_PORTS(tcam_ptr->ip6_port_mask,
1079	    fspec_mask->pdst, fspec_mask->psrc);
1080	tcam_ptr->ip6_tos_key = fspec_key->tos;
1081	tcam_ptr->ip6_tos_mask = fspec_mask->tos;
1082}
1083
1084/* ARGSUSED */
1085static void
1086nxge_fill_tcam_entry_ah_esp(p_nxge_t nxgep, flow_spec_t *flow_spec,
1087	tcam_entry_t *tcam_ptr)
1088{
1089	ahip4_spec_t *fspec_key;
1090	ahip4_spec_t *fspec_mask;
1091
1092	fspec_key = (ahip4_spec_t *)&flow_spec->uh.ahip4spec;
1093	fspec_mask = (ahip4_spec_t *)&flow_spec->um.ahip4spec;
1094
1095	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
1096	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
1097	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
1098	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
1099
1100	tcam_ptr->ip4_port_key = fspec_key->spi;
1101	tcam_ptr->ip4_port_mask = fspec_mask->spi;
1102
1103	TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
1104	    tcam_ptr->ip4_class_mask,
1105	    TCAM_CLASS_AH_ESP_IPV4);
1106
1107	if (flow_spec->flow_type == FSPEC_AHIP4) {
1108		TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
1109		    tcam_ptr->ip4_proto_mask, IPPROTO_AH);
1110	} else {
1111		TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
1112		    tcam_ptr->ip4_proto_mask, IPPROTO_ESP);
1113	}
1114	tcam_ptr->ip4_tos_key = fspec_key->tos;
1115	tcam_ptr->ip4_tos_mask = fspec_mask->tos;
1116}
1117
1118static void
1119nxge_fill_tcam_entry_ah_esp_ipv6(p_nxge_t nxgep, flow_spec_t *flow_spec,
1120	tcam_entry_t *tcam_ptr)
1121{
1122	ahip6_spec_t *fspec_key;
1123	ahip6_spec_t *fspec_mask;
1124	p_nxge_class_pt_cfg_t p_class_cfgp;
1125
1126	fspec_key = (ahip6_spec_t *)&flow_spec->uh.ahip6spec;
1127	fspec_mask = (ahip6_spec_t *)&flow_spec->um.ahip6spec;
1128
1129	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
1130	if (p_class_cfgp->class_cfg[TCAM_CLASS_AH_ESP_IPV6] &
1131	    NXGE_CLASS_TCAM_USE_SRC_ADDR) {
1132		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6src);
1133		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6src);
1134	} else {
1135		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6dst);
1136		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6dst);
1137	}
1138
1139	TCAM_IP_CLASS(tcam_ptr->ip6_class_key,
1140	    tcam_ptr->ip6_class_mask, TCAM_CLASS_AH_ESP_IPV6);
1141
1142	if (flow_spec->flow_type == FSPEC_AHIP6) {
1143		TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
1144		    tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_AH);
1145	} else {
1146		TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
1147		    tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_ESP);
1148	}
1149	tcam_ptr->ip6_port_key = fspec_key->spi;
1150	tcam_ptr->ip6_port_mask = fspec_mask->spi;
1151	tcam_ptr->ip6_tos_key = fspec_key->tos;
1152	tcam_ptr->ip6_tos_mask = fspec_mask->tos;
1153}
1154
1155/* ARGSUSED */
1156static void
1157nxge_fill_tcam_entry_ip_usr(p_nxge_t nxgep, flow_spec_t *flow_spec,
1158	tcam_entry_t *tcam_ptr, tcam_class_t class)
1159{
1160	ip_user_spec_t *fspec_key;
1161	ip_user_spec_t *fspec_mask;
1162
1163	fspec_key = (ip_user_spec_t *)&flow_spec->uh.ip_usr_spec;
1164	fspec_mask = (ip_user_spec_t *)&flow_spec->um.ip_usr_spec;
1165
1166	if (fspec_key->ip_ver == FSPEC_IP4) {
1167		TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
1168		TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
1169		TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
1170		TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
1171
1172		tcam_ptr->ip4_port_key = fspec_key->l4_4_bytes;
1173		tcam_ptr->ip4_port_mask = fspec_mask->l4_4_bytes;
1174
1175		TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
1176		    tcam_ptr->ip4_class_mask, class);
1177
1178		tcam_ptr->ip4_proto_key = fspec_key->proto;
1179		tcam_ptr->ip4_proto_mask = fspec_mask->proto;
1180
1181		tcam_ptr->ip4_tos_key = fspec_key->tos;
1182		tcam_ptr->ip4_tos_mask = fspec_mask->tos;
1183	}
1184}
1185
1186
1187nxge_status_t
1188nxge_flow_get_hash(p_nxge_t nxgep, flow_resource_t *flow_res,
1189	uint32_t *H1, uint16_t *H2)
1190{
1191	flow_spec_t *flow_spec;
1192	uint32_t class_cfg;
1193	flow_template_t ft;
1194	p_nxge_class_pt_cfg_t p_class_cfgp;
1195
1196	int ft_size = sizeof (flow_template_t);
1197
1198	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_flow_get_hash"));
1199
1200	flow_spec = (flow_spec_t *)&flow_res->flow_spec;
1201	bzero((char *)&ft, ft_size);
1202	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
1203
1204	switch (flow_spec->flow_type) {
1205	case FSPEC_TCPIP4:
1206		class_cfg = p_class_cfgp->class_cfg[TCAM_CLASS_TCP_IPV4];
1207		if (class_cfg & NXGE_CLASS_FLOW_USE_PROTO)
1208			ft.ip_proto = IPPROTO_TCP;
1209		if (class_cfg & NXGE_CLASS_FLOW_USE_IPSRC)
1210			ft.ip4_saddr = flow_res->flow_spec.uh.tcpip4spec.ip4src;
1211		if (class_cfg & NXGE_CLASS_FLOW_USE_IPDST)
1212			ft.ip4_daddr = flow_res->flow_spec.uh.tcpip4spec.ip4dst;
1213		if (class_cfg & NXGE_CLASS_FLOW_USE_SRC_PORT)
1214			ft.ip_src_port = flow_res->flow_spec.uh.tcpip4spec.psrc;
1215		if (class_cfg & NXGE_CLASS_FLOW_USE_DST_PORT)
1216			ft.ip_dst_port = flow_res->flow_spec.uh.tcpip4spec.pdst;
1217		break;
1218
1219	case FSPEC_UDPIP4:
1220		class_cfg = p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV4];
1221		if (class_cfg & NXGE_CLASS_FLOW_USE_PROTO)
1222			ft.ip_proto = IPPROTO_UDP;
1223		if (class_cfg & NXGE_CLASS_FLOW_USE_IPSRC)
1224			ft.ip4_saddr = flow_res->flow_spec.uh.udpip4spec.ip4src;
1225		if (class_cfg & NXGE_CLASS_FLOW_USE_IPDST)
1226			ft.ip4_daddr = flow_res->flow_spec.uh.udpip4spec.ip4dst;
1227		if (class_cfg & NXGE_CLASS_FLOW_USE_SRC_PORT)
1228			ft.ip_src_port = flow_res->flow_spec.uh.udpip4spec.psrc;
1229		if (class_cfg & NXGE_CLASS_FLOW_USE_DST_PORT)
1230			ft.ip_dst_port = flow_res->flow_spec.uh.udpip4spec.pdst;
1231		break;
1232
1233	default:
1234		return (NXGE_ERROR);
1235	}
1236
1237	*H1 = nxge_compute_h1(p_class_cfgp->init_h1,
1238	    (uint32_t *)&ft, ft_size) & 0xfffff;
1239	*H2 = nxge_compute_h2(p_class_cfgp->init_h2,
1240	    (uint8_t *)&ft, ft_size);
1241
1242	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_flow_get_hash"));
1243	return (NXGE_OK);
1244}
1245
1246nxge_status_t
1247nxge_add_fcram_entry(p_nxge_t nxgep, flow_resource_t *flow_res)
1248{
1249	uint32_t H1;
1250	uint16_t H2;
1251	nxge_status_t status = NXGE_OK;
1252
1253	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_add_fcram_entry"));
1254	status = nxge_flow_get_hash(nxgep, flow_res, &H1, &H2);
1255	if (status != NXGE_OK) {
1256		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1257		    " nxge_add_fcram_entry failed "));
1258		return (status);
1259	}
1260
1261	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_add_fcram_entry"));
1262	return (NXGE_OK);
1263}
1264
1265/*
1266 * Already decided this flow goes into the tcam
1267 */
1268
1269nxge_status_t
1270nxge_add_tcam_entry(p_nxge_t nxgep, flow_resource_t *flow_res)
1271{
1272	npi_handle_t handle;
1273	uint64_t channel_cookie;
1274	uint64_t flow_cookie;
1275	flow_spec_t *flow_spec;
1276	npi_status_t rs = NPI_SUCCESS;
1277	tcam_entry_t tcam_ptr;
1278	tcam_location_t location;
1279	uint8_t offset, rdc_grp;
1280	p_nxge_hw_list_t hw_p;
1281	uint64_t class;
1282
1283	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_add_tcam_entry"));
1284	handle = nxgep->npi_reg_handle;
1285
1286	bzero((void *)&tcam_ptr, sizeof (tcam_entry_t));
1287	flow_spec = (flow_spec_t *)&flow_res->flow_spec;
1288	flow_cookie = flow_res->flow_cookie;
1289	channel_cookie = flow_res->channel_cookie;
1290	location = (tcam_location_t)nxge_tcam_get_index(nxgep,
1291	    (uint16_t)flow_res->location);
1292
1293	if ((hw_p = nxgep->nxge_hw_p) == NULL) {
1294		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1295		    " nxge_add_tcam_entry: common hardware not set",
1296		    nxgep->niu_type));
1297		return (NXGE_ERROR);
1298	}
1299
1300	if (flow_spec->flow_type == FSPEC_IP_USR) {
1301		int i;
1302		int add_usr_cls = 0;
1303		int ipv6 = 0;
1304		ip_user_spec_t *uspec = &flow_spec->uh.ip_usr_spec;
1305		ip_user_spec_t *umask = &flow_spec->um.ip_usr_spec;
1306		nxge_usr_l3_cls_t *l3_ucls_p;
1307
1308		MUTEX_ENTER(&hw_p->nxge_tcam_lock);
1309
1310		for (i = 0; i < NXGE_L3_PROG_CLS; i++) {
1311			l3_ucls_p = &hw_p->tcam_l3_prog_cls[i];
1312			if (l3_ucls_p->valid && l3_ucls_p->tcam_ref_cnt) {
1313				if (uspec->proto == l3_ucls_p->pid) {
1314					class = l3_ucls_p->cls;
1315					l3_ucls_p->tcam_ref_cnt++;
1316					add_usr_cls = 1;
1317					break;
1318				}
1319			} else if (l3_ucls_p->valid == 0) {
1320				/* Program new user IP class */
1321				switch (i) {
1322				case 0:
1323					class = TCAM_CLASS_IP_USER_4;
1324					break;
1325				case 1:
1326					class = TCAM_CLASS_IP_USER_5;
1327					break;
1328				case 2:
1329					class = TCAM_CLASS_IP_USER_6;
1330					break;
1331				case 3:
1332					class = TCAM_CLASS_IP_USER_7;
1333					break;
1334				default:
1335					break;
1336				}
1337				if (uspec->ip_ver == FSPEC_IP6)
1338					ipv6 = 1;
1339				rs = npi_fflp_cfg_ip_usr_cls_set(handle,
1340				    (tcam_class_t)class, uspec->tos,
1341				    umask->tos, uspec->proto, ipv6);
1342				if (rs != NPI_SUCCESS)
1343					goto fail;
1344
1345				rs = npi_fflp_cfg_ip_usr_cls_enable(handle,
1346				    (tcam_class_t)class);
1347				if (rs != NPI_SUCCESS)
1348					goto fail;
1349
1350				l3_ucls_p->cls = class;
1351				l3_ucls_p->pid = uspec->proto;
1352				l3_ucls_p->tcam_ref_cnt++;
1353				l3_ucls_p->valid = 1;
1354				add_usr_cls = 1;
1355				break;
1356			} else if (l3_ucls_p->tcam_ref_cnt == 0 &&
1357			    uspec->proto == l3_ucls_p->pid) {
1358				/*
1359				 * The class has already been programmed,
1360				 * probably for flow hash
1361				 */
1362				class = l3_ucls_p->cls;
1363				if (uspec->ip_ver == FSPEC_IP6)
1364					ipv6 = 1;
1365				rs = npi_fflp_cfg_ip_usr_cls_set(handle,
1366				    (tcam_class_t)class, uspec->tos,
1367				    umask->tos, uspec->proto, ipv6);
1368				if (rs != NPI_SUCCESS)
1369					goto fail;
1370
1371				rs = npi_fflp_cfg_ip_usr_cls_enable(handle,
1372				    (tcam_class_t)class);
1373				if (rs != NPI_SUCCESS)
1374					goto fail;
1375
1376				l3_ucls_p->pid = uspec->proto;
1377				l3_ucls_p->tcam_ref_cnt++;
1378				add_usr_cls = 1;
1379				break;
1380			}
1381		}
1382		if (!add_usr_cls) {
1383			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1384			    "nxge_add_tcam_entry: Could not find/insert class"
1385			    "for pid %d", uspec->proto));
1386			goto fail;
1387		}
1388		MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1389	}
1390
1391	switch (flow_spec->flow_type) {
1392	case FSPEC_TCPIP4:
1393		nxge_fill_tcam_entry_tcp(nxgep, flow_spec, &tcam_ptr);
1394		rdc_grp = nxge_get_rdc_group(nxgep, TCAM_CLASS_TCP_IPV4,
1395		    flow_cookie);
1396		offset = nxge_get_rdc_offset(nxgep, TCAM_CLASS_TCP_IPV4,
1397		    channel_cookie);
1398		break;
1399
1400	case FSPEC_UDPIP4:
1401		nxge_fill_tcam_entry_udp(nxgep, flow_spec, &tcam_ptr);
1402		rdc_grp = nxge_get_rdc_group(nxgep,
1403		    TCAM_CLASS_UDP_IPV4,
1404		    flow_cookie);
1405		offset = nxge_get_rdc_offset(nxgep,
1406		    TCAM_CLASS_UDP_IPV4,
1407		    channel_cookie);
1408		break;
1409
1410	case FSPEC_TCPIP6:
1411		nxge_fill_tcam_entry_tcp_ipv6(nxgep,
1412		    flow_spec, &tcam_ptr);
1413		rdc_grp = nxge_get_rdc_group(nxgep, TCAM_CLASS_TCP_IPV6,
1414		    flow_cookie);
1415		offset = nxge_get_rdc_offset(nxgep, TCAM_CLASS_TCP_IPV6,
1416		    channel_cookie);
1417		break;
1418
1419	case FSPEC_UDPIP6:
1420		nxge_fill_tcam_entry_udp_ipv6(nxgep,
1421		    flow_spec, &tcam_ptr);
1422		rdc_grp = nxge_get_rdc_group(nxgep,
1423		    TCAM_CLASS_UDP_IPV6,
1424		    flow_cookie);
1425		offset = nxge_get_rdc_offset(nxgep,
1426		    TCAM_CLASS_UDP_IPV6,
1427		    channel_cookie);
1428		break;
1429
1430	case FSPEC_SCTPIP4:
1431		nxge_fill_tcam_entry_sctp(nxgep, flow_spec, &tcam_ptr);
1432		rdc_grp = nxge_get_rdc_group(nxgep,
1433		    TCAM_CLASS_SCTP_IPV4,
1434		    flow_cookie);
1435		offset = nxge_get_rdc_offset(nxgep,
1436		    TCAM_CLASS_SCTP_IPV4,
1437		    channel_cookie);
1438		break;
1439
1440	case FSPEC_SCTPIP6:
1441		nxge_fill_tcam_entry_sctp_ipv6(nxgep,
1442		    flow_spec, &tcam_ptr);
1443		rdc_grp = nxge_get_rdc_group(nxgep,
1444		    TCAM_CLASS_SCTP_IPV6,
1445		    flow_cookie);
1446		offset = nxge_get_rdc_offset(nxgep,
1447		    TCAM_CLASS_SCTP_IPV6,
1448		    channel_cookie);
1449		break;
1450
1451	case FSPEC_AHIP4:
1452	case FSPEC_ESPIP4:
1453		nxge_fill_tcam_entry_ah_esp(nxgep, flow_spec, &tcam_ptr);
1454		rdc_grp = nxge_get_rdc_group(nxgep,
1455		    TCAM_CLASS_AH_ESP_IPV4,
1456		    flow_cookie);
1457		offset = nxge_get_rdc_offset(nxgep,
1458		    TCAM_CLASS_AH_ESP_IPV4,
1459		    channel_cookie);
1460		break;
1461
1462	case FSPEC_AHIP6:
1463	case FSPEC_ESPIP6:
1464		nxge_fill_tcam_entry_ah_esp_ipv6(nxgep,
1465		    flow_spec, &tcam_ptr);
1466		rdc_grp = nxge_get_rdc_group(nxgep,
1467		    TCAM_CLASS_AH_ESP_IPV6,
1468		    flow_cookie);
1469		offset = nxge_get_rdc_offset(nxgep,
1470		    TCAM_CLASS_AH_ESP_IPV6,
1471		    channel_cookie);
1472		break;
1473
1474	case FSPEC_IP_USR:
1475		nxge_fill_tcam_entry_ip_usr(nxgep, flow_spec, &tcam_ptr,
1476		    (tcam_class_t)class);
1477		rdc_grp = nxge_get_rdc_group(nxgep,
1478		    (tcam_class_t)class, flow_cookie);
1479		offset = nxge_get_rdc_offset(nxgep,
1480		    (tcam_class_t)class, channel_cookie);
1481		break;
1482	default:
1483		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1484		    "nxge_add_tcam_entry: Unknown flow spec 0x%x",
1485		    flow_spec->flow_type));
1486		return (NXGE_ERROR);
1487	}
1488
1489	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1490	    " nxge_add_tcam_entry write"
1491	    " for location %d offset %d", location, offset));
1492
1493	MUTEX_ENTER(&hw_p->nxge_tcam_lock);
1494	rs = npi_fflp_tcam_entry_write(handle, location, &tcam_ptr);
1495
1496	if (rs & NPI_FFLP_ERROR) {
1497		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1498		    " nxge_add_tcam_entry write"
1499		    " failed for location %d", location));
1500		goto fail;
1501	}
1502
1503	tcam_ptr.match_action.value = 0;
1504	tcam_ptr.match_action.bits.ldw.rdctbl = rdc_grp;
1505	tcam_ptr.match_action.bits.ldw.offset = offset;
1506	tcam_ptr.match_action.bits.ldw.tres =
1507	    TRES_TERM_OVRD_L2RDC;
1508	if (channel_cookie == NXGE_PKT_DISCARD)
1509		tcam_ptr.match_action.bits.ldw.disc = 1;
1510	rs = npi_fflp_tcam_asc_ram_entry_write(handle,
1511	    location, tcam_ptr.match_action.value);
1512	if (rs & NPI_FFLP_ERROR) {
1513		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1514		    " nxge_add_tcam_entry write"
1515		    " failed for ASC RAM location %d", location));
1516		goto fail;
1517	}
1518	bcopy((void *) &tcam_ptr,
1519	    (void *) &nxgep->classifier.tcam_entries[location].tce,
1520	    sizeof (tcam_entry_t));
1521	nxgep->classifier.tcam_entry_cnt++;
1522	nxgep->classifier.tcam_entries[location].valid = 1;
1523
1524	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1525	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_add_tcam_entry"));
1526	return (NXGE_OK);
1527fail:
1528	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1529	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_tcam_entry FAILED"));
1530	return (NXGE_ERROR);
1531}
1532
1533static nxge_status_t
1534nxge_tcam_handle_ip_fragment(p_nxge_t nxgep)
1535{
1536	tcam_entry_t tcam_ptr;
1537	tcam_location_t location;
1538	uint8_t class;
1539	uint32_t class_config;
1540	npi_handle_t handle;
1541	npi_status_t rs = NPI_SUCCESS;
1542	p_nxge_hw_list_t hw_p;
1543	nxge_status_t status = NXGE_OK;
1544
1545	handle = nxgep->npi_reg_handle;
1546	class = 0;
1547	bzero((void *)&tcam_ptr, sizeof (tcam_entry_t));
1548	tcam_ptr.ip4_noport_key = 1;
1549	tcam_ptr.ip4_noport_mask = 1;
1550	location = nxgep->function_num;
1551	nxgep->classifier.fragment_bug_location = location;
1552
1553	if ((hw_p = nxgep->nxge_hw_p) == NULL) {
1554		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1555		    " nxge_tcam_handle_ip_fragment: common hardware not set",
1556		    nxgep->niu_type));
1557		return (NXGE_ERROR);
1558	}
1559	MUTEX_ENTER(&hw_p->nxge_tcam_lock);
1560	rs = npi_fflp_tcam_entry_write(handle,
1561	    location, &tcam_ptr);
1562
1563	if (rs & NPI_FFLP_ERROR) {
1564		MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1565		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1566		    " nxge_tcam_handle_ip_fragment "
1567		    " tcam_entry write"
1568		    " failed for location %d", location));
1569		return (NXGE_ERROR);
1570	}
1571	tcam_ptr.match_action.bits.ldw.rdctbl = nxgep->class_config.mac_rdcgrp;
1572	tcam_ptr.match_action.bits.ldw.offset = 0;	/* use the default */
1573	tcam_ptr.match_action.bits.ldw.tres =
1574	    TRES_TERM_USE_OFFSET;
1575	rs = npi_fflp_tcam_asc_ram_entry_write(handle,
1576	    location, tcam_ptr.match_action.value);
1577
1578	if (rs & NPI_FFLP_ERROR) {
1579		MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1580		NXGE_DEBUG_MSG((nxgep,
1581		    FFLP_CTL,
1582		    " nxge_tcam_handle_ip_fragment "
1583		    " tcam_entry write"
1584		    " failed for ASC RAM location %d", location));
1585		return (NXGE_ERROR);
1586	}
1587	bcopy((void *) &tcam_ptr,
1588	    (void *) &nxgep->classifier.tcam_entries[location].tce,
1589	    sizeof (tcam_entry_t));
1590	nxgep->classifier.tcam_entry_cnt++;
1591	nxgep->classifier.tcam_entries[location].valid = 1;
1592	for (class = TCAM_CLASS_TCP_IPV4;
1593	    class <= TCAM_CLASS_SCTP_IPV6; class++) {
1594		class_config = nxgep->class_config.class_cfg[class];
1595		class_config |= NXGE_CLASS_TCAM_LOOKUP;
1596		status = nxge_fflp_ip_class_config(nxgep, class, class_config);
1597
1598		if (status & NPI_FFLP_ERROR) {
1599			MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1600			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1601			    "nxge_tcam_handle_ip_fragment "
1602			    "nxge_fflp_ip_class_config failed "
1603			    " class %d config %x ", class, class_config));
1604			return (NXGE_ERROR);
1605		}
1606	}
1607
1608	rs = npi_fflp_cfg_tcam_enable(handle);
1609	if (rs & NPI_FFLP_ERROR) {
1610		MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1611		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1612		    "nxge_tcam_handle_ip_fragment "
1613		    " nxge_fflp_config_tcam_enable failed"));
1614		return (NXGE_ERROR);
1615	}
1616	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1617	return (NXGE_OK);
1618}
1619
1620/* ARGSUSED */
1621static int
1622nxge_flow_need_hash_lookup(p_nxge_t nxgep, flow_resource_t *flow_res)
1623{
1624	return (0);
1625}
1626
1627nxge_status_t
1628nxge_add_flow(p_nxge_t nxgep, flow_resource_t *flow_res)
1629{
1630
1631	int insert_hash = 0;
1632	nxge_status_t status = NXGE_OK;
1633
1634	if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
1635		/* determine whether to do TCAM or Hash flow */
1636		insert_hash = nxge_flow_need_hash_lookup(nxgep, flow_res);
1637	}
1638	if (insert_hash) {
1639		status = nxge_add_fcram_entry(nxgep, flow_res);
1640	} else {
1641		status = nxge_add_tcam_entry(nxgep, flow_res);
1642	}
1643	return (status);
1644}
1645
1646void
1647nxge_put_tcam(p_nxge_t nxgep, p_mblk_t mp)
1648{
1649	flow_resource_t *fs;
1650
1651	fs = (flow_resource_t *)mp->b_rptr;
1652	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1653	    "nxge_put_tcam addr fs $%p  type %x offset %x",
1654	    fs, fs->flow_spec.flow_type, fs->channel_cookie));
1655	(void) nxge_add_tcam_entry(nxgep, fs);
1656}
1657
1658nxge_status_t
1659nxge_fflp_config_tcam_enable(p_nxge_t nxgep)
1660{
1661	npi_handle_t handle = nxgep->npi_reg_handle;
1662	npi_status_t rs = NPI_SUCCESS;
1663
1664	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_config_tcam_enable"));
1665	rs = npi_fflp_cfg_tcam_enable(handle);
1666	if (rs & NPI_FFLP_ERROR) {
1667		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1668		    " nxge_fflp_config_tcam_enable failed"));
1669		return (NXGE_ERROR | rs);
1670	}
1671	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_fflp_config_tcam_enable"));
1672	return (NXGE_OK);
1673}
1674
1675nxge_status_t
1676nxge_fflp_config_tcam_disable(p_nxge_t nxgep)
1677{
1678	npi_handle_t handle = nxgep->npi_reg_handle;
1679	npi_status_t rs = NPI_SUCCESS;
1680
1681	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1682	    " ==> nxge_fflp_config_tcam_disable"));
1683	rs = npi_fflp_cfg_tcam_disable(handle);
1684	if (rs & NPI_FFLP_ERROR) {
1685		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1686		    " nxge_fflp_config_tcam_disable failed"));
1687		return (NXGE_ERROR | rs);
1688	}
1689	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1690	    " <== nxge_fflp_config_tcam_disable"));
1691	return (NXGE_OK);
1692}
1693
1694nxge_status_t
1695nxge_fflp_config_hash_lookup_enable(p_nxge_t nxgep)
1696{
1697	npi_handle_t handle = nxgep->npi_reg_handle;
1698	npi_status_t rs = NPI_SUCCESS;
1699	p_nxge_dma_pt_cfg_t p_dma_cfgp;
1700	p_nxge_hw_pt_cfg_t p_cfgp;
1701	uint8_t partition;
1702
1703	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1704	    " ==> nxge_fflp_config_hash_lookup_enable"));
1705	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
1706	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
1707
1708	for (partition = 0; partition < NXGE_MAX_RDC_GROUPS; partition++) {
1709		if (p_cfgp->grpids[partition]) {
1710			rs = npi_fflp_cfg_fcram_partition_enable(
1711			    handle, partition);
1712			if (rs != NPI_SUCCESS) {
1713				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1714				    " nxge_fflp_config_hash_lookup_enable"
1715				    "failed FCRAM partition"
1716				    " enable for partition %d ", partition));
1717				return (NXGE_ERROR | rs);
1718			}
1719		}
1720	}
1721
1722	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1723	    " <== nxge_fflp_config_hash_lookup_enable"));
1724	return (NXGE_OK);
1725}
1726
1727nxge_status_t
1728nxge_fflp_config_hash_lookup_disable(p_nxge_t nxgep)
1729{
1730	npi_handle_t handle = nxgep->npi_reg_handle;
1731	npi_status_t rs = NPI_SUCCESS;
1732	p_nxge_dma_pt_cfg_t p_dma_cfgp;
1733	p_nxge_hw_pt_cfg_t p_cfgp;
1734	uint8_t partition;
1735
1736	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1737	    " ==> nxge_fflp_config_hash_lookup_disable"));
1738	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
1739	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
1740
1741	for (partition = 0; partition < NXGE_MAX_RDC_GROUPS; partition++) {
1742		if (p_cfgp->grpids[partition]) {
1743			rs = npi_fflp_cfg_fcram_partition_disable(handle,
1744			    partition);
1745			if (rs != NPI_SUCCESS) {
1746				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1747				    " nxge_fflp_config_hash_lookup_disable"
1748				    " failed FCRAM partition"
1749				    " disable for partition %d ", partition));
1750				return (NXGE_ERROR | rs);
1751			}
1752		}
1753	}
1754
1755	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1756	    " <== nxge_fflp_config_hash_lookup_disable"));
1757	return (NXGE_OK);
1758}
1759
1760nxge_status_t
1761nxge_fflp_config_llc_snap_enable(p_nxge_t nxgep)
1762{
1763	npi_handle_t handle = nxgep->npi_reg_handle;
1764	npi_status_t rs = NPI_SUCCESS;
1765
1766	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1767	    " ==> nxge_fflp_config_llc_snap_enable"));
1768	rs = npi_fflp_cfg_llcsnap_enable(handle);
1769	if (rs & NPI_FFLP_ERROR) {
1770		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1771		    " nxge_fflp_config_llc_snap_enable failed"));
1772		return (NXGE_ERROR | rs);
1773	}
1774	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1775	    " <== nxge_fflp_config_llc_snap_enable"));
1776	return (NXGE_OK);
1777}
1778
1779nxge_status_t
1780nxge_fflp_config_llc_snap_disable(p_nxge_t nxgep)
1781{
1782	npi_handle_t handle = nxgep->npi_reg_handle;
1783	npi_status_t rs = NPI_SUCCESS;
1784
1785	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1786	    " ==> nxge_fflp_config_llc_snap_disable"));
1787	rs = npi_fflp_cfg_llcsnap_disable(handle);
1788	if (rs & NPI_FFLP_ERROR) {
1789		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1790		    " nxge_fflp_config_llc_snap_disable failed"));
1791		return (NXGE_ERROR | rs);
1792	}
1793	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1794	    " <== nxge_fflp_config_llc_snap_disable"));
1795	return (NXGE_OK);
1796}
1797
1798nxge_status_t
1799nxge_fflp_ip_usr_class_config(p_nxge_t nxgep, tcam_class_t class,
1800	uint32_t config)
1801{
1802	npi_status_t rs = NPI_SUCCESS;
1803	npi_handle_t handle = nxgep->npi_reg_handle;
1804	uint8_t tos, tos_mask, proto, ver = 0;
1805	uint8_t class_enable = 0;
1806
1807	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_ip_usr_class_config"));
1808
1809	tos = (config & NXGE_CLASS_CFG_IP_TOS_MASK) >>
1810	    NXGE_CLASS_CFG_IP_TOS_SHIFT;
1811	tos_mask = (config & NXGE_CLASS_CFG_IP_TOS_MASK_MASK) >>
1812	    NXGE_CLASS_CFG_IP_TOS_MASK_SHIFT;
1813	proto = (config & NXGE_CLASS_CFG_IP_PROTO_MASK) >>
1814	    NXGE_CLASS_CFG_IP_PROTO_SHIFT;
1815	if (config & NXGE_CLASS_CFG_IP_IPV6_MASK)
1816		ver = 1;
1817	if (config & NXGE_CLASS_CFG_IP_ENABLE_MASK)
1818		class_enable = 1;
1819	rs = npi_fflp_cfg_ip_usr_cls_set(handle, class, tos, tos_mask,
1820	    proto, ver);
1821	if (rs & NPI_FFLP_ERROR) {
1822		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1823		    " nxge_fflp_ip_usr_class_config"
1824		    " for class %d failed ", class));
1825		return (NXGE_ERROR | rs);
1826	}
1827	if (class_enable)
1828		rs = npi_fflp_cfg_ip_usr_cls_enable(handle, class);
1829	else
1830		rs = npi_fflp_cfg_ip_usr_cls_disable(handle, class);
1831
1832	if (rs & NPI_FFLP_ERROR) {
1833		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1834		    " nxge_fflp_ip_usr_class_config"
1835		    " TCAM enable/disable for class %d failed ", class));
1836		return (NXGE_ERROR | rs);
1837	}
1838	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_usr_class_config"));
1839	return (NXGE_OK);
1840}
1841
1842nxge_status_t
1843nxge_fflp_ip_class_config(p_nxge_t nxgep, tcam_class_t class, uint32_t config)
1844{
1845	uint32_t class_config;
1846	nxge_status_t t_status = NXGE_OK;
1847	nxge_status_t f_status = NXGE_OK;
1848	p_nxge_class_pt_cfg_t p_class_cfgp;
1849
1850	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_ip_class_config"));
1851
1852	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
1853	class_config = p_class_cfgp->class_cfg[class];
1854
1855	if (class_config != config) {
1856		p_class_cfgp->class_cfg[class] = config;
1857		class_config = config;
1858	}
1859
1860	t_status = nxge_cfg_tcam_ip_class(nxgep, class, class_config);
1861	f_status = nxge_cfg_ip_cls_flow_key(nxgep, class, class_config);
1862
1863	if (t_status & NPI_FFLP_ERROR) {
1864		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1865		    " nxge_fflp_ip_class_config %x"
1866		    " for class %d tcam failed", config, class));
1867		return (t_status);
1868	}
1869	if (f_status & NPI_FFLP_ERROR) {
1870		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1871		    " nxge_fflp_ip_class_config %x"
1872		    " for class %d flow key failed", config, class));
1873		return (f_status);
1874	}
1875	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_class_config"));
1876	return (NXGE_OK);
1877}
1878
1879nxge_status_t
1880nxge_fflp_ip_class_config_get(p_nxge_t nxgep, tcam_class_t class,
1881	uint32_t *config)
1882{
1883	uint32_t t_class_config, f_class_config;
1884	int t_status = NXGE_OK;
1885	int f_status = NXGE_OK;
1886
1887	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_ip_class_config"));
1888
1889	t_class_config = f_class_config = 0;
1890	t_status = nxge_cfg_tcam_ip_class_get(nxgep, class, &t_class_config);
1891	f_status = nxge_cfg_ip_cls_flow_key_get(nxgep, class, &f_class_config);
1892
1893	if (t_status & NPI_FFLP_ERROR) {
1894		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1895		    " nxge_fflp_ip_class_config_get  "
1896		    " for class %d tcam failed", class));
1897		return (t_status);
1898	}
1899
1900	if (f_status & NPI_FFLP_ERROR) {
1901		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1902		    " nxge_fflp_ip_class_config_get  "
1903		    " for class %d flow key failed", class));
1904		return (f_status);
1905	}
1906
1907	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1908	    " nxge_fflp_ip_class_config tcam %x flow %x",
1909	    t_class_config, f_class_config));
1910
1911	*config = t_class_config | f_class_config;
1912	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_class_config_get"));
1913	return (NXGE_OK);
1914}
1915
1916nxge_status_t
1917nxge_fflp_ip_class_config_all(p_nxge_t nxgep)
1918{
1919	uint32_t class_config;
1920	tcam_class_t class;
1921
1922#ifdef	NXGE_DEBUG
1923	int status = NXGE_OK;
1924#endif
1925
1926	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_ip_class_config"));
1927	for (class = TCAM_CLASS_TCP_IPV4;
1928	    class <= TCAM_CLASS_SCTP_IPV6; class++) {
1929		class_config = nxgep->class_config.class_cfg[class];
1930#ifndef	NXGE_DEBUG
1931		(void) nxge_fflp_ip_class_config(nxgep, class, class_config);
1932#else
1933		status = nxge_fflp_ip_class_config(nxgep, class, class_config);
1934		if (status & NPI_FFLP_ERROR) {
1935			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1936			    "nxge_fflp_ip_class_config failed "
1937			    " class %d config %x ",
1938			    class, class_config));
1939		}
1940#endif
1941	}
1942	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_class_config"));
1943	return (NXGE_OK);
1944}
1945
1946nxge_status_t
1947nxge_fflp_config_vlan_table(p_nxge_t nxgep, uint16_t vlan_id)
1948{
1949	uint8_t port, rdc_grp;
1950	npi_handle_t handle;
1951	npi_status_t rs = NPI_SUCCESS;
1952	uint8_t priority = 1;
1953	p_nxge_mv_cfg_t vlan_table;
1954	p_nxge_class_pt_cfg_t p_class_cfgp;
1955	p_nxge_hw_list_t hw_p;
1956
1957	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_config_vlan_table"));
1958	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
1959	handle = nxgep->npi_reg_handle;
1960	vlan_table = p_class_cfgp->vlan_tbl;
1961	port = nxgep->function_num;
1962
1963	if (vlan_table[vlan_id].flag == 0) {
1964		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1965		    " nxge_fflp_config_vlan_table"
1966		    " vlan id is not configured %d", vlan_id));
1967		return (NXGE_ERROR);
1968	}
1969
1970	if ((hw_p = nxgep->nxge_hw_p) == NULL) {
1971		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1972		    " nxge_fflp_config_vlan_table:"
1973		    " common hardware not set", nxgep->niu_type));
1974		return (NXGE_ERROR);
1975	}
1976	MUTEX_ENTER(&hw_p->nxge_vlan_lock);
1977	rdc_grp = vlan_table[vlan_id].rdctbl;
1978	rs = npi_fflp_cfg_enet_vlan_table_assoc(handle,
1979	    port, vlan_id,
1980	    rdc_grp, priority);
1981
1982	MUTEX_EXIT(&hw_p->nxge_vlan_lock);
1983	if (rs & NPI_FFLP_ERROR) {
1984		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1985		    "nxge_fflp_config_vlan_table failed "
1986		    " Port %d vlan_id %d rdc_grp %d",
1987		    port, vlan_id, rdc_grp));
1988		return (NXGE_ERROR | rs);
1989	}
1990
1991	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_config_vlan_table"));
1992	return (NXGE_OK);
1993}
1994
1995nxge_status_t
1996nxge_fflp_update_hw(p_nxge_t nxgep)
1997{
1998	nxge_status_t status = NXGE_OK;
1999	p_nxge_param_t pa;
2000	uint64_t cfgd_vlans;
2001	uint64_t *val_ptr;
2002	int i;
2003	int num_macs;
2004	uint8_t alt_mac;
2005	nxge_param_map_t *p_map;
2006	p_nxge_mv_cfg_t vlan_table;
2007	p_nxge_class_pt_cfg_t p_class_cfgp;
2008	p_nxge_dma_pt_cfg_t p_all_cfgp;
2009	p_nxge_hw_pt_cfg_t p_cfgp;
2010
2011	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_update_hw"));
2012
2013	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
2014	p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2015	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
2016
2017	status = nxge_fflp_set_hash1(nxgep, p_class_cfgp->init_h1);
2018	if (status != NXGE_OK) {
2019		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
2020		    "nxge_fflp_set_hash1 Failed"));
2021		return (NXGE_ERROR);
2022	}
2023
2024	status = nxge_fflp_set_hash2(nxgep, p_class_cfgp->init_h2);
2025	if (status != NXGE_OK) {
2026		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
2027		    "nxge_fflp_set_hash2 Failed"));
2028		return (NXGE_ERROR);
2029	}
2030	vlan_table = p_class_cfgp->vlan_tbl;
2031
2032	/* configure vlan tables */
2033	pa = (p_nxge_param_t)&nxgep->param_arr[param_vlan_2rdc_grp];
2034#if defined(__i386)
2035	val_ptr = (uint64_t *)(uint32_t)pa->value;
2036#else
2037	val_ptr = (uint64_t *)pa->value;
2038#endif
2039	cfgd_vlans = ((pa->type & NXGE_PARAM_ARRAY_CNT_MASK) >>
2040	    NXGE_PARAM_ARRAY_CNT_SHIFT);
2041
2042	for (i = 0; i < cfgd_vlans; i++) {
2043		p_map = (nxge_param_map_t *)&val_ptr[i];
2044		if (vlan_table[p_map->param_id].flag) {
2045			status = nxge_fflp_config_vlan_table(nxgep,
2046			    p_map->param_id);
2047			if (status != NXGE_OK) {
2048				NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
2049				    "nxge_fflp_config_vlan_table Failed"));
2050				return (NXGE_ERROR);
2051			}
2052		}
2053	}
2054
2055	/* config MAC addresses */
2056	num_macs = p_cfgp->max_macs;
2057	pa = (p_nxge_param_t)&nxgep->param_arr[param_mac_2rdc_grp];
2058#if defined(__i386)
2059	val_ptr = (uint64_t *)(uint32_t)pa->value;
2060#else
2061	val_ptr = (uint64_t *)pa->value;
2062#endif
2063
2064	for (alt_mac = 0; alt_mac < num_macs; alt_mac++) {
2065		if (p_class_cfgp->mac_host_info[alt_mac].flag) {
2066			status = nxge_logical_mac_assign_rdc_table(nxgep,
2067			    alt_mac);
2068			if (status != NXGE_OK) {
2069				NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
2070				    "nxge_logical_mac_assign_rdc_table"
2071				    " Failed"));
2072				return (NXGE_ERROR);
2073			}
2074		}
2075	}
2076
2077	/* Config Hash values */
2078	/* config classes */
2079	status = nxge_fflp_ip_class_config_all(nxgep);
2080	if (status != NXGE_OK) {
2081		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2082		    "nxge_fflp_ip_class_config_all Failed"));
2083		return (NXGE_ERROR);
2084	}
2085	return (NXGE_OK);
2086}
2087
2088nxge_status_t
2089nxge_classify_init_hw(p_nxge_t nxgep)
2090{
2091	nxge_status_t status = NXGE_OK;
2092
2093	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_classify_init_hw"));
2094
2095	if (nxgep->classifier.state & NXGE_FFLP_HW_INIT) {
2096		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
2097		    "nxge_classify_init_hw already init"));
2098		return (NXGE_OK);
2099	}
2100
2101	/* Now do a real configuration */
2102	status = nxge_fflp_update_hw(nxgep);
2103	if (status != NXGE_OK) {
2104		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2105		    "nxge_fflp_update_hw failed"));
2106		return (NXGE_ERROR);
2107	}
2108
2109	/* Init RDC tables? ? who should do that? rxdma or fflp ? */
2110	/* attach rdc table to the MAC port. */
2111	status = nxge_main_mac_assign_rdc_table(nxgep);
2112	if (status != NXGE_OK) {
2113		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2114		    "nxge_main_mac_assign_rdc_table failed"));
2115		return (NXGE_ERROR);
2116	}
2117
2118	status = nxge_alt_mcast_mac_assign_rdc_table(nxgep);
2119	if (status != NXGE_OK) {
2120		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2121		    "nxge_multicast_mac_assign_rdc_table failed"));
2122		return (NXGE_ERROR);
2123	}
2124
2125	if (nxgep->classifier.fragment_bug == 1) {
2126		status = nxge_tcam_handle_ip_fragment(nxgep);
2127		if (status != NXGE_OK) {
2128			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2129			    "nxge_tcam_handle_ip_fragment failed"));
2130			return (NXGE_ERROR);
2131		}
2132	}
2133
2134	nxgep->classifier.state |= NXGE_FFLP_HW_INIT;
2135	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_classify_init_hw"));
2136	return (NXGE_OK);
2137}
2138
2139nxge_status_t
2140nxge_fflp_handle_sys_errors(p_nxge_t nxgep)
2141{
2142	npi_handle_t handle;
2143	p_nxge_fflp_stats_t statsp;
2144	uint8_t portn, rdc_grp;
2145	p_nxge_dma_pt_cfg_t p_dma_cfgp;
2146	p_nxge_hw_pt_cfg_t p_cfgp;
2147	vlan_par_err_t vlan_err;
2148	tcam_err_t tcam_err;
2149	hash_lookup_err_log1_t fcram1_err;
2150	hash_lookup_err_log2_t fcram2_err;
2151	hash_tbl_data_log_t fcram_err;
2152
2153	handle = nxgep->npi_handle;
2154	statsp = (p_nxge_fflp_stats_t)&nxgep->statsp->fflp_stats;
2155	portn = nxgep->mac.portnum;
2156
2157	/*
2158	 * need to read the fflp error registers to figure out what the error
2159	 * is
2160	 */
2161	npi_fflp_vlan_error_get(handle, &vlan_err);
2162	npi_fflp_tcam_error_get(handle, &tcam_err);
2163
2164	if (vlan_err.bits.ldw.m_err || vlan_err.bits.ldw.err) {
2165		NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2166		    " vlan table parity error on port %d"
2167		    " addr: 0x%x data: 0x%x",
2168		    portn, vlan_err.bits.ldw.addr,
2169		    vlan_err.bits.ldw.data));
2170		statsp->vlan_parity_err++;
2171
2172		if (vlan_err.bits.ldw.m_err) {
2173			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2174			    " vlan table multiple errors on port %d",
2175			    portn));
2176		}
2177		statsp->errlog.vlan = (uint32_t)vlan_err.value;
2178		NXGE_FM_REPORT_ERROR(nxgep, 0, 0,
2179		    NXGE_FM_EREPORT_FFLP_VLAN_PAR_ERR);
2180		npi_fflp_vlan_error_clear(handle);
2181	}
2182
2183	if (tcam_err.bits.ldw.err) {
2184		if (tcam_err.bits.ldw.p_ecc != 0) {
2185			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2186			    " TCAM ECC error on port %d"
2187			    " TCAM entry: 0x%x syndrome: 0x%x",
2188			    portn, tcam_err.bits.ldw.addr,
2189			    tcam_err.bits.ldw.syndrome));
2190			statsp->tcam_ecc_err++;
2191		} else {
2192			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2193			    " TCAM Parity error on port %d"
2194			    " addr: 0x%x parity value: 0x%x",
2195			    portn, tcam_err.bits.ldw.addr,
2196			    tcam_err.bits.ldw.syndrome));
2197			statsp->tcam_parity_err++;
2198		}
2199
2200		if (tcam_err.bits.ldw.mult) {
2201			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2202			    " TCAM Multiple errors on port %d", portn));
2203		} else {
2204			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2205			    " TCAM PIO error on port %d", portn));
2206		}
2207
2208		statsp->errlog.tcam = (uint32_t)tcam_err.value;
2209		NXGE_FM_REPORT_ERROR(nxgep, 0, 0,
2210		    NXGE_FM_EREPORT_FFLP_TCAM_ERR);
2211		npi_fflp_tcam_error_clear(handle);
2212	}
2213
2214	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2215	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
2216
2217	for (rdc_grp = 0; rdc_grp < NXGE_MAX_RDC_GROUPS; rdc_grp++) {
2218		if (p_cfgp->grpids[rdc_grp]) {
2219			npi_fflp_fcram_error_get(handle, &fcram_err, rdc_grp);
2220			if (fcram_err.bits.ldw.pio_err) {
2221				NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2222				    " FCRAM PIO ECC error on port %d"
2223				    " rdc group: %d Hash Table addr: 0x%x"
2224				    " syndrome: 0x%x",
2225				    portn, rdc_grp,
2226				    fcram_err.bits.ldw.fcram_addr,
2227				    fcram_err.bits.ldw.syndrome));
2228				statsp->hash_pio_err[rdc_grp]++;
2229				statsp->errlog.hash_pio[rdc_grp] =
2230				    (uint32_t)fcram_err.value;
2231				NXGE_FM_REPORT_ERROR(nxgep, 0, 0,
2232				    NXGE_FM_EREPORT_FFLP_HASHT_DATA_ERR);
2233				npi_fflp_fcram_error_clear(handle, rdc_grp);
2234			}
2235		}
2236	}
2237
2238	npi_fflp_fcram_error_log1_get(handle, &fcram1_err);
2239	if (fcram1_err.bits.ldw.ecc_err) {
2240		char *multi_str = "";
2241		char *multi_bit_str = "";
2242
2243		npi_fflp_fcram_error_log2_get(handle, &fcram2_err);
2244		if (fcram1_err.bits.ldw.mult_lk) {
2245			multi_str = "multiple";
2246		}
2247		if (fcram1_err.bits.ldw.mult_bit) {
2248			multi_bit_str = "multiple bits";
2249		}
2250		statsp->hash_lookup_err++;
2251		NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2252		    " FCRAM %s lookup %s ECC error on port %d"
2253		    " H1: 0x%x Subarea: 0x%x Syndrome: 0x%x",
2254		    multi_str, multi_bit_str, portn,
2255		    fcram2_err.bits.ldw.h1,
2256		    fcram2_err.bits.ldw.subarea,
2257		    fcram2_err.bits.ldw.syndrome));
2258		NXGE_FM_REPORT_ERROR(nxgep, 0, 0,
2259		    NXGE_FM_EREPORT_FFLP_HASHT_LOOKUP_ERR);
2260	}
2261	statsp->errlog.hash_lookup1 = (uint32_t)fcram1_err.value;
2262	statsp->errlog.hash_lookup2 = (uint32_t)fcram2_err.value;
2263	return (NXGE_OK);
2264}
2265
2266int
2267nxge_get_valid_tcam_cnt(p_nxge_t nxgep) {
2268	return ((nxgep->classifier.fragment_bug == 1) ?
2269		nxgep->classifier.tcam_entry_cnt - 1 :
2270		nxgep->classifier.tcam_entry_cnt);
2271}
2272
2273int
2274nxge_rxdma_channel_cnt(p_nxge_t nxgep)
2275{
2276	p_nxge_dma_pt_cfg_t p_dma_cfgp;
2277	p_nxge_hw_pt_cfg_t p_cfgp;
2278
2279	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2280	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
2281	return (p_cfgp->max_rdcs);
2282}
2283
2284/* ARGSUSED */
2285int
2286nxge_rxclass_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp)
2287{
2288	uint32_t cmd;
2289	rx_class_cfg_t *cfg_info = (rx_class_cfg_t *)mp->b_rptr;
2290
2291	if (nxgep == NULL) {
2292		return (-1);
2293	}
2294	cmd = cfg_info->cmd;
2295	switch (cmd) {
2296	default:
2297		return (-1);
2298
2299	case NXGE_RX_CLASS_GCHAN:
2300		cfg_info->data = nxge_rxdma_channel_cnt(nxgep);
2301		break;
2302	case NXGE_RX_CLASS_GRULE_CNT:
2303		MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_tcam_lock);
2304		cfg_info->rule_cnt = nxge_get_valid_tcam_cnt(nxgep);
2305		MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_tcam_lock);
2306		break;
2307	case NXGE_RX_CLASS_GRULE:
2308		nxge_get_tcam_entry(nxgep, &cfg_info->fs);
2309		break;
2310	case NXGE_RX_CLASS_GRULE_ALL:
2311		nxge_get_tcam_entry_all(nxgep, cfg_info);
2312		break;
2313	case NXGE_RX_CLASS_RULE_DEL:
2314		nxge_del_tcam_entry(nxgep, cfg_info->fs.location);
2315		break;
2316	case NXGE_RX_CLASS_RULE_INS:
2317		(void) nxge_add_tcam_entry(nxgep, &cfg_info->fs);
2318		break;
2319	}
2320	return (0);
2321}
2322/* ARGSUSED */
2323int
2324nxge_rxhash_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp)
2325{
2326	uint32_t cmd;
2327	cfg_cmd_t	*cfg_info = (cfg_cmd_t *)mp->b_rptr;
2328
2329	if (nxgep == NULL) {
2330		return (-1);
2331	}
2332	cmd = cfg_info->cmd;
2333
2334	switch (cmd) {
2335	default:
2336		return (-1);
2337	case NXGE_IPTUN_CFG_ADD_CLS:
2338		nxge_add_iptun_class(nxgep, &cfg_info->iptun_cfg,
2339		    &cfg_info->class_id);
2340		break;
2341	case NXGE_IPTUN_CFG_SET_HASH:
2342		nxge_cfg_iptun_hash(nxgep, &cfg_info->iptun_cfg,
2343		    cfg_info->class_id);
2344		break;
2345	case NXGE_IPTUN_CFG_DEL_CLS:
2346		nxge_del_iptun_class(nxgep, cfg_info->class_id);
2347		break;
2348	case NXGE_IPTUN_CFG_GET_CLS:
2349		nxge_get_iptun_class(nxgep, &cfg_info->iptun_cfg,
2350		    cfg_info->class_id);
2351		break;
2352	case NXGE_CLS_CFG_SET_SYM:
2353		nxge_set_ip_cls_sym(nxgep, cfg_info->class_id, cfg_info->sym);
2354		break;
2355	case NXGE_CLS_CFG_GET_SYM:
2356		nxge_get_ip_cls_sym(nxgep, cfg_info->class_id, &cfg_info->sym);
2357		break;
2358	}
2359	return (0);
2360}
2361
2362void
2363nxge_get_tcam_entry_all(p_nxge_t nxgep, rx_class_cfg_t *cfgp)
2364{
2365	nxge_classify_t *clasp = &nxgep->classifier;
2366	uint16_t	n_entries;
2367	int		i, j, k;
2368	tcam_flow_spec_t	*tcam_entryp;
2369
2370	cfgp->data = clasp->tcam_size;
2371	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_tcam_lock);
2372	n_entries = cfgp->rule_cnt;
2373
2374	for (i = 0, j = 0; j < cfgp->data; j++) {
2375		k = nxge_tcam_get_index(nxgep, j);
2376		tcam_entryp = &clasp->tcam_entries[k];
2377		if (tcam_entryp->valid != 1)
2378			continue;
2379		cfgp->rule_locs[i] = j;
2380		i++;
2381	};
2382	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_tcam_lock);
2383
2384	if (n_entries != i) {
2385		/* print warning, this should not happen */
2386		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_get_tcam_entry_all"
2387		    "n_entries[%d] != i[%d]!!!", n_entries, i));
2388	}
2389}
2390
2391
2392/* Entries for the ports are interleaved in the TCAM */
2393static uint16_t
2394nxge_tcam_get_index(p_nxge_t nxgep, uint16_t index)
2395{
2396	/* One entry reserved for IP fragment rule */
2397	if (index >= (nxgep->classifier.tcam_size - 1))
2398		index = 0;
2399	if (nxgep->classifier.fragment_bug == 1)
2400		index++;
2401	return (nxgep->classifier.tcam_top + (index * nxgep->nports));
2402}
2403
2404static uint32_t
2405nxge_tcam_cls_to_flow(uint32_t class_code) {
2406	switch (class_code) {
2407	case TCAM_CLASS_TCP_IPV4:
2408		return (FSPEC_TCPIP4);
2409	case TCAM_CLASS_UDP_IPV4:
2410		return (FSPEC_UDPIP4);
2411	case TCAM_CLASS_AH_ESP_IPV4:
2412		return (FSPEC_AHIP4);
2413	case TCAM_CLASS_SCTP_IPV4:
2414		return (FSPEC_SCTPIP4);
2415	case  TCAM_CLASS_TCP_IPV6:
2416		return (FSPEC_TCPIP6);
2417	case TCAM_CLASS_UDP_IPV6:
2418		return (FSPEC_UDPIP6);
2419	case TCAM_CLASS_AH_ESP_IPV6:
2420		return (FSPEC_AHIP6);
2421	case TCAM_CLASS_SCTP_IPV6:
2422		return (FSPEC_SCTPIP6);
2423	case TCAM_CLASS_IP_USER_4:
2424	case TCAM_CLASS_IP_USER_5:
2425	case TCAM_CLASS_IP_USER_6:
2426	case TCAM_CLASS_IP_USER_7:
2427		return (FSPEC_IP_USR);
2428	default:
2429		NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, "nxge_tcam_cls_to_flow"
2430		    ": Unknown class code [0x%x]", class_code));
2431		break;
2432	}
2433	return (0);
2434}
2435
2436void
2437nxge_get_tcam_entry(p_nxge_t nxgep, flow_resource_t *fs)
2438{
2439	uint16_t 	index;
2440	tcam_flow_spec_t *tcam_ep;
2441	tcam_entry_t	*tp;
2442	flow_spec_t	*fspec;
2443	tcpip4_spec_t 	*fspec_key;
2444	tcpip4_spec_t 	*fspec_mask;
2445
2446	index = nxge_tcam_get_index(nxgep, (uint16_t)fs->location);
2447	tcam_ep = &nxgep->classifier.tcam_entries[index];
2448	if (tcam_ep->valid != 1) {
2449		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_get_tcam_entry: :"
2450		    "Entry [%d] invalid for index [%d]", fs->location, index));
2451		return;
2452	}
2453
2454	/* Fill the flow spec entry */
2455	tp = &tcam_ep->tce;
2456	fspec = &fs->flow_spec;
2457	fspec->flow_type = nxge_tcam_cls_to_flow(tp->ip4_class_key);
2458
2459	/* TODO - look at proto field to differentiate between AH and ESP */
2460	if (fspec->flow_type == FSPEC_AHIP4) {
2461		if (tp->ip4_proto_key == IPPROTO_ESP)
2462			fspec->flow_type = FSPEC_ESPIP4;
2463	}
2464
2465	switch (tp->ip4_class_key) {
2466	case TCAM_CLASS_TCP_IPV4:
2467	case TCAM_CLASS_UDP_IPV4:
2468	case TCAM_CLASS_AH_ESP_IPV4:
2469	case TCAM_CLASS_SCTP_IPV4:
2470		fspec_key = (tcpip4_spec_t *)&fspec->uh.tcpip4spec;
2471		fspec_mask = (tcpip4_spec_t *)&fspec->um.tcpip4spec;
2472		FSPEC_IPV4_ADDR(fspec_key->ip4dst, tp->ip4_dest_key);
2473		FSPEC_IPV4_ADDR(fspec_mask->ip4dst, tp->ip4_dest_mask);
2474		FSPEC_IPV4_ADDR(fspec_key->ip4src, tp->ip4_src_key);
2475		FSPEC_IPV4_ADDR(fspec_mask->ip4src, tp->ip4_src_mask);
2476		fspec_key->tos = tp->ip4_tos_key;
2477		fspec_mask->tos = tp->ip4_tos_mask;
2478		break;
2479	default:
2480		break;
2481	}
2482
2483	switch (tp->ip4_class_key) {
2484	case TCAM_CLASS_TCP_IPV4:
2485	case TCAM_CLASS_UDP_IPV4:
2486	case TCAM_CLASS_SCTP_IPV4:
2487		FSPEC_IP_PORTS(fspec_key->pdst, fspec_key->psrc,
2488		    tp->ip4_port_key);
2489		FSPEC_IP_PORTS(fspec_mask->pdst, fspec_mask->psrc,
2490		    tp->ip4_port_mask);
2491		break;
2492	case TCAM_CLASS_AH_ESP_IPV4:
2493		fspec->uh.ahip4spec.spi = tp->ip4_port_key;
2494		fspec->um.ahip4spec.spi = tp->ip4_port_mask;
2495		break;
2496	case TCAM_CLASS_IP_USER_4:
2497	case TCAM_CLASS_IP_USER_5:
2498	case TCAM_CLASS_IP_USER_6:
2499	case TCAM_CLASS_IP_USER_7:
2500		fspec->uh.ip_usr_spec.l4_4_bytes = tp->ip4_port_key;
2501		fspec->um.ip_usr_spec.l4_4_bytes = tp->ip4_port_mask;
2502		fspec->uh.ip_usr_spec.ip_ver = FSPEC_IP4;
2503		fspec->uh.ip_usr_spec.proto = tp->ip4_proto_key;
2504		fspec->um.ip_usr_spec.proto = tp->ip4_proto_mask;
2505		break;
2506	default:
2507		break;
2508	}
2509
2510	if (tp->match_action.bits.ldw.disc == 1) {
2511		fs->channel_cookie = NXGE_PKT_DISCARD;
2512	} else {
2513		fs->channel_cookie = tp->match_action.bits.ldw.offset;
2514	}
2515}
2516
2517void
2518nxge_del_tcam_entry(p_nxge_t nxgep, uint32_t location)
2519{
2520	npi_status_t rs = NPI_SUCCESS;
2521	uint16_t 	index;
2522	tcam_flow_spec_t *tcam_ep;
2523	tcam_entry_t	*tp;
2524	tcam_class_t	class;
2525
2526	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_tcam_lock);
2527	index = nxge_tcam_get_index(nxgep, (uint16_t)location);
2528	tcam_ep = &nxgep->classifier.tcam_entries[index];
2529	if (tcam_ep->valid != 1) {
2530		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_tcam_entry: :"
2531		    "Entry [%d] invalid for index [%d]", location, index));
2532		goto fail;
2533	}
2534
2535	/* Fill the flow spec entry */
2536	tp = &tcam_ep->tce;
2537	class = tp->ip4_class_key;
2538	if (class >= TCAM_CLASS_IP_USER_4 && class <= TCAM_CLASS_IP_USER_7) {
2539		int i;
2540		nxge_usr_l3_cls_t *l3_ucls_p;
2541		p_nxge_hw_list_t hw_p = nxgep->nxge_hw_p;
2542
2543		for (i = 0; i < NXGE_L3_PROG_CLS; i++) {
2544			l3_ucls_p = &hw_p->tcam_l3_prog_cls[i];
2545			if (l3_ucls_p->valid) {
2546				if (l3_ucls_p->cls == class &&
2547				    l3_ucls_p->tcam_ref_cnt) {
2548					l3_ucls_p->tcam_ref_cnt--;
2549					if (l3_ucls_p->tcam_ref_cnt > 0)
2550						continue;
2551					/* disable class */
2552					rs = npi_fflp_cfg_ip_usr_cls_disable(
2553					    nxgep->npi_reg_handle,
2554					    (tcam_class_t)class);
2555					if (rs != NPI_SUCCESS)
2556						goto fail;
2557					l3_ucls_p->cls = 0;
2558					l3_ucls_p->pid = 0;
2559					l3_ucls_p->valid = 0;
2560					break;
2561				}
2562			}
2563		}
2564		if (i == NXGE_L3_PROG_CLS) {
2565			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2566			    "nxge_del_tcam_entry: Usr class "
2567			    "0x%llx not found", (unsigned long long) class));
2568			goto fail;
2569		}
2570	}
2571
2572	rs = npi_fflp_tcam_entry_invalidate(nxgep->npi_reg_handle, index);
2573	if (rs != NPI_SUCCESS) {
2574		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2575		    "nxge_del_tcam_entry: TCAM invalidate failed "
2576		    "at loc %d ", location));
2577		goto fail;
2578	}
2579
2580	nxgep->classifier.tcam_entries[index].valid = 0;
2581	nxgep->classifier.tcam_entry_cnt--;
2582
2583	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_tcam_lock);
2584	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_del_tcam_entry"));
2585	return;
2586fail:
2587	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_tcam_lock);
2588	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2589	    "<== nxge_del_tcam_entry FAILED"));
2590}
2591
2592static uint8_t
2593nxge_iptun_pkt_type_to_pid(uint8_t pkt_type)
2594{
2595	uint8_t pid = 0;
2596
2597	switch (pkt_type) {
2598	case IPTUN_PKT_IPV4:
2599		pid = 4;
2600		break;
2601	case IPTUN_PKT_IPV6:
2602		pid = 41;
2603		break;
2604	case IPTUN_PKT_GRE:
2605		pid = 47;
2606		break;
2607	case IPTUN_PKT_GTP:
2608		pid = 17;
2609		break;
2610	default:
2611		NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL,
2612		    "nxge_iptun_pkt_type_to_pid: Unknown pkt type 0x%x",
2613		    pkt_type));
2614		break;
2615	}
2616
2617	return (pid);
2618}
2619
2620static npi_status_t
2621nxge_set_iptun_usr_cls_reg(p_nxge_t nxgep, uint64_t class,
2622		iptun_cfg_t *iptunp)
2623{
2624	npi_handle_t handle = nxgep->npi_reg_handle;
2625	npi_status_t rs = NPI_SUCCESS;
2626
2627	switch (iptunp->in_pkt_type) {
2628	case IPTUN_PKT_IPV4:
2629	case IPTUN_PKT_IPV6:
2630		rs = npi_fflp_cfg_ip_usr_cls_set_iptun(handle,
2631		    (tcam_class_t)class, 0, 0, 0, 0);
2632		break;
2633	case IPTUN_PKT_GRE:
2634		rs = npi_fflp_cfg_ip_usr_cls_set_iptun(handle,
2635		    (tcam_class_t)class, iptunp->l4b0_val,
2636		    iptunp->l4b0_mask, 0, 0);
2637		break;
2638	case IPTUN_PKT_GTP:
2639		rs = npi_fflp_cfg_ip_usr_cls_set_iptun(handle,
2640		    (tcam_class_t)class, 0, 0, iptunp->l4b23_val,
2641		    (iptunp->l4b23_sel & 0x01));
2642		break;
2643	default:
2644		rs = NPI_FFLP_TCAM_CLASS_INVALID;
2645		break;
2646	}
2647	return (rs);
2648}
2649
2650void
2651nxge_add_iptun_class(p_nxge_t nxgep, iptun_cfg_t *iptunp,
2652		uint8_t *cls_idp)
2653{
2654	int i, add_cls;
2655	uint8_t pid;
2656	uint64_t class;
2657	p_nxge_hw_list_t hw_p = nxgep->nxge_hw_p;
2658	npi_handle_t handle = nxgep->npi_reg_handle;
2659	npi_status_t rs = NPI_SUCCESS;
2660
2661	pid = nxge_iptun_pkt_type_to_pid(iptunp->in_pkt_type);
2662	if (pid == 0)
2663		return;
2664
2665	add_cls = 0;
2666	MUTEX_ENTER(&hw_p->nxge_tcam_lock);
2667
2668	/* Get an user programmable class ID */
2669	for (i = 0; i < NXGE_L3_PROG_CLS; i++) {
2670		if (hw_p->tcam_l3_prog_cls[i].valid == 0) {
2671			/* todo add new usr class reg */
2672			switch (i) {
2673			case 0:
2674				class = TCAM_CLASS_IP_USER_4;
2675				break;
2676			case 1:
2677				class = TCAM_CLASS_IP_USER_5;
2678				break;
2679			case 2:
2680				class = TCAM_CLASS_IP_USER_6;
2681				break;
2682			case 3:
2683				class = TCAM_CLASS_IP_USER_7;
2684				break;
2685			default:
2686				break;
2687			}
2688			rs = npi_fflp_cfg_ip_usr_cls_set(handle,
2689			    (tcam_class_t)class, 0, 0, pid, 0);
2690			if (rs != NPI_SUCCESS)
2691				goto fail;
2692
2693			rs = nxge_set_iptun_usr_cls_reg(nxgep, class, iptunp);
2694
2695			if (rs != NPI_SUCCESS)
2696				goto fail;
2697
2698			rs = npi_fflp_cfg_ip_usr_cls_enable(handle,
2699			    (tcam_class_t)class);
2700			if (rs != NPI_SUCCESS)
2701				goto fail;
2702
2703			hw_p->tcam_l3_prog_cls[i].cls = class;
2704			hw_p->tcam_l3_prog_cls[i].pid = pid;
2705			hw_p->tcam_l3_prog_cls[i].flow_pkt_type =
2706			    iptunp->in_pkt_type;
2707			hw_p->tcam_l3_prog_cls[i].valid = 1;
2708			*cls_idp = (uint8_t)class;
2709			add_cls = 1;
2710			break;
2711		} else if (hw_p->tcam_l3_prog_cls[i].pid == pid) {
2712			if (hw_p->tcam_l3_prog_cls[i].flow_pkt_type == 0) {
2713				/* there is no flow key */
2714				/* todo program the existing usr class reg */
2715
2716				rs = nxge_set_iptun_usr_cls_reg(nxgep, class,
2717				    iptunp);
2718				if (rs != NPI_SUCCESS)
2719					goto fail;
2720
2721				rs = npi_fflp_cfg_ip_usr_cls_enable(handle,
2722				    (tcam_class_t)class);
2723				if (rs != NPI_SUCCESS)
2724					goto fail;
2725
2726				hw_p->tcam_l3_prog_cls[i].flow_pkt_type =
2727				    iptunp->in_pkt_type;
2728				*cls_idp = (uint8_t)class;
2729				add_cls = 1;
2730			} else {
2731				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2732				    "nxge_add_iptun_class: L3 usr "
2733				    "programmable class with pid %d "
2734				    "already exists", pid));
2735			}
2736			break;
2737		}
2738	}
2739	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
2740
2741	if (add_cls != 1) {
2742		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2743		    "nxge_add_iptun_class: Could not add IP tunneling class"));
2744	}
2745	return;
2746fail:
2747	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
2748	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_iptun_class: FAILED"));
2749}
2750
2751static boolean_t
2752nxge_is_iptun_cls_present(p_nxge_t nxgep, uint8_t cls_id, int *idx)
2753{
2754	int i;
2755	p_nxge_hw_list_t hw_p = nxgep->nxge_hw_p;
2756
2757	MUTEX_ENTER(&hw_p->nxge_tcam_lock);
2758	for (i = 0; i < NXGE_L3_PROG_CLS; i++) {
2759		if (hw_p->tcam_l3_prog_cls[i].valid &&
2760		    hw_p->tcam_l3_prog_cls[i].flow_pkt_type != 0) {
2761			if (hw_p->tcam_l3_prog_cls[i].cls == cls_id)
2762				break;
2763		}
2764	}
2765	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
2766
2767	if (i == NXGE_L3_PROG_CLS) {
2768		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2769		    "nxge_is_iptun_cls_present: Invalid class %d", cls_id));
2770		return (B_FALSE);
2771	} else {
2772		*idx = i;
2773		return (B_TRUE);
2774	}
2775}
2776
2777void
2778nxge_cfg_iptun_hash(p_nxge_t nxgep, iptun_cfg_t *iptunp, uint8_t cls_id)
2779{
2780	int idx;
2781	npi_handle_t handle = nxgep->npi_reg_handle;
2782	flow_key_cfg_t cfg;
2783
2784	/* check to see that this is a valid class ID */
2785	if (!nxge_is_iptun_cls_present(nxgep, cls_id, &idx)) {
2786		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2787		    "nxge_cfg_iptun_hash: nxge_is_iptun_cls_present "
2788		    "failed for cls_id %d", cls_id));
2789		return;
2790	}
2791
2792	bzero((void *)&cfg, sizeof (flow_key_cfg_t));
2793
2794	/*
2795	 * This ensures that all 4 bytes of the XOR value are loaded to the
2796	 * hash key.
2797	 */
2798	cfg.use_dport = cfg.use_sport = cfg.ip_opts_exist = 1;
2799
2800	cfg.l4_xor_sel = (iptunp->l4xor_sel & FL_KEY_USR_L4XOR_MSK);
2801	cfg.use_l4_md = 1;
2802
2803	if (iptunp->hash_flags & HASH_L3PROTO)
2804		cfg.use_proto = 1;
2805	else if (iptunp->hash_flags & HASH_IPDA)
2806		cfg.use_daddr = 1;
2807	else if (iptunp->hash_flags & HASH_IPSA)
2808		cfg.use_saddr = 1;
2809	else if (iptunp->hash_flags & HASH_VLAN)
2810		cfg.use_vlan = 1;
2811	else if (iptunp->hash_flags & HASH_L2DA)
2812		cfg.use_l2da = 1;
2813	else if (iptunp->hash_flags & HASH_IFPORT)
2814		cfg.use_portnum = 1;
2815
2816	(void) npi_fflp_cfg_ip_cls_flow_key_rfnl(handle, (tcam_class_t)cls_id,
2817	    &cfg);
2818}
2819
2820void
2821nxge_del_iptun_class(p_nxge_t nxgep, uint8_t cls_id)
2822{
2823	int i;
2824	npi_handle_t handle = nxgep->npi_reg_handle;
2825	npi_status_t rs = NPI_SUCCESS;
2826
2827
2828	/* check to see that this is a valid class ID */
2829	if (!nxge_is_iptun_cls_present(nxgep, cls_id, &i)) {
2830		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2831		    "nxge_del_iptun_class: Invalid class ID 0x%x", cls_id));
2832		return;
2833	}
2834
2835	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_tcam_lock);
2836	rs = npi_fflp_cfg_ip_usr_cls_disable(handle, (tcam_class_t)cls_id);
2837	if (rs != NPI_SUCCESS)
2838		goto fail;
2839	nxgep->nxge_hw_p->tcam_l3_prog_cls[i].flow_pkt_type = 0;
2840	if (nxgep->nxge_hw_p->tcam_l3_prog_cls[i].tcam_ref_cnt == 0)
2841		nxgep->nxge_hw_p->tcam_l3_prog_cls[i].valid = 0;
2842
2843	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_tcam_lock);
2844	return;
2845fail:
2846	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_tcam_lock);
2847	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_iptun_class: FAILED"));
2848}
2849
2850void
2851nxge_get_iptun_class(p_nxge_t nxgep, iptun_cfg_t *iptunp, uint8_t cls_id)
2852{
2853	int i;
2854	uint8_t pid;
2855	npi_handle_t handle = nxgep->npi_reg_handle;
2856	npi_status_t rs = NPI_SUCCESS;
2857	flow_key_cfg_t cfg;
2858
2859
2860	/* check to see that this is a valid class ID */
2861	if (!nxge_is_iptun_cls_present(nxgep, cls_id, &i))
2862		return;
2863
2864	bzero((void *)iptunp, sizeof (iptun_cfg_t));
2865
2866	pid = nxgep->nxge_hw_p->tcam_l3_prog_cls[i].pid;
2867
2868	rs = npi_fflp_cfg_ip_usr_cls_get_iptun(handle, (tcam_class_t)cls_id,
2869	    &iptunp->l4b0_val, &iptunp->l4b0_mask, &iptunp->l4b23_val,
2870	    &iptunp->l4b23_sel);
2871	if (rs != NPI_SUCCESS)
2872		goto fail;
2873
2874	rs = npi_fflp_cfg_ip_cls_flow_key_get_rfnl(handle,
2875	    (tcam_class_t)cls_id, &cfg);
2876	if (rs != NPI_SUCCESS)
2877		goto fail;
2878
2879	iptunp->l4xor_sel = cfg.l4_xor_sel;
2880	if (cfg.use_proto)
2881		iptunp->hash_flags |= HASH_L3PROTO;
2882	else if (cfg.use_daddr)
2883		iptunp->hash_flags |= HASH_IPDA;
2884	else if (cfg.use_saddr)
2885		iptunp->hash_flags |= HASH_IPSA;
2886	else if (cfg.use_vlan)
2887		iptunp->hash_flags |= HASH_VLAN;
2888	else if (cfg.use_l2da)
2889		iptunp->hash_flags |= HASH_L2DA;
2890	else if (cfg.use_portnum)
2891		iptunp->hash_flags |= HASH_IFPORT;
2892
2893	switch (pid) {
2894	case 4:
2895		iptunp->in_pkt_type = IPTUN_PKT_IPV4;
2896		break;
2897	case 41:
2898		iptunp->in_pkt_type = IPTUN_PKT_IPV6;
2899		break;
2900	case 47:
2901		iptunp->in_pkt_type = IPTUN_PKT_GRE;
2902		break;
2903	case 17:
2904		iptunp->in_pkt_type = IPTUN_PKT_GTP;
2905		break;
2906	default:
2907		iptunp->in_pkt_type = 0;
2908		break;
2909	}
2910
2911	return;
2912fail:
2913	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_get_iptun_class: FAILED"));
2914}
2915
2916void
2917nxge_set_ip_cls_sym(p_nxge_t nxgep, uint8_t cls_id, uint8_t sym)
2918{
2919	npi_handle_t handle = nxgep->npi_reg_handle;
2920	npi_status_t rs = NPI_SUCCESS;
2921	boolean_t sym_en = (sym == 1) ? B_TRUE : B_FALSE;
2922
2923	rs = npi_fflp_cfg_sym_ip_cls_flow_key(handle, (tcam_class_t)cls_id,
2924	    sym_en);
2925	if (rs != NPI_SUCCESS)
2926		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2927		    "nxge_set_ip_cls_sym: FAILED"));
2928}
2929
2930void
2931nxge_get_ip_cls_sym(p_nxge_t nxgep, uint8_t cls_id, uint8_t *sym)
2932{
2933	npi_handle_t handle = nxgep->npi_reg_handle;
2934	npi_status_t rs = NPI_SUCCESS;
2935	flow_key_cfg_t cfg;
2936
2937	rs = npi_fflp_cfg_ip_cls_flow_key_get_rfnl(handle,
2938	    (tcam_class_t)cls_id, &cfg);
2939	if (rs != NPI_SUCCESS)
2940		goto fail;
2941
2942	if (cfg.use_sym)
2943		*sym = 1;
2944	else
2945		*sym = 0;
2946	return;
2947fail:
2948	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_get_ip_cls_sym: FAILED"));
2949}
2950