xref: /illumos-gate/usr/src/uts/common/io/hxge/hxge_pfc.c (revision 968633ad8faee931821fd6b656eb0d96d4b186c0)
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 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <hxge_impl.h>
28 #include <hxge_classify.h>
29 #include <hxge_pfc.h>
30 #include <hpi_pfc.h>
31 #include <sys/ethernet.h>
32 
33 /*
34  * Ethernet broadcast address definition.
35  */
36 static ether_addr_st etherbroadcastaddr = {\
37 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff \
38 };
39 
40 static hxge_status_t hxge_pfc_set_mac_address(p_hxge_t, uint32_t,
41 	struct ether_addr *);
42 static uint32_t crc32_mchash(p_ether_addr_t addr);
43 static hxge_status_t hxge_pfc_load_hash_table(p_hxge_t hxgep);
44 static uint32_t hxge_get_blade_id(p_hxge_t hxgep);
45 static hxge_status_t hxge_tcam_default_add_entry(p_hxge_t hxgep,
46 	tcam_class_t class);
47 static hxge_status_t hxge_tcam_default_config(p_hxge_t hxgep);
48 
49 hxge_status_t
50 hxge_classify_init(p_hxge_t hxgep)
51 {
52 	hxge_status_t status = HXGE_OK;
53 
54 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_init"));
55 
56 	status = hxge_classify_init_sw(hxgep);
57 	if (status != HXGE_OK)
58 		return (status);
59 
60 	status = hxge_classify_init_hw(hxgep);
61 	if (status != HXGE_OK) {
62 		(void) hxge_classify_exit_sw(hxgep);
63 		return (status);
64 	}
65 
66 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_init"));
67 
68 	return (HXGE_OK);
69 }
70 
71 hxge_status_t
72 hxge_classify_uninit(p_hxge_t hxgep)
73 {
74 	return (hxge_classify_exit_sw(hxgep));
75 }
76 
77 static hxge_status_t
78 hxge_tcam_dump_entry(p_hxge_t hxgep, uint32_t location)
79 {
80 	hxge_tcam_entry_t	tcam_rdptr;
81 	uint64_t		asc_ram = 0;
82 	hpi_handle_t		handle;
83 	hpi_status_t		status;
84 
85 	handle = hxgep->hpi_reg_handle;
86 
87 	/* Retrieve the saved entry */
88 	bcopy((void *)&hxgep->classifier.tcam_entries[location].tce,
89 	    (void *)&tcam_rdptr, sizeof (hxge_tcam_entry_t));
90 
91 	/* Compare the entry */
92 	status = hpi_pfc_tcam_entry_read(handle, location, &tcam_rdptr);
93 	if (status == HPI_FAILURE) {
94 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
95 		    " hxge_tcam_dump_entry: tcam read failed at location %d ",
96 		    location));
97 		return (HXGE_ERROR);
98 	}
99 
100 	status = hpi_pfc_tcam_asc_ram_entry_read(handle, location, &asc_ram);
101 
102 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "location %x\n"
103 	    " key:  %llx %llx\n mask: %llx %llx\n ASC RAM %llx \n", location,
104 	    tcam_rdptr.key0, tcam_rdptr.key1,
105 	    tcam_rdptr.mask0, tcam_rdptr.mask1, asc_ram));
106 	return (HXGE_OK);
107 }
108 
109 void
110 hxge_get_tcam(p_hxge_t hxgep, p_mblk_t mp)
111 {
112 	uint32_t	tcam_loc;
113 	uint32_t	*lptr;
114 	int		location;
115 	int		start_location = 0;
116 	int		stop_location = hxgep->classifier.tcam_size;
117 
118 	lptr = (uint32_t *)mp->b_rptr;
119 	location = *lptr;
120 
121 	if ((location >= hxgep->classifier.tcam_size) || (location < -1)) {
122 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
123 		    "hxge_tcam_dump: Invalid location %d \n", location));
124 		return;
125 	}
126 	if (location == -1) {
127 		start_location = 0;
128 		stop_location = hxgep->classifier.tcam_size;
129 	} else {
130 		start_location = location;
131 		stop_location = location + 1;
132 	}
133 	for (tcam_loc = start_location; tcam_loc < stop_location; tcam_loc++)
134 		(void) hxge_tcam_dump_entry(hxgep, tcam_loc);
135 }
136 
137 /*ARGSUSED*/
138 static hxge_status_t
139 hxge_add_tcam_entry(p_hxge_t hxgep, flow_resource_t *flow_res)
140 {
141 	return (HXGE_OK);
142 }
143 
144 void
145 hxge_put_tcam(p_hxge_t hxgep, p_mblk_t mp)
146 {
147 	flow_resource_t *fs;
148 	fs = (flow_resource_t *)mp->b_rptr;
149 
150 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
151 	    "hxge_put_tcam addr fs $%p  type %x offset %x",
152 	    fs, fs->flow_spec.flow_type, fs->channel_cookie));
153 
154 	(void) hxge_add_tcam_entry(hxgep, fs);
155 }
156 
157 static uint32_t
158 hxge_get_blade_id(p_hxge_t hxgep)
159 {
160 	phy_debug_training_vec_t	blade_id;
161 
162 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_get_blade_id"));
163 	HXGE_REG_RD32(hxgep->hpi_reg_handle, PHY_DEBUG_TRAINING_VEC,
164 	    &blade_id.value);
165 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_get_blade_id: id = %d",
166 	    blade_id.bits.bld_num));
167 
168 	return (blade_id.bits.bld_num);
169 }
170 
171 static hxge_status_t
172 hxge_tcam_default_add_entry(p_hxge_t hxgep, tcam_class_t class)
173 {
174 	hpi_status_t		rs = HPI_SUCCESS;
175 	uint32_t		location;
176 	hxge_tcam_entry_t	entry;
177 	hxge_tcam_spread_t	*key = NULL;
178 	hxge_tcam_spread_t	*mask = NULL;
179 	hpi_handle_t		handle;
180 	p_hxge_hw_list_t	hw_p;
181 
182 	if ((hw_p = hxgep->hxge_hw_p) == NULL) {
183 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
184 		    " hxge_tcam_default_add_entry: common hardware not set"));
185 		return (HXGE_ERROR);
186 	}
187 
188 	bzero(&entry, sizeof (hxge_tcam_entry_t));
189 
190 	/*
191 	 * The class id and blade id are common for all classes
192 	 * Only use the blade id for matching and the rest are wild cards.
193 	 * This will allow one TCAM entry to match all traffic in order
194 	 * to spread the traffic using source hash.
195 	 */
196 	key = &entry.key.spread;
197 	mask = &entry.mask.spread;
198 
199 	key->blade_id = hxge_get_blade_id(hxgep);
200 
201 	mask->class_code = 0xf;
202 	mask->class_code_l = 0x1;
203 	mask->blade_id = 0;
204 	mask->wild1 = 0x7ffffff;
205 	mask->wild = 0xffffffff;
206 	mask->wild_l = 0xffffffff;
207 
208 	location = class;
209 
210 	handle = hxgep->hpi_reg_handle;
211 
212 	MUTEX_ENTER(&hw_p->hxge_tcam_lock);
213 	rs = hpi_pfc_tcam_entry_write(handle, location, &entry);
214 	if (rs & HPI_PFC_ERROR) {
215 		MUTEX_EXIT(&hw_p->hxge_tcam_lock);
216 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
217 		    " hxge_tcam_default_add_entry tcam entry write"
218 		    " failed for location %d", location));
219 		return (HXGE_ERROR);
220 	}
221 
222 	/* Add the associative portion */
223 	entry.match_action.value = 0;
224 
225 	/* Use source hash to spread traffic */
226 	entry.match_action.bits.channel_d = 0;
227 	entry.match_action.bits.channel_c = 1;
228 	entry.match_action.bits.channel_b = 2;
229 	entry.match_action.bits.channel_a = 3;
230 	entry.match_action.bits.source_hash = 1;
231 	entry.match_action.bits.discard = 0;
232 
233 	rs = hpi_pfc_tcam_asc_ram_entry_write(handle,
234 	    location, entry.match_action.value);
235 	if (rs & HPI_PFC_ERROR) {
236 		MUTEX_EXIT(&hw_p->hxge_tcam_lock);
237 		HXGE_DEBUG_MSG((hxgep, PFC_CTL,
238 		    " hxge_tcam_default_add_entry tcam entry write"
239 		    " failed for ASC RAM location %d", location));
240 		return (HXGE_ERROR);
241 	}
242 
243 	bcopy((void *) &entry,
244 	    (void *) &hxgep->classifier.tcam_entries[location].tce,
245 	    sizeof (hxge_tcam_entry_t));
246 
247 	MUTEX_EXIT(&hw_p->hxge_tcam_lock);
248 
249 	return (HXGE_OK);
250 }
251 
252 /*
253  * Configure one TCAM entry for each class and make it match
254  * everything within the class in order to spread the traffic
255  * among the DMA channels based on the source hash.
256  *
257  * This is the default for now. This may change when Crossbow is
258  * available for configuring TCAM.
259  */
260 static hxge_status_t
261 hxge_tcam_default_config(p_hxge_t hxgep)
262 {
263 	uint8_t		class;
264 	uint32_t	class_config;
265 	hxge_status_t	status = HXGE_OK;
266 
267 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_tcam_default_config"));
268 
269 	/*
270 	 * Add TCAM and its associative ram entries
271 	 * A wild card will be used for the class code in order to match
272 	 * any classes.
273 	 */
274 	class = 0;
275 	status = hxge_tcam_default_add_entry(hxgep, class);
276 	if (status != HXGE_OK) {
277 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
278 		    "hxge_tcam_default_config "
279 		    "hxge_tcam_default_add_entry failed class %d ",
280 		    class));
281 		return (HXGE_ERROR);
282 	}
283 
284 	/* Enable the classes */
285 	for (class = TCAM_CLASS_TCP_IPV4;
286 	    class <= TCAM_CLASS_SCTP_IPV6; class++) {
287 		/*
288 		 * By default, it is set to HXGE_CLASS_TCAM_LOOKUP in
289 		 * hxge_ndd.c. It may be overwritten in hxge.conf.
290 		 */
291 		class_config = hxgep->class_config.class_cfg[class];
292 
293 		status = hxge_pfc_ip_class_config(hxgep, class, class_config);
294 		if (status & HPI_PFC_ERROR) {
295 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
296 			    "hxge_tcam_default_config "
297 			    "hxge_pfc_ip_class_config failed "
298 			    " class %d config %x ", class, class_config));
299 			return (HXGE_ERROR);
300 		}
301 	}
302 
303 	status = hxge_pfc_config_tcam_enable(hxgep);
304 
305 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_tcam_default_config"));
306 
307 	return (status);
308 }
309 
310 hxge_status_t
311 hxge_pfc_set_default_mac_addr(p_hxge_t hxgep)
312 {
313 	hxge_status_t status;
314 
315 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_set_default_mac_addr"));
316 
317 	MUTEX_ENTER(&hxgep->ouraddr_lock);
318 
319 	/*
320 	 * Set new interface local address and re-init device.
321 	 * This is destructive to any other streams attached
322 	 * to this device.
323 	 */
324 	RW_ENTER_WRITER(&hxgep->filter_lock);
325 	status = hxge_pfc_set_mac_address(hxgep,
326 	    HXGE_MAC_DEFAULT_ADDR_SLOT, &hxgep->ouraddr);
327 	RW_EXIT(&hxgep->filter_lock);
328 
329 	MUTEX_EXIT(&hxgep->ouraddr_lock);
330 
331 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_set_default_mac_addr"));
332 	return (status);
333 }
334 
335 hxge_status_t
336 hxge_set_mac_addr(p_hxge_t hxgep, struct ether_addr *addrp)
337 {
338 	hxge_status_t status = HXGE_OK;
339 
340 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_set_mac_addr"));
341 
342 	MUTEX_ENTER(&hxgep->ouraddr_lock);
343 
344 	/*
345 	 * Exit if the address is same as ouraddr or multicast or broadcast
346 	 */
347 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
348 	    (ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
349 	    (ether_cmp(addrp, &hxgep->ouraddr) == 0)) {
350 		goto hxge_set_mac_addr_exit;
351 	}
352 	hxgep->ouraddr = *addrp;
353 
354 	/*
355 	 * Set new interface local address and re-init device.
356 	 * This is destructive to any other streams attached
357 	 * to this device.
358 	 */
359 	RW_ENTER_WRITER(&hxgep->filter_lock);
360 	status = hxge_pfc_set_mac_address(hxgep,
361 	    HXGE_MAC_DEFAULT_ADDR_SLOT, addrp);
362 	RW_EXIT(&hxgep->filter_lock);
363 
364 	MUTEX_EXIT(&hxgep->ouraddr_lock);
365 	goto hxge_set_mac_addr_end;
366 
367 hxge_set_mac_addr_exit:
368 	MUTEX_EXIT(&hxgep->ouraddr_lock);
369 
370 hxge_set_mac_addr_end:
371 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_set_mac_addr"));
372 	return (status);
373 fail:
374 	MUTEX_EXIT(&hxgep->ouraddr_lock);
375 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_set_mac_addr: "
376 	    "Unable to set mac address"));
377 	return (status);
378 }
379 
380 /*
381  * Add a multicast address entry into the HW hash table
382  */
383 hxge_status_t
384 hxge_add_mcast_addr(p_hxge_t hxgep, struct ether_addr *addrp)
385 {
386 	uint32_t	mchash;
387 	p_hash_filter_t	hash_filter;
388 	uint16_t	hash_bit;
389 	boolean_t	rx_init = B_FALSE;
390 	uint_t		j;
391 	hxge_status_t	status = HXGE_OK;
392 
393 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_add_mcast_addr"));
394 
395 	RW_ENTER_WRITER(&hxgep->filter_lock);
396 	mchash = crc32_mchash(addrp);
397 
398 	if (hxgep->hash_filter == NULL) {
399 		HXGE_DEBUG_MSG((NULL, STR_CTL,
400 		    "Allocating hash filter storage."));
401 		hxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
402 		    KM_SLEEP);
403 	}
404 
405 	hash_filter = hxgep->hash_filter;
406 	/*
407 	 * Note that mchash is an 8 bit value and thus 0 <= mchash <= 255.
408 	 * Consequently, 0 <= j <= 15 and 0 <= mchash % HASH_REG_WIDTH <= 15.
409 	 */
410 	j = mchash / HASH_REG_WIDTH;
411 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
412 	hash_filter->hash_filter_regs[j] |= hash_bit;
413 
414 	hash_filter->hash_bit_ref_cnt[mchash]++;
415 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
416 		hash_filter->hash_ref_cnt++;
417 		rx_init = B_TRUE;
418 	}
419 
420 	if (rx_init) {
421 		(void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, B_FALSE);
422 		(void) hxge_pfc_load_hash_table(hxgep);
423 		(void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, B_TRUE);
424 	}
425 
426 	RW_EXIT(&hxgep->filter_lock);
427 
428 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_add_mcast_addr"));
429 
430 	return (HXGE_OK);
431 fail:
432 	RW_EXIT(&hxgep->filter_lock);
433 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_add_mcast_addr: "
434 	    "Unable to add multicast address"));
435 
436 	return (status);
437 }
438 
439 /*
440  * Remove a multicast address entry from the HW hash table
441  */
442 hxge_status_t
443 hxge_del_mcast_addr(p_hxge_t hxgep, struct ether_addr *addrp)
444 {
445 	uint32_t	mchash;
446 	p_hash_filter_t	hash_filter;
447 	uint16_t	hash_bit;
448 	boolean_t	rx_init = B_FALSE;
449 	uint_t		j;
450 	hxge_status_t	status = HXGE_OK;
451 
452 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_del_mcast_addr"));
453 	RW_ENTER_WRITER(&hxgep->filter_lock);
454 	mchash = crc32_mchash(addrp);
455 	if (hxgep->hash_filter == NULL) {
456 		HXGE_DEBUG_MSG((NULL, STR_CTL,
457 		    "Hash filter already de_allocated."));
458 		RW_EXIT(&hxgep->filter_lock);
459 		HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_del_mcast_addr"));
460 		return (HXGE_OK);
461 	}
462 
463 	hash_filter = hxgep->hash_filter;
464 	hash_filter->hash_bit_ref_cnt[mchash]--;
465 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
466 		j = mchash / HASH_REG_WIDTH;
467 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
468 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
469 		hash_filter->hash_ref_cnt--;
470 		rx_init = B_TRUE;
471 	}
472 
473 	if (hash_filter->hash_ref_cnt == 0) {
474 		HXGE_DEBUG_MSG((NULL, STR_CTL,
475 		    "De-allocating hash filter storage."));
476 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
477 		hxgep->hash_filter = NULL;
478 	}
479 
480 	if (rx_init) {
481 		(void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, B_FALSE);
482 		(void) hxge_pfc_load_hash_table(hxgep);
483 
484 		/* Enable hash only if there are any hash entries */
485 		if (hxgep->hash_filter != NULL)
486 			(void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle,
487 			    B_TRUE);
488 	}
489 
490 	RW_EXIT(&hxgep->filter_lock);
491 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_del_mcast_addr"));
492 
493 	return (HXGE_OK);
494 fail:
495 	RW_EXIT(&hxgep->filter_lock);
496 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_del_mcast_addr: "
497 	    "Unable to remove multicast address"));
498 
499 	return (status);
500 }
501 
502 
503 static hxge_status_t
504 hxge_pfc_set_mac_address(p_hxge_t hxgep, uint32_t slot,
505     struct ether_addr *addrp)
506 {
507 	hpi_handle_t		handle;
508 	uint64_t		addr;
509 	hpi_status_t		hpi_status;
510 	uint8_t			*address = addrp->ether_addr_octet;
511 	uint64_t		tmp;
512 	int			i;
513 
514 	if (hxgep->hxge_hw_p == NULL) {
515 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
516 		    " hxge_pfc_set_mac_address: common hardware not set"));
517 		return (HXGE_ERROR);
518 	}
519 
520 	/*
521 	 * Convert a byte array to a 48 bit value.
522 	 * Need to check endianess if in doubt
523 	 */
524 	addr = 0;
525 	for (i = 0; i < ETHERADDRL; i++) {
526 		tmp = address[i];
527 		addr <<= 8;
528 		addr |= tmp;
529 	}
530 
531 	handle = hxgep->hpi_reg_handle;
532 	hpi_status = hpi_pfc_set_mac_address(handle, slot, addr);
533 
534 	if (hpi_status != HPI_SUCCESS) {
535 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
536 		    " hxge_pfc_set_mac_address: failed to set address"));
537 		return (HXGE_ERROR);
538 	}
539 
540 	return (HXGE_OK);
541 }
542 
543 /*ARGSUSED*/
544 hxge_status_t
545 hxge_pfc_num_macs_get(p_hxge_t hxgep, uint32_t *nmacs)
546 {
547 	*nmacs = PFC_N_MAC_ADDRESSES;
548 	return (HXGE_OK);
549 }
550 
551 
552 hxge_status_t
553 hxge_pfc_set_hash(p_hxge_t hxgep, uint32_t seed)
554 {
555 	hpi_status_t		rs = HPI_SUCCESS;
556 	hpi_handle_t		handle;
557 	p_hxge_class_pt_cfg_t 	p_class_cfgp;
558 
559 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_set_hash"));
560 
561 	p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
562 	p_class_cfgp->init_hash = seed;
563 	handle = hxgep->hpi_reg_handle;
564 
565 	rs = hpi_pfc_set_hash_seed_value(handle, seed);
566 	if (rs & HPI_PFC_ERROR) {
567 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
568 		    " hxge_pfc_set_hash %x failed ", seed));
569 		return (HXGE_ERROR | rs);
570 	}
571 
572 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, " <== hxge_pfc_set_hash"));
573 
574 	return (HXGE_OK);
575 }
576 
577 hxge_status_t
578 hxge_pfc_config_tcam_enable(p_hxge_t hxgep)
579 {
580 	hpi_handle_t		handle;
581 	boolean_t		enable = B_TRUE;
582 	hpi_status_t		hpi_status;
583 
584 	handle = hxgep->hpi_reg_handle;
585 	if (hxgep->hxge_hw_p == NULL) {
586 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
587 		    " hxge_pfc_config_tcam_enable: common hardware not set"));
588 		return (HXGE_ERROR);
589 	}
590 
591 	hpi_status = hpi_pfc_set_tcam_enable(handle, enable);
592 	if (hpi_status != HPI_SUCCESS) {
593 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
594 		    " hpi_pfc_set_tcam_enable: enable tcam failed"));
595 		return (HXGE_ERROR);
596 	}
597 
598 	return (HXGE_OK);
599 }
600 
601 hxge_status_t
602 hxge_pfc_config_tcam_disable(p_hxge_t hxgep)
603 {
604 	hpi_handle_t		handle;
605 	boolean_t		enable = B_FALSE;
606 	hpi_status_t		hpi_status;
607 
608 	handle = hxgep->hpi_reg_handle;
609 	if (hxgep->hxge_hw_p == NULL) {
610 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
611 		    " hxge_pfc_config_tcam_disable: common hardware not set"));
612 		return (HXGE_ERROR);
613 	}
614 
615 	hpi_status = hpi_pfc_set_tcam_enable(handle, enable);
616 	if (hpi_status != HPI_SUCCESS) {
617 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
618 		    " hpi_pfc_set_tcam_enable: disable tcam failed"));
619 		return (HXGE_ERROR);
620 	}
621 
622 	return (HXGE_OK);
623 }
624 
625 static hxge_status_t
626 hxge_cfg_tcam_ip_class_get(p_hxge_t hxgep, tcam_class_t class,
627     uint32_t *class_config)
628 {
629 	hpi_status_t	rs = HPI_SUCCESS;
630 	tcam_key_cfg_t	cfg;
631 	hpi_handle_t	handle;
632 	uint32_t	ccfg = 0;
633 
634 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_cfg_tcam_ip_class_get"));
635 
636 	bzero(&cfg, sizeof (tcam_key_cfg_t));
637 	handle = hxgep->hpi_reg_handle;
638 
639 	rs = hpi_pfc_get_l3_class_config(handle, class, &cfg);
640 	if (rs & HPI_PFC_ERROR) {
641 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
642 		    " hxge_cfg_tcam_ip_class opt %x for class %d failed ",
643 		    class_config, class));
644 		return (HXGE_ERROR | rs);
645 	}
646 	if (cfg.discard)
647 		ccfg |=  HXGE_CLASS_DISCARD;
648 
649 	if (cfg.lookup_enable)
650 		ccfg |= HXGE_CLASS_TCAM_LOOKUP;
651 
652 	*class_config = ccfg;
653 
654 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_cfg_tcam_ip_class_get %x",
655 	    ccfg));
656 
657 	return (HXGE_OK);
658 }
659 
660 hxge_status_t
661 hxge_pfc_ip_class_config_get(p_hxge_t hxgep, tcam_class_t class,
662     uint32_t *config)
663 {
664 	uint32_t	t_class_config;
665 	int		t_status = HXGE_OK;
666 
667 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_ip_class_config_get"));
668 	t_class_config = 0;
669 	t_status = hxge_cfg_tcam_ip_class_get(hxgep, class, &t_class_config);
670 
671 	if (t_status & HPI_PFC_ERROR) {
672 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
673 		    " hxge_pfc_ip_class_config_get for class %d tcam failed",
674 		    class));
675 		return (t_status);
676 	}
677 
678 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, " hxge_pfc_ip_class_config tcam %x",
679 	    t_class_config));
680 
681 	*config = t_class_config;
682 
683 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_ip_class_config_get"));
684 	return (HXGE_OK);
685 }
686 
687 static hxge_status_t
688 hxge_pfc_config_init(p_hxge_t hxgep)
689 {
690 	hpi_handle_t		handle;
691 	block_reset_t		reset_reg;
692 
693 	handle = hxgep->hpi_reg_handle;
694 	if (hxgep->hxge_hw_p == NULL) {
695 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
696 		    " hxge_pfc_config_init: common hardware not set"));
697 		return (HXGE_ERROR);
698 	}
699 
700 	/* Reset PFC block from PEU to clear any previous state */
701 	reset_reg.value = 0;
702 	reset_reg.bits.pfc_rst = 1;
703 	HXGE_REG_WR32(hxgep->hpi_handle, BLOCK_RESET, reset_reg.value);
704 	HXGE_DELAY(1000);
705 
706 	(void) hpi_pfc_set_tcam_enable(handle, B_FALSE);
707 	(void) hpi_pfc_set_l2_hash(handle, B_FALSE);
708 	(void) hpi_pfc_set_tcp_cksum(handle, B_FALSE);
709 	(void) hpi_pfc_set_default_dma(handle, 0);
710 	(void) hpi_pfc_mac_addr_enable(handle, 0);
711 	(void) hpi_pfc_set_force_csum(handle, B_FALSE);
712 
713 	/* Set the drop log mask to ignore the logs */
714 	(void) hpi_pfc_set_drop_log_mask(handle, 1, 1, 1, 1, 1);
715 
716 	/* Clear the interrupt masks to receive interrupts */
717 	(void) hpi_pfc_set_interrupt_mask(handle, 0, 0, 0);
718 
719 	/* Clear the interrupt status */
720 	(void) hpi_pfc_clear_interrupt_status(handle);
721 
722 	return (HXGE_OK);
723 }
724 
725 static hxge_status_t
726 hxge_pfc_tcam_invalidate_all(p_hxge_t hxgep)
727 {
728 	hpi_status_t		rs = HPI_SUCCESS;
729 	hpi_handle_t		handle;
730 	p_hxge_hw_list_t	hw_p;
731 
732 	HXGE_DEBUG_MSG((hxgep, PFC_CTL,
733 	    "==> hxge_pfc_tcam_invalidate_all"));
734 	handle = hxgep->hpi_reg_handle;
735 	if ((hw_p = hxgep->hxge_hw_p) == NULL) {
736 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
737 		    " hxge_pfc_tcam_invalidate_all: common hardware not set"));
738 		return (HXGE_ERROR);
739 	}
740 
741 	MUTEX_ENTER(&hw_p->hxge_tcam_lock);
742 	rs = hpi_pfc_tcam_invalidate_all(handle);
743 	MUTEX_EXIT(&hw_p->hxge_tcam_lock);
744 
745 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_tcam_invalidate_all"));
746 	if (rs != HPI_SUCCESS)
747 		return (HXGE_ERROR);
748 
749 	return (HXGE_OK);
750 }
751 
752 static hxge_status_t
753 hxge_pfc_tcam_init(p_hxge_t hxgep)
754 {
755 	hpi_status_t	rs = HPI_SUCCESS;
756 	hpi_handle_t	handle;
757 
758 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_tcam_init"));
759 	handle = hxgep->hpi_reg_handle;
760 
761 	if (hxgep->hxge_hw_p == NULL) {
762 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
763 		    " hxge_pfc_tcam_init: common hardware not set"));
764 		return (HXGE_ERROR);
765 	}
766 
767 	/*
768 	 * Disable the TCAM.
769 	 */
770 	rs = hpi_pfc_set_tcam_enable(handle, B_FALSE);
771 	if (rs != HPI_SUCCESS) {
772 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "failed TCAM Disable\n"));
773 		return (HXGE_ERROR | rs);
774 	}
775 
776 	/*
777 	 * Invalidate all the TCAM entries for this blade.
778 	 */
779 	rs = hxge_pfc_tcam_invalidate_all(hxgep);
780 	if (rs != HPI_SUCCESS) {
781 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "failed TCAM Disable\n"));
782 		return (HXGE_ERROR | rs);
783 	}
784 
785 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_tcam_init"));
786 	return (HXGE_OK);
787 }
788 
789 static hxge_status_t
790 hxge_pfc_vlan_tbl_clear_all(p_hxge_t hxgep)
791 {
792 	hpi_handle_t		handle;
793 	hpi_status_t		rs = HPI_SUCCESS;
794 	p_hxge_hw_list_t	hw_p;
795 
796 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_vlan_tbl_clear_all "));
797 
798 	handle = hxgep->hpi_reg_handle;
799 	if ((hw_p = hxgep->hxge_hw_p) == NULL) {
800 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
801 		    " hxge_pfc_vlan_tbl_clear_all: common hardware not set"));
802 		return (HXGE_ERROR);
803 	}
804 
805 	mutex_enter(&hw_p->hxge_vlan_lock);
806 	rs = hpi_pfc_cfg_vlan_table_clear(handle);
807 	mutex_exit(&hw_p->hxge_vlan_lock);
808 
809 	if (rs != HPI_SUCCESS) {
810 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
811 		    "failed vlan table clear\n"));
812 		return (HXGE_ERROR | rs);
813 	}
814 
815 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_vlan_tbl_clear_all "));
816 	return (HXGE_OK);
817 }
818 
819 hxge_status_t
820 hxge_pfc_ip_class_config(p_hxge_t hxgep, tcam_class_t class, uint32_t config)
821 {
822 	uint32_t		class_config;
823 	p_hxge_class_pt_cfg_t 	p_class_cfgp;
824 	tcam_key_cfg_t		cfg;
825 	hpi_handle_t		handle;
826 	hpi_status_t		rs = HPI_SUCCESS;
827 
828 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_ip_class_config"));
829 	p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
830 	class_config = p_class_cfgp->class_cfg[class];
831 
832 	if (class_config != config) {
833 		p_class_cfgp->class_cfg[class] = config;
834 		class_config = config;
835 	}
836 
837 	handle = hxgep->hpi_reg_handle;
838 
839 	if (class == TCAM_CLASS_ETYPE_1 || class == TCAM_CLASS_ETYPE_2) {
840 		rs = hpi_pfc_set_l2_class_slot(handle,
841 		    class_config & HXGE_CLASS_ETHER_TYPE_MASK,
842 		    class_config & HXGE_CLASS_VALID,
843 		    class - TCAM_CLASS_ETYPE_1);
844 	} else {
845 		if (class_config & HXGE_CLASS_DISCARD)
846 			cfg.discard = 1;
847 		else
848 			cfg.discard = 0;
849 		if (class_config & HXGE_CLASS_TCAM_LOOKUP)
850 			cfg.lookup_enable = 1;
851 		else
852 			cfg.lookup_enable = 0;
853 
854 		rs = hpi_pfc_set_l3_class_config(handle, class, cfg);
855 	}
856 
857 	if (rs & HPI_PFC_ERROR) {
858 		HXGE_DEBUG_MSG((hxgep, PFC_CTL,
859 		    " hxge_pfc_ip_class_config %x for class %d tcam failed",
860 		    config, class));
861 		return (HXGE_ERROR);
862 	}
863 
864 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_ip_class_config"));
865 	return (HXGE_OK);
866 }
867 
868 hxge_status_t
869 hxge_pfc_ip_class_config_all(p_hxge_t hxgep)
870 {
871 	uint32_t	class_config;
872 	tcam_class_t	cl;
873 	int		status = HXGE_OK;
874 
875 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_ip_class_config_all"));
876 
877 	for (cl = TCAM_CLASS_ETYPE_1; cl <= TCAM_CLASS_SCTP_IPV6; cl++) {
878 		if (cl == TCAM_CLASS_RESERVED_4 ||
879 		    cl == TCAM_CLASS_RESERVED_5 ||
880 		    cl == TCAM_CLASS_RESERVED_6 ||
881 		    cl == TCAM_CLASS_RESERVED_7)
882 			continue;
883 
884 		class_config = hxgep->class_config.class_cfg[cl];
885 		status = hxge_pfc_ip_class_config(hxgep, cl, class_config);
886 		if (status & HPI_PFC_ERROR) {
887 			HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
888 			    "hxge_pfc_ip_class_config failed "
889 			    " class %d config %x ", cl, class_config));
890 		}
891 	}
892 
893 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_ip_class_config_all"));
894 	return (HXGE_OK);
895 }
896 
897 static hxge_status_t
898 hxge_pfc_update_hw(p_hxge_t hxgep)
899 {
900 	hxge_status_t	status = HXGE_OK;
901 	hpi_handle_t	handle;
902 	p_hxge_param_t	pa;
903 	int		i;
904 	boolean_t	parity = 0;
905 	boolean_t	implicit_valid = 0;
906 	vlan_id_t	implicit_vlan_id;
907 	uint32_t	vlanid_group;
908 	uint64_t	offset;
909 	int		max_vlan_groups;
910 	int		vlan_group_step;
911 
912 	p_hxge_class_pt_cfg_t 	p_class_cfgp;
913 
914 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_update_hw"));
915 	p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
916 	handle = hxgep->hpi_reg_handle;
917 
918 	status = hxge_pfc_set_hash(hxgep, p_class_cfgp->init_hash);
919 	if (status != HXGE_OK) {
920 		HXGE_DEBUG_MSG((hxgep, PFC_CTL, "hxge_pfc_set_hash Failed"));
921 		return (HXGE_ERROR);
922 	}
923 
924 	/*
925 	 * configure vlan table to join all vlans in order for Solaris
926 	 * network to receive vlan packets of any acceptible VIDs.
927 	 * This may change when Solaris network passes VIDs down.
928 	 */
929 	vlanid_group = 0xffffffff;
930 	max_vlan_groups = 128;
931 	vlan_group_step = 8;
932 	for (i = 0; i < max_vlan_groups; i++) {
933 		offset = PFC_VLAN_TABLE + i * vlan_group_step;
934 		REG_PIO_WRITE64(handle, offset, vlanid_group);
935 	}
936 
937 	/* Configure the vlan_ctrl register */
938 	/* Let hw generate the parity bits in pfc_vlan_table */
939 	parity = 0;
940 
941 	pa = (p_hxge_param_t)&hxgep->param_arr[param_implicit_vlan_id];
942 	implicit_vlan_id = (vlan_id_t)pa->value;
943 
944 	/*
945 	 * Enable it only if there is a valid implicity vlan id either in
946 	 * NDD table or the .conf file.
947 	 */
948 	if (implicit_vlan_id >= VLAN_ID_MIN && implicit_vlan_id <= VLAN_ID_MAX)
949 		implicit_valid = 1;
950 
951 	status = hpi_pfc_cfg_vlan_control_set(handle, parity, implicit_valid,
952 	    implicit_vlan_id);
953 	if (status != HPI_SUCCESS) {
954 		HXGE_DEBUG_MSG((hxgep, PFC_CTL,
955 		    "hxge_pfc_update_hw: hpi_pfc_cfg_vlan_control_set failed"));
956 		return (HXGE_ERROR);
957 	}
958 
959 	/* config MAC addresses */
960 	/* Need to think about this */
961 
962 	/* Configure hash value and classes */
963 	status = hxge_pfc_ip_class_config_all(hxgep);
964 	if (status != HXGE_OK) {
965 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
966 		    "hxge_pfc_ip_class_config_all Failed"));
967 		return (HXGE_ERROR);
968 	}
969 
970 	return (HXGE_OK);
971 }
972 
973 hxge_status_t
974 hxge_pfc_hw_reset(p_hxge_t hxgep)
975 {
976 	hxge_status_t status = HXGE_OK;
977 
978 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_hw_reset"));
979 
980 	status = hxge_pfc_config_init(hxgep);
981 	if (status != HXGE_OK) {
982 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
983 		    "failed PFC config init."));
984 		return (status);
985 	}
986 
987 	status = hxge_pfc_tcam_init(hxgep);
988 	if (status != HXGE_OK) {
989 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "failed TCAM init."));
990 		return (status);
991 	}
992 
993 	/*
994 	 * invalidate VLAN RDC tables
995 	 */
996 	status = hxge_pfc_vlan_tbl_clear_all(hxgep);
997 	if (status != HXGE_OK) {
998 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
999 		    "failed VLAN Table Invalidate. "));
1000 		return (status);
1001 	}
1002 	hxgep->classifier.state |= HXGE_PFC_HW_RESET;
1003 
1004 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_hw_reset"));
1005 
1006 	return (HXGE_OK);
1007 }
1008 
1009 hxge_status_t
1010 hxge_classify_init_hw(p_hxge_t hxgep)
1011 {
1012 	hxge_status_t status = HXGE_OK;
1013 
1014 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_init_hw"));
1015 
1016 	if (hxgep->classifier.state & HXGE_PFC_HW_INIT) {
1017 		HXGE_DEBUG_MSG((hxgep, PFC_CTL,
1018 		    "hxge_classify_init_hw already init"));
1019 		return (HXGE_OK);
1020 	}
1021 
1022 	/* Now do a real configuration */
1023 	status = hxge_pfc_update_hw(hxgep);
1024 	if (status != HXGE_OK) {
1025 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1026 		    "hxge_pfc_update_hw failed"));
1027 		return (HXGE_ERROR);
1028 	}
1029 
1030 	status = hxge_tcam_default_config(hxgep);
1031 	if (status != HXGE_OK) {
1032 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1033 		    "hxge_tcam_default_config failed"));
1034 		return (status);
1035 	}
1036 
1037 	hxgep->classifier.state |= HXGE_PFC_HW_INIT;
1038 
1039 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_init_hw"));
1040 
1041 	return (HXGE_OK);
1042 }
1043 
1044 hxge_status_t
1045 hxge_classify_init_sw(p_hxge_t hxgep)
1046 {
1047 	int		alloc_size;
1048 	hxge_classify_t	*classify_ptr;
1049 
1050 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_init_sw"));
1051 	classify_ptr = &hxgep->classifier;
1052 
1053 	if (classify_ptr->state & HXGE_PFC_SW_INIT) {
1054 		HXGE_DEBUG_MSG((hxgep, PFC_CTL,
1055 		    "hxge_classify_init_sw already init"));
1056 		return (HXGE_OK);
1057 	}
1058 
1059 	/* Init SW structures */
1060 	classify_ptr->tcam_size = TCAM_HXGE_TCAM_MAX_ENTRY;
1061 
1062 	alloc_size = sizeof (tcam_flow_spec_t) * classify_ptr->tcam_size;
1063 	classify_ptr->tcam_entries = KMEM_ZALLOC(alloc_size, NULL);
1064 	bzero(classify_ptr->class_usage, sizeof (classify_ptr->class_usage));
1065 
1066 	/* Start from the beginning of TCAM */
1067 	hxgep->classifier.tcam_location = 0;
1068 	classify_ptr->state |= HXGE_PFC_SW_INIT;
1069 
1070 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_init_sw"));
1071 
1072 	return (HXGE_OK);
1073 }
1074 
1075 hxge_status_t
1076 hxge_classify_exit_sw(p_hxge_t hxgep)
1077 {
1078 	int		alloc_size;
1079 	hxge_classify_t	*classify_ptr;
1080 	int		fsize;
1081 
1082 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_exit_sw"));
1083 	classify_ptr = &hxgep->classifier;
1084 
1085 	fsize = sizeof (tcam_flow_spec_t);
1086 	if (classify_ptr->tcam_entries) {
1087 		alloc_size = fsize * classify_ptr->tcam_size;
1088 		KMEM_FREE((void *) classify_ptr->tcam_entries, alloc_size);
1089 	}
1090 	hxgep->classifier.state = NULL;
1091 
1092 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_exit_sw"));
1093 
1094 	return (HXGE_OK);
1095 }
1096 
1097 /*ARGSUSED*/
1098 hxge_status_t
1099 hxge_pfc_handle_sys_errors(p_hxge_t hxgep)
1100 {
1101 	return (HXGE_OK);
1102 }
1103 
1104 uint_t
1105 hxge_pfc_intr(caddr_t arg1, caddr_t arg2)
1106 {
1107 	p_hxge_ldv_t		ldvp = (p_hxge_ldv_t)arg1;
1108 	p_hxge_t		hxgep = (p_hxge_t)arg2;
1109 	hpi_handle_t		handle;
1110 	p_hxge_pfc_stats_t	statsp;
1111 	pfc_int_status_t	int_status;
1112 	pfc_bad_cs_counter_t	bad_cs_count;
1113 	pfc_drop_counter_t	drop_count;
1114 	pfc_drop_log_t		drop_log;
1115 	pfc_vlan_par_err_log_t	vlan_par_err_log;
1116 	pfc_tcam_par_err_log_t	tcam_par_err_log;
1117 
1118 	if (ldvp == NULL) {
1119 		HXGE_DEBUG_MSG((NULL, INT_CTL,
1120 		    "<== hxge_pfc_intr: hxgep $%p ldvp $%p", hxgep, ldvp));
1121 		return (DDI_INTR_UNCLAIMED);
1122 	}
1123 
1124 	if (arg2 == NULL || (void *) ldvp->hxgep != arg2) {
1125 		hxgep = ldvp->hxgep;
1126 	}
1127 
1128 	handle = hxgep->hpi_reg_handle;
1129 	statsp = (p_hxge_pfc_stats_t)&hxgep->statsp->pfc_stats;
1130 
1131 	/*
1132 	 * need to read the pfc interrupt status register to figure out
1133 	 * what is happenning
1134 	 */
1135 	(void) hpi_pfc_get_interrupt_status(handle, &int_status);
1136 
1137 	if (int_status.bits.pkt_drop) {
1138 		statsp->pkt_drop++;
1139 		if (statsp->pkt_drop == 1)
1140 			HXGE_ERROR_MSG((hxgep, INT_CTL, "PFC pkt_drop"));
1141 
1142 		/* Collect each individual drops */
1143 		(void) hpi_pfc_get_drop_log(handle, &drop_log);
1144 
1145 		if (drop_log.bits.tcp_ctrl_drop)
1146 			statsp->errlog.tcp_ctrl_drop++;
1147 		if (drop_log.bits.l2_addr_drop)
1148 			statsp->errlog.l2_addr_drop++;
1149 		if (drop_log.bits.class_code_drop)
1150 			statsp->errlog.class_code_drop++;
1151 		if (drop_log.bits.tcam_drop)
1152 			statsp->errlog.tcam_drop++;
1153 		if (drop_log.bits.vlan_drop)
1154 			statsp->errlog.vlan_drop++;
1155 
1156 		/* Collect the total drops for all kinds */
1157 		(void) hpi_pfc_get_drop_counter(handle, &drop_count.value);
1158 		statsp->drop_count += drop_count.bits.drop_count;
1159 	}
1160 
1161 	if (int_status.bits.tcam_parity_err) {
1162 		statsp->tcam_parity_err++;
1163 
1164 		(void) hpi_pfc_get_tcam_parity_log(handle, &tcam_par_err_log);
1165 		statsp->errlog.tcam_par_err_log = tcam_par_err_log.bits.addr;
1166 
1167 		if (statsp->tcam_parity_err == 1)
1168 			HXGE_ERROR_MSG((hxgep,
1169 			    INT_CTL, " TCAM parity error addr: 0x%x",
1170 			    tcam_par_err_log.bits.addr));
1171 	}
1172 
1173 	if (int_status.bits.vlan_parity_err) {
1174 		statsp->vlan_parity_err++;
1175 
1176 		(void) hpi_pfc_get_vlan_parity_log(handle, &vlan_par_err_log);
1177 		statsp->errlog.vlan_par_err_log = vlan_par_err_log.bits.addr;
1178 
1179 		if (statsp->vlan_parity_err == 1)
1180 			HXGE_ERROR_MSG((hxgep, INT_CTL,
1181 			    " vlan table parity error addr: 0x%x",
1182 			    vlan_par_err_log.bits.addr));
1183 	}
1184 
1185 	(void) hpi_pfc_get_bad_csum_counter(handle, &bad_cs_count.value);
1186 	statsp->bad_cs_count += bad_cs_count.bits.bad_cs_count;
1187 
1188 	(void) hpi_pfc_clear_interrupt_status(handle);
1189 	return (DDI_INTR_CLAIMED);
1190 }
1191 
1192 static void
1193 hxge_pfc_get_next_mac_addr(uint8_t *st_mac, struct ether_addr *final_mac)
1194 {
1195 	uint64_t	mac[ETHERADDRL];
1196 	uint64_t	mac_addr = 0;
1197 	int		i, j;
1198 
1199 	for (i = ETHERADDRL - 1, j = 0; j < ETHERADDRL; i--, j++) {
1200 		mac[j] = st_mac[i];
1201 		mac_addr |= (mac[j] << (j*8));
1202 	}
1203 
1204 	final_mac->ether_addr_octet[0] = (mac_addr & 0xff0000000000) >> 40;
1205 	final_mac->ether_addr_octet[1] = (mac_addr & 0xff00000000) >> 32;
1206 	final_mac->ether_addr_octet[2] = (mac_addr & 0xff000000) >> 24;
1207 	final_mac->ether_addr_octet[3] = (mac_addr & 0xff0000) >> 16;
1208 	final_mac->ether_addr_octet[4] = (mac_addr & 0xff00) >> 8;
1209 	final_mac->ether_addr_octet[5] = (mac_addr & 0xff);
1210 }
1211 
1212 hxge_status_t
1213 hxge_pfc_mac_addrs_get(p_hxge_t hxgep)
1214 {
1215 	hxge_status_t	status = HXGE_OK;
1216 	hpi_status_t	hpi_status = HPI_SUCCESS;
1217 	hpi_handle_t	handle = HXGE_DEV_HPI_HANDLE(hxgep);
1218 	uint8_t		mac_addr[ETHERADDRL];
1219 
1220 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_mac_addr_get"));
1221 
1222 	hpi_status = hpi_pfc_mac_addr_get_i(handle, mac_addr, 0);
1223 	if (hpi_status != HPI_SUCCESS) {
1224 		status = (HXGE_ERROR | hpi_status);
1225 		HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1226 		    "hxge_pfc_mac_addr_get: pfc_mac_addr_get_i failed"));
1227 		goto exit;
1228 	}
1229 
1230 	hxge_pfc_get_next_mac_addr(mac_addr, &hxgep->factaddr);
1231 	HXGE_ERROR_MSG((hxgep, PFC_CTL, "MAC Addr(0): %x:%x:%x:%x:%x:%x\n",
1232 	    mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
1233 	    mac_addr[4], mac_addr[5]));
1234 
1235 exit:
1236 	HXGE_DEBUG_MSG((hxgep, CFG_CTL, "<== hxge_pfc_mac_addr_get, "
1237 	    "status [0x%x]", status));
1238 	return (status);
1239 }
1240 
1241 /*
1242  * Calculate the bit in the multicast address filter
1243  * that selects the given * address.
1244  * Note: For Hydra, the last 8-bits are used.
1245  */
1246 static uint32_t
1247 crc32_mchash(p_ether_addr_t addr)
1248 {
1249 	uint8_t		*cp;
1250 	uint32_t	crc;
1251 	uint32_t	c;
1252 	int		byte;
1253 	int		bit;
1254 
1255 	cp = (uint8_t *)addr;
1256 	crc = (uint32_t)0xffffffff;
1257 	for (byte = 0; byte < ETHERADDRL; byte++) {
1258 		/* Hydra calculates the hash backwardly */
1259 		c = (uint32_t)cp[ETHERADDRL - 1 - byte];
1260 		for (bit = 0; bit < 8; bit++) {
1261 			if ((c & 0x1) ^ (crc & 0x1))
1262 				crc = (crc >> 1)^0xedb88320;
1263 			else
1264 				crc = (crc >> 1);
1265 			c >>= 1;
1266 		}
1267 	}
1268 	return ((~crc) >> (32 - HASH_BITS));
1269 }
1270 
1271 static hxge_status_t
1272 hxge_pfc_load_hash_table(p_hxge_t hxgep)
1273 {
1274 	uint32_t		i;
1275 	uint16_t		hashtab_e;
1276 	p_hash_filter_t		hash_filter;
1277 	hpi_handle_t		handle;
1278 
1279 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_load_hash_table\n"));
1280 	handle = hxgep->hpi_reg_handle;
1281 
1282 	/*
1283 	 * Load the multicast hash filter bits.
1284 	 */
1285 	hash_filter = hxgep->hash_filter;
1286 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
1287 		if (hash_filter != NULL) {
1288 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[i];
1289 		} else {
1290 			hashtab_e = 0;
1291 		}
1292 
1293 		if (hpi_pfc_set_multicast_hash_table(handle, i,
1294 		    hashtab_e) != HPI_SUCCESS)
1295 			return (HXGE_ERROR);
1296 	}
1297 
1298 	HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_load_hash_table\n"));
1299 
1300 	return (HXGE_OK);
1301 }
1302