xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_fflp.c (revision 14ea4bb737263733ad80a36b4f73f681c30a6b45)
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  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <npi_fflp.h>
30 #include <npi_mac.h>
31 #include <nxge_defs.h>
32 #include <nxge_flow.h>
33 #include <nxge_fflp.h>
34 #include <nxge_impl.h>
35 #include <nxge_fflp_hash.h>
36 #include <nxge_common.h>
37 
38 
39 /* function prototypes  */
40 
41 static nxge_status_t nxge_fflp_vlan_tbl_clear_all(p_nxge_t);
42 static nxge_status_t nxge_fflp_tcam_invalidate_all(p_nxge_t);
43 static nxge_status_t nxge_fflp_tcam_init(p_nxge_t);
44 static nxge_status_t nxge_fflp_fcram_invalidate_all(p_nxge_t);
45 static nxge_status_t nxge_fflp_fcram_init(p_nxge_t);
46 static int nxge_flow_need_hash_lookup(p_nxge_t, flow_resource_t *);
47 
48 static void nxge_fill_tcam_entry_tcp(p_nxge_t, flow_spec_t *,
49 				    tcam_entry_t *);
50 static void nxge_fill_tcam_entry_udp(p_nxge_t,
51 					    flow_spec_t *,
52 					    tcam_entry_t *);
53 static void nxge_fill_tcam_entry_sctp(p_nxge_t,
54 					    flow_spec_t *,
55 					    tcam_entry_t *);
56 
57 static void nxge_fill_tcam_entry_tcp_ipv6(p_nxge_t, flow_spec_t *,
58 					    tcam_entry_t *);
59 
60 static void nxge_fill_tcam_entry_udp_ipv6(p_nxge_t,
61 					    flow_spec_t *,
62 					    tcam_entry_t *);
63 
64 static void nxge_fill_tcam_entry_sctp_ipv6(p_nxge_t,
65 					    flow_spec_t *,
66 					    tcam_entry_t *);
67 
68 static uint8_t nxge_get_rdc_offset(p_nxge_t, uint8_t, intptr_t);
69 static uint8_t nxge_get_rdc_group(p_nxge_t, uint8_t, intptr_t);
70 
71 static tcam_location_t nxge_get_tcam_location(p_nxge_t, uint8_t);
72 
73 
74 /* functions used outside this file */
75 nxge_status_t nxge_fflp_config_vlan_table(p_nxge_t, uint16_t);
76 nxge_status_t nxge_fflp_ip_class_config_all(p_nxge_t);
77 nxge_status_t nxge_add_flow(p_nxge_t, flow_resource_t *);
78 static nxge_status_t nxge_tcam_handle_ip_fragment(p_nxge_t);
79 nxge_status_t nxge_add_tcam_entry(p_nxge_t, flow_resource_t *);
80 nxge_status_t nxge_add_fcram_entry(p_nxge_t, flow_resource_t *);
81 nxge_status_t nxge_flow_get_hash(p_nxge_t, flow_resource_t *,
82 			    uint32_t *, uint16_t *);
83 
84 nxge_status_t
85 nxge_tcam_dump_entry(p_nxge_t nxgep, uint32_t location)
86 {
87 	tcam_entry_t tcam_rdptr;
88 	uint64_t asc_ram = 0;
89 	npi_handle_t handle;
90 	npi_status_t status;
91 
92 	handle = nxgep->npi_reg_handle;
93 
94 	bzero((char *)&tcam_rdptr, sizeof (struct tcam_entry));
95 	status = npi_fflp_tcam_entry_read(handle, (tcam_location_t)location,
96 				    (struct tcam_entry *)&tcam_rdptr);
97 	if (status & NPI_FAILURE) {
98 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
99 				    " nxge_tcam_dump_entry:"
100 				    "  tcam read failed at location %d ",
101 				    location));
102 		return (NXGE_ERROR);
103 	}
104 
105 	status = npi_fflp_tcam_asc_ram_entry_read(handle,
106 				    (tcam_location_t)location, &asc_ram);
107 
108 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "location %x\n"
109 		    " key:  %llx %llx %llx %llx \n"
110 		    " mask: %llx %llx %llx %llx \n"
111 		    " ASC RAM %llx \n", location,
112 		    tcam_rdptr.key0, tcam_rdptr.key1,
113 		    tcam_rdptr.key2, tcam_rdptr.key3,
114 		    tcam_rdptr.mask0, tcam_rdptr.mask1,
115 		    tcam_rdptr.mask2, tcam_rdptr.mask3,
116 		    asc_ram));
117 	return (NXGE_OK);
118 }
119 
120 void
121 nxge_get_tcam(p_nxge_t nxgep, p_mblk_t mp)
122 {
123 
124 	uint32_t tcam_loc;
125 	int *lptr;
126 	int location;
127 
128 	uint32_t start_location = 0;
129 	uint32_t stop_location = nxgep->classifier.tcam_size;
130 	lptr = (int *)mp->b_rptr;
131 	location = *lptr;
132 
133 	if ((location >= nxgep->classifier.tcam_size) || (location < -1)) {
134 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
135 			    "nxge_tcam_dump: Invalid location %d \n",
136 			    location));
137 		return;
138 	}
139 	if (location == -1) {
140 		start_location = 0;
141 		stop_location = nxgep->classifier.tcam_size;
142 	} else {
143 		start_location = location;
144 		stop_location = location +1;
145 	}
146 	for (tcam_loc = start_location; tcam_loc < stop_location; tcam_loc++)
147 		(void) nxge_tcam_dump_entry(nxgep, tcam_loc);
148 
149 }
150 
151 
152 /*
153  * nxge_fflp_vlan_table_invalidate_all
154  * invalidates the vlan RDC table entries.
155  * INPUT
156  * nxge    soft state data structure
157  * Return
158  *      NXGE_OK
159  *      NXGE_ERROR
160  *
161  */
162 static nxge_status_t
163 nxge_fflp_vlan_tbl_clear_all(p_nxge_t nxgep)
164 {
165 	vlan_id_t vlan_id;
166 	npi_handle_t handle;
167 	npi_status_t rs = NPI_SUCCESS;
168 	vlan_id_t start = 0, stop = NXGE_MAX_VLANS;
169 
170 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_vlan_tbl_clear_all "));
171 	handle = nxgep->npi_reg_handle;
172 	for (vlan_id = start; vlan_id < stop; vlan_id++) {
173 		rs = npi_fflp_cfg_vlan_table_clear(handle, vlan_id);
174 		if (rs != NPI_SUCCESS) {
175 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
176 			    "VLAN Table invalidate failed for vlan id %d ",
177 			    vlan_id));
178 			return (NXGE_ERROR | rs);
179 		}
180 	}
181 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_vlan_tbl_clear_all "));
182 
183 	return (NXGE_OK);
184 }
185 
186 
187 
188 /*
189  * The following functions are used by other modules to init
190  * the fflp module.
191  * these functions are the basic API used to init
192  * the fflp modules (tcam, fcram etc ......)
193  *
194  * The TCAM search future would be disabled  by default.
195  */
196 
197 static nxge_status_t
198 nxge_fflp_tcam_init(p_nxge_t nxgep)
199 {
200 
201 	uint8_t access_ratio;
202 	tcam_class_t class;
203 	npi_status_t rs = NPI_SUCCESS;
204 	npi_handle_t handle;
205 
206 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_tcam_init"));
207 	handle = nxgep->npi_reg_handle;
208 
209 	rs = npi_fflp_cfg_tcam_disable(handle);
210 	if (rs != NPI_SUCCESS) {
211 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "failed TCAM Disable\n"));
212 		return (NXGE_ERROR | rs);
213 	}
214 
215 	access_ratio = nxgep->param_arr[param_tcam_access_ratio].value;
216 	rs = npi_fflp_cfg_tcam_access(handle, access_ratio);
217 	if (rs != NPI_SUCCESS) {
218 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
219 			    "failed TCAM Access cfg\n"));
220 		return (NXGE_ERROR | rs);
221 	}
222 
223 /* disable configurable classes */
224 /* disable the configurable ethernet classes; */
225 	for (class = TCAM_CLASS_ETYPE_1;
226 		class <= TCAM_CLASS_ETYPE_2; class++) {
227 		rs = npi_fflp_cfg_enet_usr_cls_disable(handle, class);
228 		if (rs != NPI_SUCCESS) {
229 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
230 							"TCAM USR Ether Class"
231 							"config failed."));
232 			return (NXGE_ERROR | rs);
233 		}
234 	}
235 
236 		/* disable the configurable ip classes; */
237 	for (class = TCAM_CLASS_IP_USER_4;
238 		class <= TCAM_CLASS_IP_USER_7; class++) {
239 		rs = npi_fflp_cfg_ip_usr_cls_disable(handle, class);
240 		if (rs != NPI_SUCCESS) {
241 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
242 					"TCAM USR IP Class"
243 					"cnfg failed."));
244 			return (NXGE_ERROR | rs);
245 		}
246 	}
247 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_tcam_init"));
248 
249 	return (NXGE_OK);
250 }
251 
252 
253 /*
254  * nxge_fflp_tcam_invalidate_all
255  * invalidates all the tcam entries.
256  * INPUT
257  * nxge    soft state data structure
258  * Return
259  *      NXGE_OK
260  *      NXGE_ERROR
261  *
262  */
263 static nxge_status_t
264 nxge_fflp_tcam_invalidate_all(p_nxge_t nxgep)
265 {
266 	uint16_t location;
267 	npi_status_t rs = NPI_SUCCESS;
268 	npi_handle_t handle;
269 	uint16_t start = 0, stop = nxgep->classifier.tcam_size;
270 	p_nxge_hw_list_t	hw_p;
271 
272 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
273 			    "==> nxge_fflp_tcam_invalidate_all"));
274 	handle = nxgep->npi_reg_handle;
275 	if ((hw_p = nxgep->nxge_hw_p) == NULL) {
276 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
277 			" nxge_fflp_tcam_invalidate_all:"
278 			" common hardware not set",
279 			nxgep->niu_type));
280 		return (NXGE_ERROR);
281 	}
282 	MUTEX_ENTER(&hw_p->nxge_tcam_lock);
283 	for (location = start; location < stop; location++) {
284 		rs = npi_fflp_tcam_entry_invalidate(handle, location);
285 		if (rs != NPI_SUCCESS) {
286 			MUTEX_EXIT(&hw_p->nxge_tcam_lock);
287 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
288 				    "TCAM invalidate failed at loc %d ",
289 				    location));
290 			return (NXGE_ERROR | rs);
291 		}
292 	}
293 	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
294 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
295 			    "<== nxge_fflp_tcam_invalidate_all"));
296 	return (NXGE_OK);
297 }
298 
299 /*
300  * nxge_fflp_fcram_entry_invalidate_all
301  * invalidates all the FCRAM entries.
302  * INPUT
303  * nxge    soft state data structure
304  * Return
305  *      NXGE_OK
306  *      NXGE_ERROR
307  *
308  */
309 static nxge_status_t
310 nxge_fflp_fcram_invalidate_all(p_nxge_t nxgep)
311 
312 {
313     npi_handle_t handle;
314     npi_status_t rs = NPI_SUCCESS;
315     part_id_t pid = 0;
316     uint8_t base_mask, base_reloc;
317     fcram_entry_t fc;
318     uint32_t location;
319     uint32_t increment, last_location;
320 
321 /*
322  * (1) configure and enable partition 0 with no relocation
323  * (2) Assume the FCRAM is used as IPv4 exact match entry cells
324  * (3) Invalidate these cells by clearing the valid bit in
325  * the subareas 0 and 4
326  * (4) disable the partition
327  *
328  */
329 
330 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_fcram_invalidate_all"));
331 
332 	base_mask = base_reloc = 0x0;
333 	handle = nxgep->npi_reg_handle;
334     rs = npi_fflp_cfg_fcram_partition(handle, pid, base_mask, base_reloc);
335 
336 	if (rs != NPI_SUCCESS) {
337 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
338 				    "failed partition  cfg\n"));
339 		return (NXGE_ERROR | rs);
340 	}
341 
342     rs = npi_fflp_cfg_fcram_partition_disable(handle, pid);
343 
344 	if (rs != NPI_SUCCESS) {
345 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
346 			    "failed partition  enable\n"));
347 		return (NXGE_ERROR | rs);
348 	}
349 
350     fc.dreg[0].value = 0;
351     fc.hash_hdr_valid = 0;
352     fc.hash_hdr_ext = 1; /* specify as IPV4 exact match entry */
353     increment = sizeof (hash_ipv4_t);
354     last_location = FCRAM_SIZE * 0x40;
355 
356     for (location = 0; location < last_location; location += increment) {
357 		rs = npi_fflp_fcram_subarea_write(handle, pid,
358 							location,
359 							fc.value[0]);
360 		if (rs != NPI_SUCCESS) {
361 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
362 							"failed write"
363 							"at location %x ",
364 							location));
365 			return (NXGE_ERROR | rs);
366 		}
367 	}
368 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_fcram_invalidate_all"));
369 
370     return (NXGE_OK);
371 
372 }
373 
374 
375 static nxge_status_t
376 nxge_fflp_fcram_init(p_nxge_t nxgep)
377 
378 {
379 	fflp_fcram_output_drive_t strength;
380 	fflp_fcram_qs_t qs;
381 	npi_status_t rs = NPI_SUCCESS;
382 	uint8_t access_ratio;
383     int partition;
384 	npi_handle_t handle;
385 	uint32_t min_time,  max_time,  sys_time;
386 
387 
388 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_fcram_init"));
389 
390 /*
391  * for these we need to get the recommended values from Michael
392  */
393 	min_time = FCRAM_REFRESH_DEFAULT_MIN_TIME;
394 	max_time = FCRAM_REFRESH_DEFAULT_MAX_TIME;
395 	sys_time = FCRAM_REFRESH_DEFAULT_SYS_TIME;
396 	handle = nxgep->npi_reg_handle;
397 	strength = FCRAM_OUTDR_NORMAL;
398 	qs = FCRAM_QS_MODE_QS;
399 	rs = npi_fflp_cfg_fcram_reset(handle, strength, qs);
400 	if (rs != NPI_SUCCESS) {
401 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "failed FCRAM Reset. "));
402 		return (NXGE_ERROR | rs);
403 	}
404 
405     access_ratio = nxgep->param_arr[param_fcram_access_ratio].value;
406     rs = npi_fflp_cfg_fcram_access(handle, access_ratio);
407     if (rs != NPI_SUCCESS) {
408 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "failed FCRAM Access ratio"
409 						"configuration \n"));
410 		return (NXGE_ERROR | rs);
411 	}
412 
413 	rs = npi_fflp_cfg_fcram_refresh_time(handle, min_time,
414 						    max_time, sys_time);
415 	if (rs != NPI_SUCCESS) {
416 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
417 						"failed FCRAM refresh cfg"));
418 		return (NXGE_ERROR);
419 	}
420 
421 	/* disable all the partitions until explicitly enabled */
422 	for (partition = 0; partition < FFLP_FCRAM_MAX_PARTITION; partition++) {
423 		rs = npi_fflp_cfg_fcram_partition_disable(handle,
424 							    partition);
425 		if (rs != NPI_SUCCESS) {
426 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
427 					"failed FCRAM partition"
428 					" enable for partition %d ",
429 					partition));
430 			return (NXGE_ERROR | rs);
431 		}
432 	}
433 
434 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_fcram_init"));
435 
436     return (NXGE_OK);
437 
438 }
439 
440 
441 nxge_status_t
442 nxge_logical_mac_assign_rdc_table(p_nxge_t nxgep, uint8_t alt_mac)
443 {
444 
445 	npi_status_t rs = NPI_SUCCESS;
446 	hostinfo_t mac_rdc;
447 	npi_handle_t handle;
448 	p_nxge_class_pt_cfg_t 	p_class_cfgp;
449 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
450 
451 	if (p_class_cfgp->mac_host_info[alt_mac].flag == 0) {
452 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
453 				    " nxge_logical_mac_assign_rdc_table"
454 				    " unconfigured alt MAC addr %d ",
455 				    alt_mac));
456 		return (NXGE_ERROR);
457 	}
458 
459 	handle = nxgep->npi_reg_handle;
460 	mac_rdc.value = 0;
461 	mac_rdc.bits.w0.rdc_tbl_num =
462 		    p_class_cfgp->mac_host_info[alt_mac].rdctbl;
463 	mac_rdc.bits.w0.mac_pref = p_class_cfgp->mac_host_info[alt_mac].mpr_npr;
464 
465 	rs = npi_mac_hostinfo_entry(handle, OP_SET,
466 				    nxgep->function_num, alt_mac, &mac_rdc);
467 
468 	if (rs != NPI_SUCCESS) {
469 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
470 				    "failed Assign RDC table"));
471 		return (NXGE_ERROR | rs);
472 	}
473 	return (NXGE_OK);
474 }
475 
476 nxge_status_t
477 nxge_main_mac_assign_rdc_table(p_nxge_t nxgep)
478 {
479 
480 	npi_status_t rs = NPI_SUCCESS;
481 	hostinfo_t mac_rdc;
482 	npi_handle_t handle;
483 
484 	handle = nxgep->npi_reg_handle;
485 	mac_rdc.value = 0;
486 	mac_rdc.bits.w0.rdc_tbl_num = nxgep->class_config.mac_rdcgrp;
487 	mac_rdc.bits.w0.mac_pref = 1;
488 	switch (nxgep->function_num) {
489 		case 0:
490 		case 1:
491 			rs = npi_mac_hostinfo_entry(handle, OP_SET,
492 				nxgep->function_num,
493 				XMAC_UNIQUE_HOST_INFO_ENTRY, &mac_rdc);
494 			break;
495 		case 2:
496 		case 3:
497 			rs = npi_mac_hostinfo_entry(handle, OP_SET,
498 				nxgep->function_num,
499 				BMAC_UNIQUE_HOST_INFO_ENTRY, &mac_rdc);
500 			break;
501 		default:
502 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
503 				"failed Assign RDC table (invalid funcion #)"));
504 			return (NXGE_ERROR);
505 	}
506 
507 	if (rs != NPI_SUCCESS) {
508 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
509 						"failed Assign RDC table"));
510 		return (NXGE_ERROR | rs);
511 	}
512 	return (NXGE_OK);
513 }
514 
515 
516 nxge_status_t
517 nxge_multicast_mac_assign_rdc_table(p_nxge_t nxgep)
518 {
519 
520 	npi_status_t rs = NPI_SUCCESS;
521 	hostinfo_t mac_rdc;
522 	npi_handle_t handle;
523 
524 	handle = nxgep->npi_reg_handle;
525 	mac_rdc.value = 0;
526 	mac_rdc.bits.w0.rdc_tbl_num = nxgep->class_config.mcast_rdcgrp;
527 	mac_rdc.bits.w0.mac_pref = 1;
528 	switch (nxgep->function_num) {
529 		case 0:
530 		case 1:
531 			rs = npi_mac_hostinfo_entry(handle, OP_SET,
532 				nxgep->function_num,
533 				XMAC_MULTI_HOST_INFO_ENTRY, &mac_rdc);
534 			break;
535 		case 2:
536 		case 3:
537 			rs = npi_mac_hostinfo_entry(handle, OP_SET,
538 				nxgep->function_num,
539 				BMAC_MULTI_HOST_INFO_ENTRY, &mac_rdc);
540 			break;
541 		default:
542 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
543 				"failed Assign RDC table (invalid funcion #)"));
544 			return (NXGE_ERROR);
545 	}
546 
547 	if (rs != NPI_SUCCESS) {
548 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
549 						"failed Assign RDC table"));
550 		return (NXGE_ERROR | rs);
551 	}
552 	return (NXGE_OK);
553 }
554 
555 nxge_status_t
556 nxge_fflp_init_hostinfo(p_nxge_t nxgep)
557 {
558 	nxge_status_t status = NXGE_OK;
559 	status = nxge_multicast_mac_assign_rdc_table(nxgep);
560 	status = nxge_main_mac_assign_rdc_table(nxgep);
561 	return (status);
562 }
563 
564 
565 nxge_status_t
566 nxge_fflp_hw_reset(p_nxge_t nxgep)
567 {
568 	npi_handle_t handle;
569 	npi_status_t rs = NPI_SUCCESS;
570 	nxge_status_t status = NXGE_OK;
571 
572 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_hw_reset"));
573 
574 
575 	if (nxgep->niu_type == NEPTUNE) {
576 		status = nxge_fflp_fcram_init(nxgep);
577 		if (status  != NXGE_OK) {
578 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
579 					    " failed FCRAM init. "));
580 			return (status);
581 		}
582 	}
583 
584 
585 	status = nxge_fflp_tcam_init(nxgep);
586 	if (status != NXGE_OK) {
587 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
588 					    "failed TCAM init."));
589 			return (status);
590 	}
591 
592 	handle = nxgep->npi_reg_handle;
593 	rs = npi_fflp_cfg_llcsnap_enable(handle);
594 	if (rs != NPI_SUCCESS) {
595 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
596 					"failed LLCSNAP enable. "));
597 			return (NXGE_ERROR | rs);
598 	}
599 
600 	rs = npi_fflp_cfg_cam_errorcheck_disable(handle);
601 	if (rs != NPI_SUCCESS) {
602 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
603 				"failed CAM Error Check enable. "));
604 		return (NXGE_ERROR | rs);
605 	}
606 
607 /* init the hash generators */
608 
609 	rs = npi_fflp_cfg_hash_h1poly(handle, 0);
610 	if (rs != NPI_SUCCESS) {
611 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
612 					"failed H1 Poly Init. "));
613 			return (NXGE_ERROR | rs);
614 	}
615 
616 	rs = npi_fflp_cfg_hash_h2poly(handle, 0);
617 	if (rs != NPI_SUCCESS) {
618 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
619 					"failed H2 Poly Init. "));
620 			return (NXGE_ERROR | rs);
621 	}
622 
623 
624 /* invalidate TCAM entries */
625 	status = nxge_fflp_tcam_invalidate_all(nxgep);
626 	if (status != NXGE_OK) {
627 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
628 				"failed TCAM Entry Invalidate. "));
629 		return (status);
630 	}
631 
632 /* invalidate FCRAM entries */
633 	if (nxgep->niu_type == NEPTUNE) {
634 		status = nxge_fflp_fcram_invalidate_all(nxgep);
635 		if (status != NXGE_OK) {
636 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
637 				    "failed FCRAM Entry Invalidate. "));
638 			return (status);
639 		}
640 	}
641 
642 
643 /* invalidate VLAN RDC tables */
644 
645 	status = nxge_fflp_vlan_tbl_clear_all(nxgep);
646 	if (status != NXGE_OK) {
647 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
648 				"failed VLAN Table Invalidate. "));
649 		return (status);
650 	}
651 
652 	nxgep->classifier.state |= NXGE_FFLP_HW_RESET;
653 
654 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_hw_reset"));
655 
656 	return (NXGE_OK);
657 
658 }
659 
660 
661 nxge_status_t
662 nxge_cfg_ip_cls_flow_key(p_nxge_t nxgep, tcam_class_t l3_class,
663 			    uint32_t class_config)
664 {
665 	flow_key_cfg_t fcfg;
666 	npi_handle_t handle;
667 	npi_status_t rs = NPI_SUCCESS;
668 
669 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_cfg_ip_cls_flow_key"));
670 	handle = nxgep->npi_reg_handle;
671 	bzero(&fcfg, sizeof (flow_key_cfg_t));
672 
673 	if (class_config &  NXGE_CLASS_FLOW_USE_PROTO)
674 		fcfg.use_proto = 1;
675 	if (class_config & NXGE_CLASS_FLOW_USE_DST_PORT)
676 		fcfg.use_dport = 1;
677 	if (class_config & NXGE_CLASS_FLOW_USE_SRC_PORT)
678 		fcfg.use_sport = 1;
679 	if (class_config & NXGE_CLASS_FLOW_USE_IPDST)
680 		fcfg.use_daddr = 1;
681 	if (class_config & NXGE_CLASS_FLOW_USE_IPSRC)
682 		fcfg.use_saddr = 1;
683 	if (class_config & NXGE_CLASS_FLOW_USE_VLAN)
684 		fcfg.use_vlan = 1;
685 
686 	if (class_config & NXGE_CLASS_FLOW_USE_L2DA)
687 		fcfg.use_l2da = 1;
688 
689 	if (class_config & NXGE_CLASS_FLOW_USE_PORTNUM)
690 		fcfg.use_portnum = 1;
691 
692 	fcfg.ip_opts_exist = 0;
693 
694 	rs = npi_fflp_cfg_ip_cls_flow_key(handle, l3_class, &fcfg);
695 	if (rs & NPI_FFLP_ERROR) {
696 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_ip_cls_flow_key"
697 				    " opt %x for class %d failed ",
698 				    class_config, l3_class));
699 		return (NXGE_ERROR | rs);
700 	}
701 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_cfg_ip_cls_flow_key"));
702 	return (NXGE_OK);
703 }
704 
705 
706 nxge_status_t
707 nxge_cfg_ip_cls_flow_key_get(p_nxge_t nxgep, tcam_class_t l3_class,
708 			    uint32_t *class_config)
709 {
710 	flow_key_cfg_t fcfg;
711 	npi_handle_t handle;
712 	npi_status_t rs = NPI_SUCCESS;
713 	uint32_t ccfg = 0;
714 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_cfg_ip_cls_flow_key_get"));
715 	handle = nxgep->npi_reg_handle;
716 	bzero(&fcfg, sizeof (flow_key_cfg_t));
717 
718 	rs = npi_fflp_cfg_ip_cls_flow_key_get(handle, l3_class, &fcfg);
719 	if (rs & NPI_FFLP_ERROR) {
720 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_ip_cls_flow_key"
721 				    " opt %x for class %d failed ",
722 				    class_config, l3_class));
723 		return (NXGE_ERROR | rs);
724 	}
725 
726 	if (fcfg.use_proto)
727 		ccfg |= NXGE_CLASS_FLOW_USE_PROTO;
728 
729 	if (fcfg.use_dport)
730 		ccfg |= NXGE_CLASS_FLOW_USE_DST_PORT;
731 
732 	if (fcfg.use_sport)
733 		ccfg |= NXGE_CLASS_FLOW_USE_SRC_PORT;
734 
735 	if (fcfg.use_daddr)
736 		ccfg |= NXGE_CLASS_FLOW_USE_IPDST;
737 
738 	if (fcfg.use_saddr)
739 		ccfg |= NXGE_CLASS_FLOW_USE_IPSRC;
740 
741 	if (fcfg.use_vlan)
742 		ccfg |= NXGE_CLASS_FLOW_USE_VLAN;
743 
744 	if (fcfg.use_l2da)
745 		ccfg |= NXGE_CLASS_FLOW_USE_L2DA;
746 
747 	if (fcfg.use_portnum)
748 		ccfg |=  NXGE_CLASS_FLOW_USE_PORTNUM;
749 
750 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
751 			    " nxge_cfg_ip_cls_flow_key_get %x", ccfg));
752 	*class_config = ccfg;
753 
754 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
755 			    " <== nxge_cfg_ip_cls_flow_key_get"));
756 	return (NXGE_OK);
757 }
758 
759 
760 static nxge_status_t
761 nxge_cfg_tcam_ip_class_get(p_nxge_t nxgep, tcam_class_t class,
762 			    uint32_t  *class_config)
763 {
764 	npi_status_t rs = NPI_SUCCESS;
765 	tcam_key_cfg_t cfg;
766 	npi_handle_t handle;
767 	uint32_t ccfg = 0;
768 
769 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_cfg_tcam_ip_class"));
770 
771 	bzero(&cfg, sizeof (tcam_key_cfg_t));
772 	handle = nxgep->npi_reg_handle;
773 
774 	rs = npi_fflp_cfg_ip_cls_tcam_key_get(handle, class, &cfg);
775 	if (rs & NPI_FFLP_ERROR) {
776 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_tcam_ip_class"
777 				    " opt %x for class %d failed ",
778 				    class_config, class));
779 		return (NXGE_ERROR | rs);
780 	}
781 	if (cfg.discard)
782 		ccfg |=  NXGE_CLASS_DISCARD;
783 
784 	if (cfg.lookup_enable)
785 		ccfg |= NXGE_CLASS_TCAM_LOOKUP;
786 
787 	if (cfg.use_ip_daddr)
788 		ccfg |= 	NXGE_CLASS_TCAM_USE_SRC_ADDR;
789 
790 	*class_config = ccfg;
791 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
792 			    " ==> nxge_cfg_tcam_ip_class %x", ccfg));
793 	return (NXGE_OK);
794 }
795 
796 
797 static nxge_status_t
798 nxge_cfg_tcam_ip_class(p_nxge_t nxgep, tcam_class_t class,
799 			    uint32_t  class_config)
800 {
801 	npi_status_t rs = NPI_SUCCESS;
802 	tcam_key_cfg_t cfg;
803 	npi_handle_t handle;
804 	p_nxge_class_pt_cfg_t 	p_class_cfgp;
805 
806 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_cfg_tcam_ip_class"));
807 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
808 	p_class_cfgp->class_cfg[class] = class_config;
809 
810 	bzero(&cfg, sizeof (tcam_key_cfg_t));
811 	handle = nxgep->npi_reg_handle;
812 	cfg.discard = 0;
813 	cfg.lookup_enable = 0;
814 	cfg.use_ip_daddr = 0;
815 	if (class_config & NXGE_CLASS_DISCARD)
816 		cfg.discard = 1;
817 	if (class_config & NXGE_CLASS_TCAM_LOOKUP)
818 		cfg.lookup_enable = 1;
819 	if (class_config & 	NXGE_CLASS_TCAM_USE_SRC_ADDR)
820 		cfg.use_ip_daddr = 1;
821 
822 	rs = npi_fflp_cfg_ip_cls_tcam_key(handle, class, &cfg);
823 	if (rs & NPI_FFLP_ERROR) {
824 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_cfg_tcam_ip_class"
825 				    " opt %x for class %d failed ",
826 				    class_config, class));
827 		return (NXGE_ERROR | rs);
828 	}
829 	return (NXGE_OK);
830 }
831 
832 
833 nxge_status_t
834 nxge_fflp_set_hash1(p_nxge_t nxgep, uint32_t h1)
835 {
836 	npi_status_t rs = NPI_SUCCESS;
837 	npi_handle_t handle;
838 	p_nxge_class_pt_cfg_t 	p_class_cfgp;
839 
840 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_init_h1"));
841 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
842 	p_class_cfgp->init_h1 = h1;
843 	handle = nxgep->npi_reg_handle;
844 	rs = npi_fflp_cfg_hash_h1poly(handle, h1);
845 	if (rs & NPI_FFLP_ERROR) {
846 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_fflp_init_h1"
847 				    "  %x failed ",
848 				    h1));
849 		return (NXGE_ERROR | rs);
850 	}
851 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_fflp_init_h1"));
852 	return (NXGE_OK);
853 }
854 
855 nxge_status_t
856 nxge_fflp_set_hash2(p_nxge_t nxgep, uint16_t h2)
857 {
858 	npi_status_t rs = NPI_SUCCESS;
859 	npi_handle_t handle;
860 	p_nxge_class_pt_cfg_t 	p_class_cfgp;
861 
862 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_init_h2"));
863 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
864 	p_class_cfgp->init_h2 = h2;
865 
866 	handle = nxgep->npi_reg_handle;
867 	rs = npi_fflp_cfg_hash_h2poly(handle, h2);
868 	if (rs & NPI_FFLP_ERROR) {
869 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, " nxge_fflp_init_h2"
870 				    "  %x failed ",
871 				    h2));
872 		return (NXGE_ERROR | rs);
873 	}
874 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_fflp_init_h2"));
875 	return (NXGE_OK);
876 }
877 
878 
879 nxge_status_t
880 nxge_classify_init_sw(p_nxge_t nxgep)
881 {
882 	int alloc_size;
883 	nxge_classify_t *classify_ptr;
884 
885 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_classify_init_sw"));
886 	classify_ptr = &nxgep->classifier;
887 
888 	if (classify_ptr->state & NXGE_FFLP_SW_INIT) {
889 		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
890 		    "nxge_classify_init_sw already init"));
891 		return (NXGE_OK);
892 	}
893 
894 		/* Init SW structures */
895 
896 	classify_ptr->tcam_size = TCAM_NIU_TCAM_MAX_ENTRY;
897 		/* init data structures, based on HW type */
898 	if (nxgep->niu_type == NEPTUNE) {
899 		classify_ptr->tcam_size = TCAM_NXGE_TCAM_MAX_ENTRY;
900 			/*
901 			 * check if fcram based classification is required
902 			 * and init the flow storage
903 			 */
904 	}
905 
906 	alloc_size = sizeof (tcam_flow_spec_t) * classify_ptr->tcam_size;
907 	classify_ptr->tcam_entries = KMEM_ZALLOC(alloc_size, NULL);
908 
909 		/* Init defaults */
910 		/*
911 		 * add hacks required for HW shortcomings
912 		 * for example, code to handle fragmented packets
913 		 */
914 
915 	nxge_init_h1_table();
916 	nxge_crc_ccitt_init();
917 	nxgep->classifier.tcam_location = nxgep->function_num;
918 	nxgep->classifier.fragment_bug = 1;
919 	classify_ptr->state |= NXGE_FFLP_SW_INIT;
920 
921 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_classify_init_sw"));
922 
923 	return (NXGE_OK);
924 
925 }
926 
927 
928 
929 nxge_status_t
930 nxge_classify_exit_sw(p_nxge_t nxgep)
931 {
932 	int alloc_size;
933 	nxge_classify_t *classify_ptr;
934 	int fsize;
935 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_classify_exit_sw"));
936 	classify_ptr = &nxgep->classifier;
937 
938 	fsize = sizeof (tcam_flow_spec_t);
939 	if (classify_ptr->tcam_entries) {
940 		alloc_size =  fsize * classify_ptr->tcam_size;
941 		KMEM_FREE((void*)classify_ptr->tcam_entries, alloc_size);
942 	}
943 
944 	nxgep->classifier.state = NULL;
945 
946 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_classify_exit_sw"));
947 
948 	return (NXGE_OK);
949 
950 }
951 
952 
953 
954 /*
955  * Figures out the location where the TCAM entry is
956  * to be inserted.
957  *
958  * The current implementation is just a place holder and it
959  * returns the next tcam location.
960  * The real location determining algorithm would consider
961  * the priority, partition etc ... before deciding which
962  * location to insert.
963  *
964  */
965 
966 #ifdef lint
967 /* ARGSUSED */
968 #endif
969 static tcam_location_t
970 nxge_get_tcam_location(p_nxge_t nxgep, uint8_t class)
971 {
972 	tcam_location_t location;
973 	location = nxgep->classifier.tcam_location;
974 	nxgep->classifier.tcam_location = (location + nxgep->nports) %
975 					    nxgep->classifier.tcam_size;
976 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
977 			    "nxge_get_tcam_location: location %d next %d \n",
978 			    location, nxgep->classifier.tcam_location));
979 	return (location);
980 }
981 
982 
983 /*
984  * Figures out the RDC Group for the entry
985  *
986  * The current implementation is just a place holder and it
987  * returns 0.
988  * The real location determining algorithm would consider
989  * the partition etc ... before deciding w
990  *
991  */
992 #ifdef lint
993 /* ARGSUSED */
994 #endif
995 static uint8_t
996 nxge_get_rdc_group(p_nxge_t nxgep, uint8_t class, intptr_t cookie)
997 {
998 	int use_port_rdc_grp = 0;
999 	uint8_t rdc_grp = 0;
1000 	p_nxge_dma_pt_cfg_t	p_dma_cfgp;
1001 	p_nxge_hw_pt_cfg_t	p_cfgp;
1002 	p_nxge_rdc_grp_t	rdc_grp_p;
1003 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
1004 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
1005 	rdc_grp_p = &p_dma_cfgp->rdc_grps[use_port_rdc_grp];
1006 	rdc_grp = p_cfgp->start_rdc_grpid;
1007 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1008 		    "nxge_get_rdc_group: grp 0x%x real_grp %x grpp $%p\n",
1009 		    cookie, rdc_grp, rdc_grp_p));
1010 	return (rdc_grp);
1011 }
1012 
1013 #ifdef lint
1014 /* ARGSUSED */
1015 #endif
1016 static uint8_t
1017 nxge_get_rdc_offset(p_nxge_t nxgep, uint8_t class, intptr_t cookie)
1018 {
1019 	return ((uint8_t)cookie);
1020 }
1021 
1022 
1023 #ifdef lint
1024 /* ARGSUSED */
1025 #endif
1026 static void
1027 nxge_fill_tcam_entry_udp(p_nxge_t nxgep, flow_spec_t *flow_spec,
1028 			    tcam_entry_t *tcam_ptr)
1029 {
1030 	udpip4_spec_t *fspec_key;
1031 	udpip4_spec_t *fspec_mask;
1032 
1033 	fspec_key = (udpip4_spec_t *)&flow_spec->uh.udpip4spec;
1034 	fspec_mask = (udpip4_spec_t *)&flow_spec->um.udpip4spec;
1035 
1036 	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
1037 	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
1038 	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
1039 	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
1040 
1041 	TCAM_IP_PORTS(tcam_ptr->ip4_port_key,
1042 					fspec_key->pdst, fspec_key->psrc);
1043 	TCAM_IP_PORTS(tcam_ptr->ip4_port_mask,
1044 					fspec_mask->pdst, fspec_mask->psrc);
1045 
1046 	TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
1047 				    tcam_ptr->ip4_class_mask,
1048 				    TCAM_CLASS_UDP_IPV4);
1049 
1050 	TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
1051 				    tcam_ptr->ip4_proto_mask,
1052 				    IPPROTO_UDP);
1053 
1054 }
1055 
1056 #ifdef lint
1057 /* ARGSUSED */
1058 #endif
1059 static void
1060 nxge_fill_tcam_entry_udp_ipv6(p_nxge_t nxgep, flow_spec_t *flow_spec,
1061 			    tcam_entry_t *tcam_ptr)
1062 {
1063 	udpip6_spec_t *fspec_key;
1064 	udpip6_spec_t *fspec_mask;
1065 	p_nxge_class_pt_cfg_t 	p_class_cfgp;
1066 
1067 	fspec_key = (udpip6_spec_t *)&flow_spec->uh.udpip6spec;
1068 	fspec_mask = (udpip6_spec_t *)&flow_spec->um.udpip6spec;
1069 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
1070 	if (p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV6] &
1071 		NXGE_CLASS_TCAM_USE_SRC_ADDR) {
1072 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6src);
1073 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6src);
1074 	} else {
1075 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6dst);
1076 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6dst);
1077 	}
1078 
1079 	TCAM_IP_CLASS(tcam_ptr->ip6_class_key,
1080 		    tcam_ptr->ip6_class_mask, TCAM_CLASS_UDP_IPV6);
1081 
1082 
1083 	TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
1084 		    tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_UDP);
1085 
1086 	TCAM_IP_PORTS(tcam_ptr->ip6_port_key,
1087 			fspec_key->pdst, fspec_key->psrc);
1088 	TCAM_IP_PORTS(tcam_ptr->ip6_port_mask,
1089 			fspec_mask->pdst, fspec_mask->psrc);
1090 
1091 }
1092 
1093 #ifdef lint
1094 /* ARGSUSED */
1095 #endif
1096 
1097 static void
1098 nxge_fill_tcam_entry_tcp(p_nxge_t nxgep, flow_spec_t *flow_spec,
1099 							tcam_entry_t *tcam_ptr)
1100 {
1101 
1102 	tcpip4_spec_t *fspec_key;
1103 	tcpip4_spec_t *fspec_mask;
1104 
1105 	fspec_key = (tcpip4_spec_t *)&flow_spec->uh.tcpip4spec;
1106 	fspec_mask = (tcpip4_spec_t *)&flow_spec->um.tcpip4spec;
1107 
1108 
1109 	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
1110 	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
1111 	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
1112 	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
1113 
1114 	TCAM_IP_PORTS(tcam_ptr->ip4_port_key,
1115 				fspec_key->pdst, fspec_key->psrc);
1116 	TCAM_IP_PORTS(tcam_ptr->ip4_port_mask,
1117 				fspec_mask->pdst, fspec_mask->psrc);
1118 
1119 	TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
1120 		    tcam_ptr->ip4_class_mask, TCAM_CLASS_TCP_IPV4);
1121 
1122 	TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
1123 			    tcam_ptr->ip4_proto_mask, IPPROTO_TCP);
1124 }
1125 
1126 #ifdef lint
1127 /* ARGSUSED */
1128 #endif
1129 static void
1130 nxge_fill_tcam_entry_sctp(p_nxge_t nxgep, flow_spec_t *flow_spec,
1131 							tcam_entry_t *tcam_ptr)
1132 {
1133 
1134 	tcpip4_spec_t *fspec_key;
1135 	tcpip4_spec_t *fspec_mask;
1136 
1137 	fspec_key = (tcpip4_spec_t *)&flow_spec->uh.tcpip4spec;
1138 	fspec_mask = (tcpip4_spec_t *)&flow_spec->um.tcpip4spec;
1139 
1140 	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_key, fspec_key->ip4dst);
1141 	TCAM_IPV4_ADDR(tcam_ptr->ip4_dest_mask, fspec_mask->ip4dst);
1142 	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_key, fspec_key->ip4src);
1143 	TCAM_IPV4_ADDR(tcam_ptr->ip4_src_mask, fspec_mask->ip4src);
1144 
1145 	TCAM_IP_CLASS(tcam_ptr->ip4_class_key,
1146 		    tcam_ptr->ip4_class_mask, TCAM_CLASS_SCTP_IPV4);
1147 
1148 	TCAM_IP_PROTO(tcam_ptr->ip4_proto_key,
1149 			    tcam_ptr->ip4_proto_mask, IPPROTO_SCTP);
1150 
1151 	TCAM_IP_PORTS(tcam_ptr->ip4_port_key,
1152 			    fspec_key->pdst, fspec_key->psrc);
1153 	TCAM_IP_PORTS(tcam_ptr->ip4_port_mask,
1154 			    fspec_mask->pdst, fspec_mask->psrc);
1155 }
1156 
1157 
1158 
1159 static void
1160 nxge_fill_tcam_entry_tcp_ipv6(p_nxge_t nxgep, flow_spec_t *flow_spec,
1161 							tcam_entry_t *tcam_ptr)
1162 {
1163 
1164 	tcpip6_spec_t *fspec_key;
1165 	tcpip6_spec_t *fspec_mask;
1166 	p_nxge_class_pt_cfg_t 	p_class_cfgp;
1167 	fspec_key = (tcpip6_spec_t *)&flow_spec->uh.tcpip6spec;
1168 	fspec_mask = (tcpip6_spec_t *)&flow_spec->um.tcpip6spec;
1169 
1170 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
1171 	if (p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV6] &
1172 		NXGE_CLASS_TCAM_USE_SRC_ADDR) {
1173 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6src);
1174 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6src);
1175 
1176 	} else {
1177 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6dst);
1178 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6dst);
1179 	}
1180 
1181 	TCAM_IP_CLASS(tcam_ptr->ip6_class_key,
1182 			    tcam_ptr->ip6_class_mask, TCAM_CLASS_TCP_IPV6);
1183 
1184 
1185 	TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
1186 			    tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_TCP);
1187 
1188 	TCAM_IP_PORTS(tcam_ptr->ip6_port_key,
1189 			    fspec_key->pdst, fspec_key->psrc);
1190 	TCAM_IP_PORTS(tcam_ptr->ip6_port_mask,
1191 			    fspec_mask->pdst, fspec_mask->psrc);
1192 
1193 }
1194 
1195 
1196 static void
1197 nxge_fill_tcam_entry_sctp_ipv6(p_nxge_t nxgep, flow_spec_t *flow_spec,
1198 							tcam_entry_t *tcam_ptr)
1199 {
1200 
1201 	tcpip6_spec_t *fspec_key;
1202 	tcpip6_spec_t *fspec_mask;
1203 	p_nxge_class_pt_cfg_t 	p_class_cfgp;
1204 
1205 	fspec_key = (tcpip6_spec_t *)&flow_spec->uh.tcpip6spec;
1206 	fspec_mask = (tcpip6_spec_t *)&flow_spec->um.tcpip6spec;
1207 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
1208 
1209 	if (p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV6] &
1210 		NXGE_CLASS_TCAM_USE_SRC_ADDR) {
1211 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6src);
1212 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6src);
1213 
1214 	} else {
1215 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_key, fspec_key->ip6dst);
1216 		TCAM_IPV6_ADDR(tcam_ptr->ip6_ip_addr_mask, fspec_mask->ip6dst);
1217 	}
1218 
1219 	TCAM_IP_CLASS(tcam_ptr->ip6_class_key,
1220 			    tcam_ptr->ip6_class_mask, TCAM_CLASS_SCTP_IPV6);
1221 
1222 
1223 	TCAM_IP_PROTO(tcam_ptr->ip6_nxt_hdr_key,
1224 			    tcam_ptr->ip6_nxt_hdr_mask, IPPROTO_SCTP);
1225 
1226 
1227 	TCAM_IP_PORTS(tcam_ptr->ip6_port_key,
1228 			    fspec_key->pdst, fspec_key->psrc);
1229 	TCAM_IP_PORTS(tcam_ptr->ip6_port_mask,
1230 			    fspec_mask->pdst, fspec_mask->psrc);
1231 
1232 
1233 }
1234 
1235 
1236 nxge_status_t
1237 nxge_flow_get_hash(p_nxge_t nxgep, flow_resource_t *flow_res,
1238 			    uint32_t *H1, uint16_t *H2)
1239 {
1240 
1241 
1242 	intptr_t channel_cookie;
1243 	intptr_t flow_cookie;
1244 	flow_spec_t *flow_spec;
1245 	uint32_t class_cfg;
1246 	flow_template_t ft;
1247 	p_nxge_class_pt_cfg_t 	p_class_cfgp;
1248 
1249 	int ft_size = sizeof (flow_template_t);
1250 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_flow_get_hash"));
1251 
1252 	flow_spec = (flow_spec_t *)&flow_res->flow_spec;
1253 	flow_cookie = flow_res->flow_cookie;
1254 	channel_cookie = flow_res->channel_cookie;
1255 #ifdef lint
1256 	flow_cookie = flow_cookie;
1257 	channel_cookie = channel_cookie;
1258 #endif
1259 	bzero((char *)&ft, ft_size);
1260 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
1261 	switch (flow_spec->flow_type) {
1262 		case FSPEC_TCPIP4:
1263 			class_cfg =
1264 			    p_class_cfgp->class_cfg[TCAM_CLASS_TCP_IPV4];
1265 			if (class_cfg & NXGE_CLASS_FLOW_USE_PROTO)
1266 				ft.ip_proto = IPPROTO_TCP;
1267 			if (class_cfg & NXGE_CLASS_FLOW_USE_IPSRC)
1268 				ft.ip4_saddr =
1269 				flow_res->flow_spec.uh.tcpip4spec.ip4src;
1270 
1271 			if (class_cfg & NXGE_CLASS_FLOW_USE_IPDST)
1272 				ft.ip4_daddr =
1273 				flow_res->flow_spec.uh.tcpip4spec.ip4dst;
1274 
1275 			if (class_cfg & NXGE_CLASS_FLOW_USE_SRC_PORT)
1276 				ft.ip_src_port =
1277 				flow_res->flow_spec.uh.tcpip4spec.psrc;
1278 
1279 			if (class_cfg & NXGE_CLASS_FLOW_USE_DST_PORT)
1280 				ft.ip_dst_port =
1281 					flow_res->flow_spec.uh.tcpip4spec.pdst;
1282 
1283 			break;
1284 
1285 		case FSPEC_UDPIP4:
1286 			class_cfg =
1287 			    p_class_cfgp->class_cfg[TCAM_CLASS_UDP_IPV4];
1288 			if (class_cfg & NXGE_CLASS_FLOW_USE_PROTO)
1289 				ft.ip_proto = IPPROTO_UDP;
1290 
1291 			if (class_cfg & NXGE_CLASS_FLOW_USE_IPSRC)
1292 				ft.ip4_saddr =
1293 				    flow_res->flow_spec.uh.udpip4spec.ip4src;
1294 
1295 			if (class_cfg & NXGE_CLASS_FLOW_USE_IPDST)
1296 				ft.ip4_daddr =
1297 				    flow_res->flow_spec.uh.udpip4spec.ip4dst;
1298 
1299 			if (class_cfg & NXGE_CLASS_FLOW_USE_SRC_PORT)
1300 				ft.ip_src_port =
1301 				    flow_res->flow_spec.uh.udpip4spec.psrc;
1302 
1303 			if (class_cfg & NXGE_CLASS_FLOW_USE_DST_PORT)
1304 				ft.ip_dst_port =
1305 				    flow_res->flow_spec.uh.udpip4spec.pdst;
1306 
1307 			break;
1308 
1309 		default:
1310 			return (NXGE_ERROR);
1311 	}
1312 
1313 	*H1 = nxge_compute_h1(p_class_cfgp->init_h1,
1314 	    (uint32_t *)&ft, ft_size) & 0xfffff;
1315 	*H2 = nxge_compute_h2(p_class_cfgp->init_h2,
1316 	    (uint8_t *)&ft, ft_size);
1317 
1318 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_flow_get_hash"));
1319 	return (NXGE_OK);
1320 }
1321 
1322 /* ARGSUSED */
1323 nxge_status_t
1324 nxge_add_fcram_entry(p_nxge_t nxgep, flow_resource_t *flow_res)
1325 {
1326 
1327 	uint32_t H1;
1328 	uint16_t H2;
1329 	nxge_status_t status = NXGE_OK;
1330 
1331 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_add_fcram_entry"));
1332 	status = nxge_flow_get_hash(nxgep, flow_res, &H1, &H2);
1333 	if (status != NXGE_OK) {
1334 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1335 			    " nxge_add_fcram_entry failed "));
1336 		return (status);
1337 	}
1338 
1339 		/* add code to find rdc grp */
1340 		/* add code to determine the action */
1341 		/* Determine type of match (exact, optimistic etc ...) */
1342 		/* Compose hash entry */
1343 		/* add hash entry */
1344 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_add_fcram_entry"));
1345 	return (NXGE_OK);
1346 }
1347 
1348 
1349 /*
1350  * Already decided this flow goes into the tcam
1351  */
1352 
1353 nxge_status_t
1354 nxge_add_tcam_entry(p_nxge_t nxgep, flow_resource_t *flow_res)
1355 {
1356 
1357 	npi_handle_t handle;
1358 	intptr_t channel_cookie;
1359 	intptr_t flow_cookie;
1360 	flow_spec_t *flow_spec;
1361 	npi_status_t rs = NPI_SUCCESS;
1362 	tcam_entry_t tcam_ptr;
1363 	tcam_location_t location = 0;
1364 	uint8_t offset, rdc_grp;
1365 	p_nxge_hw_list_t	hw_p;
1366 
1367 
1368 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_add_tcam_entry"));
1369 	handle = nxgep->npi_reg_handle;
1370 
1371 	bzero((void*)&tcam_ptr, sizeof (tcam_entry_t));
1372 	flow_spec = (flow_spec_t *)&flow_res->flow_spec;
1373 	flow_cookie = flow_res->flow_cookie;
1374 	channel_cookie = flow_res->channel_cookie;
1375 
1376 	switch (flow_spec->flow_type) {
1377 		case FSPEC_TCPIP4:
1378 
1379 			nxge_fill_tcam_entry_tcp(nxgep, flow_spec, &tcam_ptr);
1380 			location = nxge_get_tcam_location(nxgep,
1381 						    TCAM_CLASS_TCP_IPV4);
1382 			rdc_grp = nxge_get_rdc_group(nxgep, TCAM_CLASS_TCP_IPV4,
1383 							    flow_cookie);
1384 			offset = nxge_get_rdc_offset(nxgep, TCAM_CLASS_TCP_IPV4,
1385 							    channel_cookie);
1386 
1387 			break;
1388 
1389 
1390 		case FSPEC_UDPIP4:
1391 
1392 			nxge_fill_tcam_entry_udp(nxgep, flow_spec, &tcam_ptr);
1393 			location = nxge_get_tcam_location(nxgep,
1394 						    TCAM_CLASS_UDP_IPV4);
1395 			rdc_grp = nxge_get_rdc_group(nxgep,
1396 					    TCAM_CLASS_UDP_IPV4,
1397 					    flow_cookie);
1398 			offset = nxge_get_rdc_offset(nxgep,
1399 					    TCAM_CLASS_UDP_IPV4,
1400 					    channel_cookie);
1401 
1402 			break;
1403 
1404 
1405 		case FSPEC_TCPIP6:
1406 
1407 			nxge_fill_tcam_entry_tcp_ipv6(nxgep,
1408 						    flow_spec, &tcam_ptr);
1409 			location = nxge_get_tcam_location(nxgep,
1410 						    TCAM_CLASS_TCP_IPV6);
1411 			rdc_grp = nxge_get_rdc_group(nxgep, TCAM_CLASS_TCP_IPV6,
1412 							    flow_cookie);
1413 			offset = nxge_get_rdc_offset(nxgep, TCAM_CLASS_TCP_IPV6,
1414 							    channel_cookie);
1415 
1416 			break;
1417 
1418 		case FSPEC_UDPIP6:
1419 
1420 			nxge_fill_tcam_entry_udp_ipv6(nxgep,
1421 						    flow_spec, &tcam_ptr);
1422 
1423 			location = nxge_get_tcam_location(nxgep,
1424 						    TCAM_CLASS_UDP_IPV6);
1425 			rdc_grp = nxge_get_rdc_group(nxgep,
1426 					    TCAM_CLASS_UDP_IPV6,
1427 					    channel_cookie);
1428 			offset = nxge_get_rdc_offset(nxgep,
1429 					    TCAM_CLASS_UDP_IPV6,
1430 					    flow_cookie);
1431 
1432 			break;
1433 
1434 		case FSPEC_SCTPIP4:
1435 
1436 			nxge_fill_tcam_entry_sctp(nxgep, flow_spec, &tcam_ptr);
1437 			location = nxge_get_tcam_location(nxgep,
1438 						    TCAM_CLASS_SCTP_IPV4);
1439 			rdc_grp = nxge_get_rdc_group(nxgep,
1440 						    TCAM_CLASS_SCTP_IPV4,
1441 						    channel_cookie);
1442 			offset = nxge_get_rdc_offset(nxgep,
1443 						    TCAM_CLASS_SCTP_IPV4,
1444 						    flow_cookie);
1445 
1446 			break;
1447 
1448 		case FSPEC_SCTPIP6:
1449 
1450 			nxge_fill_tcam_entry_sctp_ipv6(nxgep,
1451 						    flow_spec, &tcam_ptr);
1452 			location = nxge_get_tcam_location(nxgep,
1453 						    TCAM_CLASS_SCTP_IPV4);
1454 			rdc_grp = nxge_get_rdc_group(nxgep,
1455 						    TCAM_CLASS_SCTP_IPV6,
1456 						    channel_cookie);
1457 			offset = nxge_get_rdc_offset(nxgep,
1458 						    TCAM_CLASS_SCTP_IPV6,
1459 						    flow_cookie);
1460 
1461 			break;
1462 
1463 
1464 		default:
1465 			return (NXGE_OK);
1466 	}
1467 
1468 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1469 			    " nxge_add_tcam_entry write"
1470 			    " for location %d offset %d", location, offset));
1471 
1472 	if ((hw_p = nxgep->nxge_hw_p) == NULL) {
1473 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1474 			" nxge_add_tcam_entry:"
1475 			" common hardware not set",
1476 			nxgep->niu_type));
1477 		return (NXGE_ERROR);
1478 	}
1479 	MUTEX_ENTER(&hw_p->nxge_tcam_lock);
1480 	rs = npi_fflp_tcam_entry_write(handle,
1481 					    location, &tcam_ptr);
1482 
1483 	if (rs & NPI_FFLP_ERROR) {
1484 		MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1485 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1486 				    " nxge_add_tcam_entry write"
1487 				    " failed for location %d",
1488 				    location));
1489 		return (NXGE_ERROR | rs);
1490 	}
1491 	tcam_ptr.match_action.value = 0;
1492 	tcam_ptr.match_action.bits.ldw.rdctbl = rdc_grp;
1493 	tcam_ptr.match_action.bits.ldw.offset = offset;
1494 	tcam_ptr.match_action.bits.ldw.tres =
1495 		TRES_TERM_OVRD_L2RDC;
1496 	if (channel_cookie == -1)
1497 		tcam_ptr.match_action.bits.ldw.disc = 1;
1498 
1499 	rs = npi_fflp_tcam_asc_ram_entry_write(handle,
1500 					    location,
1501 					    tcam_ptr.match_action.value);
1502 
1503 	if (rs & NPI_FFLP_ERROR) {
1504 		MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1505 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1506 				    " nxge_add_tcam_entry write"
1507 				    " failed for ASC RAM location %d",
1508 				    location));
1509 		return (NXGE_ERROR | rs);
1510 	}
1511 
1512 	bcopy((void *)&tcam_ptr,
1513 		    (void *)&nxgep->classifier.tcam_entries[location].tce,
1514 		    sizeof (tcam_entry_t));
1515 
1516 	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1517 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_add_tcam_entry"));
1518 	return (NXGE_OK);
1519 }
1520 
1521 
1522 static nxge_status_t
1523 nxge_tcam_handle_ip_fragment(p_nxge_t nxgep)
1524 {
1525 	tcam_entry_t tcam_ptr;
1526 	tcam_location_t location;
1527 	uint8_t class;
1528 	uint32_t class_config;
1529 	npi_handle_t handle;
1530 	npi_status_t rs = NPI_SUCCESS;
1531 	p_nxge_hw_list_t	hw_p;
1532 	nxge_status_t status = NXGE_OK;
1533 
1534 	handle = nxgep->npi_reg_handle;
1535 	class = 0;
1536 	bzero((void*)&tcam_ptr, sizeof (tcam_entry_t));
1537 	tcam_ptr.ip4_noport_key = 1;
1538 	tcam_ptr.ip4_noport_mask = 1;
1539 	location = nxgep->function_num;
1540 	nxgep->classifier.fragment_bug_location = location;
1541 
1542 	if ((hw_p = nxgep->nxge_hw_p) == NULL) {
1543 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1544 			" nxge_tcam_handle_ip_fragment:"
1545 			" common hardware not set",
1546 			nxgep->niu_type));
1547 		return (NXGE_ERROR);
1548 	}
1549 
1550 	MUTEX_ENTER(&hw_p->nxge_tcam_lock);
1551 	rs = npi_fflp_tcam_entry_write(handle,
1552 					    location, &tcam_ptr);
1553 
1554 	if (rs & NPI_FFLP_ERROR) {
1555 		MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1556 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1557 				    " nxge_tcam_handle_ip_fragment "
1558 				    " tcam_entry write"
1559 				    " failed for location %d",
1560 				    location));
1561 		return (NXGE_ERROR);
1562 	}
1563 
1564 	tcam_ptr.match_action.bits.ldw.rdctbl = nxgep->class_config.mac_rdcgrp;
1565 	tcam_ptr.match_action.bits.ldw.offset = 0; /* use the default */
1566 	tcam_ptr.match_action.bits.ldw.tres =
1567 		TRES_TERM_USE_OFFSET;
1568 
1569 	rs = npi_fflp_tcam_asc_ram_entry_write(handle,
1570 					    location,
1571 					    tcam_ptr.match_action.value);
1572 
1573 	if (rs & NPI_FFLP_ERROR) {
1574 		MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1575 		NXGE_DEBUG_MSG((nxgep,
1576 				    FFLP_CTL,
1577 				    " nxge_tcam_handle_ip_fragment "
1578 				    " tcam_entry write"
1579 				    " failed for ASC RAM location %d",
1580 				    location));
1581 		return (NXGE_ERROR);
1582 	}
1583 
1584 	bcopy((void *)&tcam_ptr,
1585 		    (void *)&nxgep->classifier.tcam_entries[location].tce,
1586 		    sizeof (tcam_entry_t));
1587 	for (class = TCAM_CLASS_TCP_IPV4;
1588 		    class <= TCAM_CLASS_SCTP_IPV6; class++) {
1589 		class_config = nxgep->class_config.class_cfg[class];
1590 		class_config |= NXGE_CLASS_TCAM_LOOKUP;
1591 		status = nxge_fflp_ip_class_config(nxgep, class, class_config);
1592 
1593 		if (status & NPI_FFLP_ERROR) {
1594 			MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1595 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1596 					"nxge_tcam_handle_ip_fragment "
1597 					"nxge_fflp_ip_class_config failed "
1598 					" class %d config %x ",
1599 					class, class_config));
1600 			return (NXGE_ERROR);
1601 		}
1602 	}
1603 
1604 	rs = npi_fflp_cfg_tcam_enable(handle);
1605 	if (rs & NPI_FFLP_ERROR) {
1606 		MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1607 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1608 				"nxge_tcam_handle_ip_fragment "
1609 			    " nxge_fflp_config_tcam_enable failed"));
1610 		return (NXGE_ERROR);
1611 	}
1612 
1613 	MUTEX_EXIT(&hw_p->nxge_tcam_lock);
1614 	return (NXGE_OK);
1615 }
1616 
1617 #ifdef lint
1618 /* ARGSUSED */
1619 #endif
1620 static int
1621 nxge_flow_need_hash_lookup(p_nxge_t nxgep,
1622 			    flow_resource_t *flow_res)
1623 {
1624 	return (0);
1625 
1626 }
1627 
1628 
1629 nxge_status_t
1630 nxge_add_flow(p_nxge_t nxgep, flow_resource_t *flow_res)
1631 {
1632 
1633 	int insert_hash = 0;
1634 	nxge_status_t status = NXGE_OK;
1635 
1636 	if (nxgep->niu_type == NEPTUNE) {
1637 			/* determine whether to do TCAM or Hash flow */
1638 		insert_hash = nxge_flow_need_hash_lookup(nxgep, flow_res);
1639 	}
1640 
1641 	if (insert_hash) {
1642 		status = nxge_add_fcram_entry(nxgep, flow_res);
1643 	} else {
1644 		status = nxge_add_tcam_entry(nxgep, flow_res);
1645 	}
1646 
1647 	return (status);
1648 }
1649 
1650 #ifdef lint
1651 /* ARGSUSED */
1652 #endif
1653 void
1654 nxge_put_tcam(p_nxge_t nxgep, p_mblk_t mp)
1655 {
1656 
1657 	flow_resource_t *fs;
1658 	fs = (flow_resource_t *)mp->b_rptr;
1659 
1660 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1661 			    "nxge_put_tcam addr fs $%p  type %x offset %x",
1662 			    fs, fs->flow_spec.flow_type, fs->channel_cookie));
1663 
1664 	(void) nxge_add_tcam_entry(nxgep, fs);
1665 }
1666 
1667 
1668 nxge_status_t
1669 nxge_fflp_config_tcam_enable(p_nxge_t nxgep)
1670 {
1671 	npi_handle_t handle = nxgep->npi_reg_handle;
1672 	npi_status_t rs = NPI_SUCCESS;
1673 
1674 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_config_tcam_enable"));
1675 	rs = npi_fflp_cfg_tcam_enable(handle);
1676 	if (rs & NPI_FFLP_ERROR) {
1677 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1678 			    " nxge_fflp_config_tcam_enable failed"));
1679 		return (NXGE_ERROR | rs);
1680 	}
1681 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " <== nxge_fflp_config_tcam_enable"));
1682 	return (NXGE_OK);
1683 }
1684 
1685 nxge_status_t
1686 nxge_fflp_config_tcam_disable(p_nxge_t nxgep)
1687 {
1688 	npi_handle_t handle = nxgep->npi_reg_handle;
1689 	npi_status_t rs = NPI_SUCCESS;
1690 
1691 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1692 			    " ==> nxge_fflp_config_tcam_disable"));
1693 	rs = npi_fflp_cfg_tcam_disable(handle);
1694 	if (rs & NPI_FFLP_ERROR) {
1695 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1696 			    " nxge_fflp_config_tcam_disable failed"));
1697 		return (NXGE_ERROR | rs);
1698 	}
1699 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1700 			    " <== nxge_fflp_config_tcam_disable"));
1701 	return (NXGE_OK);
1702 }
1703 
1704 
1705 
1706 nxge_status_t
1707 nxge_fflp_config_hash_lookup_enable(p_nxge_t nxgep)
1708 {
1709 	npi_handle_t handle = nxgep->npi_reg_handle;
1710 	npi_status_t rs = NPI_SUCCESS;
1711 	p_nxge_dma_pt_cfg_t	p_dma_cfgp;
1712 	p_nxge_hw_pt_cfg_t	p_cfgp;
1713 	uint8_t		partition;
1714 
1715 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1716 			    " ==> nxge_fflp_config_hash_lookup_enable"));
1717 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
1718 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
1719 
1720 
1721 	for (partition = p_cfgp->start_rdc_grpid;
1722 		partition < p_cfgp->max_rdc_grpids; partition++) {
1723 		rs = npi_fflp_cfg_fcram_partition_enable(handle,
1724 							    partition);
1725 		if (rs != NPI_SUCCESS) {
1726 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1727 					" nxge_fflp_config_hash_lookup_enable"
1728 					"failed FCRAM partition"
1729 					" enable for partition %d ",
1730 					partition));
1731 			return (NXGE_ERROR | rs);
1732 		}
1733 	}
1734 
1735 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1736 			    " <== nxge_fflp_config_hash_lookup_enable"));
1737 	return (NXGE_OK);
1738 }
1739 
1740 nxge_status_t
1741 nxge_fflp_config_hash_lookup_disable(p_nxge_t nxgep)
1742 {
1743 	npi_handle_t handle = nxgep->npi_reg_handle;
1744 	npi_status_t rs = NPI_SUCCESS;
1745 	p_nxge_dma_pt_cfg_t	p_dma_cfgp;
1746 	p_nxge_hw_pt_cfg_t	p_cfgp;
1747 	uint8_t		partition;
1748 
1749 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1750 			    " ==> nxge_fflp_config_hash_lookup_disable"));
1751 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
1752 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
1753 
1754 
1755 	for (partition = p_cfgp->start_rdc_grpid;
1756 		partition < p_cfgp->max_rdc_grpids; partition++) {
1757 		rs = npi_fflp_cfg_fcram_partition_disable(handle,
1758 							    partition);
1759 		if (rs != NPI_SUCCESS) {
1760 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1761 					" nxge_fflp_config_hash_lookup_disable"
1762 					" failed FCRAM partition"
1763 					" disable for partition %d ",
1764 					partition));
1765 			return (NXGE_ERROR | rs);
1766 		}
1767 	}
1768 
1769 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1770 			    " <== nxge_fflp_config_hash_lookup_disable"));
1771 	return (NXGE_OK);
1772 }
1773 
1774 
1775 nxge_status_t
1776 nxge_fflp_config_llc_snap_enable(p_nxge_t nxgep)
1777 {
1778 	npi_handle_t handle = nxgep->npi_reg_handle;
1779 	npi_status_t rs = NPI_SUCCESS;
1780 
1781 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1782 			    " ==> nxge_fflp_config_llc_snap_enable"));
1783 	rs = npi_fflp_cfg_llcsnap_enable(handle);
1784 	if (rs & NPI_FFLP_ERROR) {
1785 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1786 			    " nxge_fflp_config_llc_snap_enable failed"));
1787 		return (NXGE_ERROR | rs);
1788 	}
1789 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1790 			    " <== nxge_fflp_config_llc_snap_enable"));
1791 	return (NXGE_OK);
1792 }
1793 
1794 nxge_status_t
1795 nxge_fflp_config_llc_snap_disable(p_nxge_t nxgep)
1796 {
1797 	npi_handle_t handle = nxgep->npi_reg_handle;
1798 	npi_status_t rs = NPI_SUCCESS;
1799 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1800 			    " ==> nxge_fflp_config_llc_snap_disable"));
1801 	rs = npi_fflp_cfg_llcsnap_disable(handle);
1802 	if (rs & NPI_FFLP_ERROR) {
1803 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1804 			    " nxge_fflp_config_llc_snap_disable failed"));
1805 		return (NXGE_ERROR | rs);
1806 	}
1807 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1808 			    " <== nxge_fflp_config_llc_snap_disable"));
1809 	return (NXGE_OK);
1810 }
1811 
1812 
1813 
1814 nxge_status_t
1815 nxge_fflp_ip_usr_class_config(p_nxge_t nxgep, tcam_class_t class,
1816 			    uint32_t config)
1817 {
1818 	npi_status_t rs = NPI_SUCCESS;
1819 	npi_handle_t handle = nxgep->npi_reg_handle;
1820 	uint8_t tos, tos_mask, proto, ver = 0;
1821 	uint8_t class_enable = 0;
1822 
1823 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_ip_usr_class_config"));
1824 
1825 	tos = (config & NXGE_CLASS_CFG_IP_TOS_MASK) >>
1826 			    NXGE_CLASS_CFG_IP_TOS_SHIFT;
1827 	tos_mask = (config & NXGE_CLASS_CFG_IP_TOS_MASK_MASK) >>
1828 		NXGE_CLASS_CFG_IP_TOS_MASK_SHIFT;
1829 	proto = (config & NXGE_CLASS_CFG_IP_PROTO_MASK) >>
1830 		NXGE_CLASS_CFG_IP_PROTO_SHIFT;
1831 
1832 	if (config & NXGE_CLASS_CFG_IP_IPV6_MASK)
1833 		ver = 1;
1834 	if (config & NXGE_CLASS_CFG_IP_ENABLE_MASK)
1835 		class_enable = 1;
1836 
1837 	rs = npi_fflp_cfg_ip_usr_cls_set(handle, class, tos, tos_mask,
1838 		    proto, ver);
1839 	if (rs & NPI_FFLP_ERROR) {
1840 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1841 			" nxge_fflp_ip_usr_class_config"
1842 			" for class %d failed ", class));
1843 		return (NXGE_ERROR | rs);
1844 	}
1845 
1846 	if (class_enable)
1847 		rs = npi_fflp_cfg_ip_usr_cls_enable(handle, class);
1848 	else
1849 		rs = npi_fflp_cfg_ip_usr_cls_disable(handle, class);
1850 
1851 	if (rs & NPI_FFLP_ERROR) {
1852 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1853 			    " nxge_fflp_ip_usr_class_config"
1854 			    " TCAM enable/disable for class %d failed ",
1855 			    class));
1856 		return (NXGE_ERROR | rs);
1857 	}
1858 
1859 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_usr_class_config"));
1860 	return (NXGE_OK);
1861 }
1862 
1863 
1864 
1865 nxge_status_t
1866 nxge_fflp_ip_class_config(p_nxge_t nxgep, tcam_class_t class,
1867 				    uint32_t config)
1868 {
1869 
1870 	uint32_t class_config;
1871 	nxge_status_t t_status = NXGE_OK;
1872 	nxge_status_t f_status = NXGE_OK;
1873 	p_nxge_class_pt_cfg_t 	p_class_cfgp;
1874 
1875 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_ip_class_config"));
1876 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
1877 	class_config = p_class_cfgp->class_cfg[class];
1878 
1879 	if (class_config != config) {
1880 		p_class_cfgp->class_cfg[class] = config;
1881 		class_config = config;
1882 	}
1883 
1884 	t_status = nxge_cfg_tcam_ip_class(nxgep, class, class_config);
1885 	f_status = nxge_cfg_ip_cls_flow_key(nxgep, class, class_config);
1886 
1887 	if (t_status & NPI_FFLP_ERROR) {
1888 		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1889 				    " nxge_fflp_ip_class_config %x"
1890 				    " for class %d tcam failed", config,
1891 					class));
1892 		return (t_status);
1893 	}
1894 
1895 	if (f_status & NPI_FFLP_ERROR) {
1896 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1897 				    " nxge_fflp_ip_class_config %x"
1898 				    " for class %d flow key failed", config,
1899 					class));
1900 		return (f_status);
1901 	}
1902 
1903 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_class_config"));
1904 	return (NXGE_OK);
1905 }
1906 
1907 
1908 nxge_status_t
1909 nxge_fflp_ip_class_config_get(p_nxge_t nxgep, tcam_class_t class,
1910 				    uint32_t *config)
1911 {
1912 
1913 	uint32_t t_class_config, f_class_config;
1914 	int t_status = NXGE_OK;
1915 	int f_status = NXGE_OK;
1916 
1917 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, " ==> nxge_fflp_ip_class_config"));
1918 	t_class_config = f_class_config = 0;
1919 	t_status = nxge_cfg_tcam_ip_class_get(nxgep, class, &t_class_config);
1920 	f_status = nxge_cfg_ip_cls_flow_key_get(nxgep, class, &f_class_config);
1921 
1922 
1923 	if (t_status & NPI_FFLP_ERROR) {
1924 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1925 				    " nxge_fflp_ip_class_config_get  "
1926 				    " for class %d tcam failed", class));
1927 		return (t_status);
1928 	}
1929 
1930 	if (f_status & NPI_FFLP_ERROR) {
1931 		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1932 				    " nxge_fflp_ip_class_config_get  "
1933 				    " for class %d flow key failed", class));
1934 		return (f_status);
1935 	}
1936 
1937 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
1938 			    " nxge_fflp_ip_class_config tcam %x flow %x",
1939 			    t_class_config, f_class_config));
1940 
1941 	*config = t_class_config | f_class_config;
1942 
1943 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_class_config_get"));
1944 	return (NXGE_OK);
1945 }
1946 
1947 
1948 nxge_status_t
1949 nxge_fflp_ip_class_config_all(p_nxge_t nxgep)
1950 {
1951 
1952 	uint32_t class_config;
1953 	tcam_class_t class;
1954 
1955 #ifdef	NXGE_DEBUG
1956 	int status = NXGE_OK;
1957 #endif
1958 
1959 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_ip_class_config"));
1960 	for (class = TCAM_CLASS_TCP_IPV4;
1961 		    class <= TCAM_CLASS_SCTP_IPV6; class++) {
1962 		class_config = nxgep->class_config.class_cfg[class];
1963 #ifndef	NXGE_DEBUG
1964 		(void) nxge_fflp_ip_class_config(nxgep, class, class_config);
1965 #else
1966 		status = nxge_fflp_ip_class_config(nxgep, class, class_config);
1967 		if (status & NPI_FFLP_ERROR) {
1968 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1969 					"nxge_fflp_ip_class_config failed "
1970 					" class %d config %x ",
1971 					class, class_config));
1972 		}
1973 #endif
1974 	}
1975 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_ip_class_config"));
1976 	return (NXGE_OK);
1977 }
1978 
1979 
1980 
1981 nxge_status_t
1982 nxge_fflp_config_vlan_table(p_nxge_t nxgep, uint16_t vlan_id)
1983 {
1984 	uint8_t port, rdc_grp;
1985 	npi_handle_t handle;
1986 	npi_status_t rs = NPI_SUCCESS;
1987 	uint8_t priority = 1;
1988 	p_nxge_mv_cfg_t vlan_table;
1989 	p_nxge_class_pt_cfg_t 	p_class_cfgp;
1990 	p_nxge_hw_list_t	hw_p;
1991 
1992 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_config_vlan_table"));
1993 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
1994 	handle = nxgep->npi_reg_handle;
1995 	vlan_table = p_class_cfgp->vlan_tbl;
1996 	port = nxgep->function_num;
1997 
1998 	if (vlan_table[vlan_id].flag == 0) {
1999 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2000 				    " nxge_fflp_config_vlan_table"
2001 				    " vlan id is not configured %d", vlan_id));
2002 		return (NXGE_ERROR);
2003 	}
2004 
2005 	if ((hw_p = nxgep->nxge_hw_p) == NULL) {
2006 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2007 			" nxge_fflp_config_vlan_table:"
2008 			" common hardware not set",
2009 			nxgep->niu_type));
2010 		return (NXGE_ERROR);
2011 	}
2012 
2013 	MUTEX_ENTER(&hw_p->nxge_vlan_lock);
2014 	rdc_grp = vlan_table[vlan_id].rdctbl;
2015 	rs = npi_fflp_cfg_enet_vlan_table_assoc(handle,
2016 						    port, vlan_id,
2017 						    rdc_grp, priority);
2018 
2019 	MUTEX_EXIT(&hw_p->nxge_vlan_lock);
2020 	if (rs & NPI_FFLP_ERROR) {
2021 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2022 					"nxge_fflp_config_vlan_table failed "
2023 					" Port %d vlan_id %d rdc_grp %d",
2024 					port, vlan_id, rdc_grp));
2025 		return (NXGE_ERROR | rs);
2026 	}
2027 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_fflp_config_vlan_table"));
2028 	return (NXGE_OK);
2029 }
2030 
2031 nxge_status_t
2032 nxge_fflp_update_hw(p_nxge_t nxgep)
2033 {
2034 
2035 	nxge_status_t status = NXGE_OK;
2036 	p_nxge_param_t pa;
2037 	uint64_t cfgd_vlans;
2038 	uint64_t *val_ptr;
2039 	int i;
2040 	int num_macs;
2041 	uint8_t alt_mac;
2042 	nxge_param_map_t *p_map;
2043 
2044 	p_nxge_mv_cfg_t vlan_table;
2045 	p_nxge_class_pt_cfg_t 	p_class_cfgp;
2046 	p_nxge_dma_pt_cfg_t	p_all_cfgp;
2047 	p_nxge_hw_pt_cfg_t	p_cfgp;
2048 
2049 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_fflp_update_hw"));
2050 	p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config;
2051 	p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2052 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config;
2053 
2054 	status = nxge_fflp_set_hash1(nxgep, p_class_cfgp->init_h1);
2055 	if (status != NXGE_OK) {
2056 		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
2057 		    "nxge_fflp_set_hash1 Failed"));
2058 		return (NXGE_ERROR);
2059 	}
2060 
2061 	status = nxge_fflp_set_hash2(nxgep, p_class_cfgp->init_h2);
2062 	if (status != NXGE_OK) {
2063 		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
2064 		    "nxge_fflp_set_hash2 Failed"));
2065 		return (NXGE_ERROR);
2066 	}
2067 
2068 	vlan_table = p_class_cfgp->vlan_tbl;
2069 
2070 /* configure vlan tables */
2071 	pa = (p_nxge_param_t)&nxgep->param_arr[param_vlan_2rdc_grp];
2072 	val_ptr = (uint64_t *)pa->value;
2073 	cfgd_vlans = ((pa->type &  NXGE_PARAM_ARRAY_CNT_MASK) >>
2074 			    NXGE_PARAM_ARRAY_CNT_SHIFT);
2075 
2076 	for (i = 0; i < cfgd_vlans; i++) {
2077 		p_map = (nxge_param_map_t *)&val_ptr[i];
2078 		if (vlan_table[p_map->param_id].flag) {
2079 			status = nxge_fflp_config_vlan_table(nxgep,
2080 							    p_map->param_id);
2081 			if (status != NXGE_OK) {
2082 				NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
2083 				    "nxge_fflp_config_vlan_table Failed"));
2084 				return (NXGE_ERROR);
2085 			}
2086 		}
2087 	}
2088 		/* config MAC addresses */
2089 	num_macs = p_cfgp->max_macs;
2090 	pa = (p_nxge_param_t)&nxgep->param_arr[param_mac_2rdc_grp];
2091 	val_ptr = (uint64_t *)pa->value;
2092 
2093 	for (alt_mac = 0; alt_mac < num_macs; alt_mac++) {
2094 		if (p_class_cfgp->mac_host_info[alt_mac].flag) {
2095 			status = nxge_logical_mac_assign_rdc_table(nxgep,
2096 								    alt_mac);
2097 			if (status != NXGE_OK) {
2098 				NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
2099 				"nxge_logical_mac_assign_rdc_table Failed"));
2100 				return (NXGE_ERROR);
2101 			}
2102 		}
2103 	}
2104 		/* Config Hash values */
2105 		/* config classess */
2106 	status = nxge_fflp_ip_class_config_all(nxgep);
2107 	if (status != NXGE_OK) {
2108 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2109 		    "nxge_fflp_ip_class_config_all Failed"));
2110 		return (NXGE_ERROR);
2111 	}
2112 
2113 	return (NXGE_OK);
2114 }
2115 
2116 
2117 nxge_status_t
2118 nxge_classify_init_hw(p_nxge_t nxgep)
2119 {
2120 	nxge_status_t status = NXGE_OK;
2121 
2122 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "==> nxge_classify_init_hw"));
2123 
2124 	if (nxgep->classifier.state & NXGE_FFLP_HW_INIT) {
2125 		NXGE_DEBUG_MSG((nxgep, FFLP_CTL,
2126 		    "nxge_classify_init_hw already init"));
2127 		return (NXGE_OK);
2128 	}
2129 
2130 
2131 /* Now do a real configuration */
2132 	status = nxge_fflp_update_hw(nxgep);
2133 	if (status != NXGE_OK) {
2134 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2135 		    "nxge_fflp_update_hw failed"));
2136 		return (NXGE_ERROR);
2137 	}
2138 /* Init RDC tables? ? who should do that? rxdma or fflp ? */
2139 /* attach rdc table to the MAC port. */
2140 	status = nxge_main_mac_assign_rdc_table(nxgep);
2141 	if (status != NXGE_OK) {
2142 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2143 		    "nxge_main_mac_assign_rdc_table failed"));
2144 		return (NXGE_ERROR);
2145 	}
2146 	status = nxge_multicast_mac_assign_rdc_table(nxgep);
2147 	if (status != NXGE_OK) {
2148 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2149 		    "nxge_multicast_mac_assign_rdc_table failed"));
2150 		return (NXGE_ERROR);
2151 	}
2152 
2153 	status = nxge_tcam_handle_ip_fragment(nxgep);
2154 	if (status != NXGE_OK) {
2155 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2156 				    "nxge_tcam_handle_ip_fragment failed"));
2157 		return (NXGE_ERROR);
2158 	}
2159 
2160 	nxgep->classifier.state |= NXGE_FFLP_HW_INIT;
2161 
2162 	NXGE_DEBUG_MSG((nxgep, FFLP_CTL, "<== nxge_classify_init_hw"));
2163 
2164 	return (NXGE_OK);
2165 
2166 }
2167 
2168 nxge_status_t
2169 nxge_fflp_handle_sys_errors(p_nxge_t nxgep)
2170 {
2171 	npi_handle_t		handle;
2172 	p_nxge_fflp_stats_t	statsp;
2173 	uint8_t			portn, rdc_grp;
2174 	p_nxge_dma_pt_cfg_t	p_dma_cfgp;
2175 	p_nxge_hw_pt_cfg_t	p_cfgp;
2176 	vlan_par_err_t		vlan_err;
2177 	tcam_err_t		tcam_err;
2178 	hash_lookup_err_log1_t	fcram1_err;
2179 	hash_lookup_err_log2_t	fcram2_err;
2180 	hash_tbl_data_log_t	fcram_err;
2181 
2182 	handle = nxgep->npi_handle;
2183 	statsp = (p_nxge_fflp_stats_t)&nxgep->statsp->fflp_stats;
2184 	portn = nxgep->mac.portnum;
2185 
2186 	/*
2187 	 * need to read the fflp error registers to figure out
2188 	 * what the error is
2189 	 */
2190 	npi_fflp_vlan_error_get(handle, &vlan_err);
2191 	npi_fflp_tcam_error_get(handle, &tcam_err);
2192 
2193 	if (vlan_err.bits.ldw.m_err || vlan_err.bits.ldw.err) {
2194 		NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2195 				    " vlan table parity error on port %d"
2196 				    " addr: 0x%x data: 0x%x",
2197 				    portn, vlan_err.bits.ldw.addr,
2198 				    vlan_err.bits.ldw.data));
2199 		statsp->vlan_parity_err++;
2200 
2201 		if (vlan_err.bits.ldw.m_err) {
2202 			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2203 				    " vlan table multiple errors on port %d",
2204 				    portn));
2205 		}
2206 
2207 		statsp->errlog.vlan = (uint32_t)vlan_err.value;
2208 		NXGE_FM_REPORT_ERROR(nxgep, NULL, NULL,
2209 					NXGE_FM_EREPORT_FFLP_VLAN_PAR_ERR);
2210 		npi_fflp_vlan_error_clear(handle);
2211 	}
2212 
2213 	if (tcam_err.bits.ldw.err) {
2214 		if (tcam_err.bits.ldw.p_ecc != 0) {
2215 			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2216 				    " TCAM ECC error on port %d"
2217 				    " TCAM entry: 0x%x syndrome: 0x%x",
2218 				    portn, tcam_err.bits.ldw.addr,
2219 				    tcam_err.bits.ldw.syndrome));
2220 			statsp->tcam_ecc_err++;
2221 		} else {
2222 			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2223 				    " TCAM Parity error on port %d"
2224 				    " addr: 0x%x parity value: 0x%x",
2225 				    portn, tcam_err.bits.ldw.addr,
2226 				    tcam_err.bits.ldw.syndrome));
2227 			statsp->tcam_parity_err++;
2228 		}
2229 
2230 		if (tcam_err.bits.ldw.mult) {
2231 			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2232 				    " TCAM Multiple errors on port %d",
2233 				    portn));
2234 		} else {
2235 			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2236 					    " TCAM PIO error on port %d",
2237 					    portn));
2238 		}
2239 
2240 		statsp->errlog.tcam = (uint32_t)tcam_err.value;
2241 		NXGE_FM_REPORT_ERROR(nxgep, NULL, NULL,
2242 					NXGE_FM_EREPORT_FFLP_TCAM_ERR);
2243 		npi_fflp_tcam_error_clear(handle);
2244 	}
2245 
2246 	p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config;
2247 	p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
2248 
2249 	for (rdc_grp = p_cfgp->start_rdc_grpid;
2250 		    rdc_grp < p_cfgp->max_rdc_grpids; rdc_grp++) {
2251 		npi_fflp_fcram_error_get(handle, &fcram_err, rdc_grp);
2252 		if (fcram_err.bits.ldw.pio_err) {
2253 			NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2254 				    " FCRAM PIO ECC error on port %d"
2255 				    " rdc group: %d Hash Table addr: 0x%x"
2256 				    " syndrome: 0x%x",
2257 				    portn, rdc_grp,
2258 				    fcram_err.bits.ldw.fcram_addr,
2259 				    fcram_err.bits.ldw.syndrome));
2260 			statsp->hash_pio_err[rdc_grp]++;
2261 			statsp->errlog.hash_pio[rdc_grp] =
2262 						(uint32_t)fcram_err.value;
2263 			NXGE_FM_REPORT_ERROR(nxgep, NULL, NULL,
2264 					NXGE_FM_EREPORT_FFLP_HASHT_DATA_ERR);
2265 			npi_fflp_fcram_error_clear(handle, rdc_grp);
2266 		}
2267 	}
2268 
2269 	npi_fflp_fcram_error_log1_get(handle, &fcram1_err);
2270 	if (fcram1_err.bits.ldw.ecc_err) {
2271 		char *multi_str = "";
2272 		char *multi_bit_str = "";
2273 		npi_fflp_fcram_error_log2_get(handle, &fcram2_err);
2274 		if (fcram1_err.bits.ldw.mult_lk) {
2275 			multi_str = "multiple";
2276 		}
2277 		if (fcram1_err.bits.ldw.mult_bit) {
2278 			multi_bit_str = "multiple bits";
2279 		}
2280 		NXGE_ERROR_MSG((nxgep, FFLP_CTL,
2281 				    " FCRAM %s lookup %s ECC error on port %d"
2282 				    " H1: 0x%x Subarea: 0x%x Syndrome: 0x%x",
2283 				    multi_str, multi_bit_str, portn,
2284 				    fcram2_err.bits.ldw.h1,
2285 				    fcram2_err.bits.ldw.subarea,
2286 				    fcram2_err.bits.ldw.syndrome));
2287 		NXGE_FM_REPORT_ERROR(nxgep, NULL, NULL,
2288 					NXGE_FM_EREPORT_FFLP_HASHT_LOOKUP_ERR);
2289 	}
2290 	statsp->errlog.hash_lookup1 = (uint32_t)fcram1_err.value;
2291 	statsp->errlog.hash_lookup2 = (uint32_t)fcram2_err.value;
2292 
2293 	return (NXGE_OK);
2294 }
2295