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