16349Sqs148142 /*
26349Sqs148142 * CDDL HEADER START
36349Sqs148142 *
46349Sqs148142 * The contents of this file are subject to the terms of the
56349Sqs148142 * Common Development and Distribution License (the "License").
66349Sqs148142 * You may not use this file except in compliance with the License.
76349Sqs148142 *
86349Sqs148142 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96349Sqs148142 * or http://www.opensolaris.org/os/licensing.
106349Sqs148142 * See the License for the specific language governing permissions
116349Sqs148142 * and limitations under the License.
126349Sqs148142 *
136349Sqs148142 * When distributing Covered Code, include this CDDL HEADER in each
146349Sqs148142 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156349Sqs148142 * If applicable, add the following below this CDDL HEADER, with the
166349Sqs148142 * fields enclosed by brackets "[]" replaced with your own identifying
176349Sqs148142 * information: Portions Copyright [yyyy] [name of copyright owner]
186349Sqs148142 *
196349Sqs148142 * CDDL HEADER END
206349Sqs148142 */
216349Sqs148142
226349Sqs148142 /*
23*8718SMichael.Speer@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
246349Sqs148142 * Use is subject to license terms.
256349Sqs148142 */
266349Sqs148142
276349Sqs148142 #include <hxge_impl.h>
286349Sqs148142 #include <hxge_classify.h>
296349Sqs148142 #include <hxge_pfc.h>
306349Sqs148142 #include <hpi_pfc.h>
316349Sqs148142 #include <sys/ethernet.h>
326349Sqs148142
336349Sqs148142 static uint32_t crc32_mchash(p_ether_addr_t addr);
346349Sqs148142 static hxge_status_t hxge_pfc_load_hash_table(p_hxge_t hxgep);
356349Sqs148142 static uint32_t hxge_get_blade_id(p_hxge_t hxgep);
366349Sqs148142 static hxge_status_t hxge_tcam_default_add_entry(p_hxge_t hxgep,
376349Sqs148142 tcam_class_t class);
386349Sqs148142 static hxge_status_t hxge_tcam_default_config(p_hxge_t hxgep);
396349Sqs148142
406349Sqs148142 hxge_status_t
hxge_classify_init(p_hxge_t hxgep)416349Sqs148142 hxge_classify_init(p_hxge_t hxgep)
426349Sqs148142 {
436349Sqs148142 hxge_status_t status = HXGE_OK;
446349Sqs148142
456349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_init"));
466349Sqs148142
476349Sqs148142 status = hxge_classify_init_sw(hxgep);
486349Sqs148142 if (status != HXGE_OK)
496349Sqs148142 return (status);
506349Sqs148142
516349Sqs148142 status = hxge_classify_init_hw(hxgep);
526349Sqs148142 if (status != HXGE_OK) {
536349Sqs148142 (void) hxge_classify_exit_sw(hxgep);
546349Sqs148142 return (status);
556349Sqs148142 }
566349Sqs148142
576349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_init"));
586349Sqs148142
596349Sqs148142 return (HXGE_OK);
606349Sqs148142 }
616349Sqs148142
626349Sqs148142 hxge_status_t
hxge_classify_uninit(p_hxge_t hxgep)636349Sqs148142 hxge_classify_uninit(p_hxge_t hxgep)
646349Sqs148142 {
656349Sqs148142 return (hxge_classify_exit_sw(hxgep));
666349Sqs148142 }
676349Sqs148142
686349Sqs148142 static hxge_status_t
hxge_tcam_dump_entry(p_hxge_t hxgep,uint32_t location)696349Sqs148142 hxge_tcam_dump_entry(p_hxge_t hxgep, uint32_t location)
706349Sqs148142 {
716349Sqs148142 hxge_tcam_entry_t tcam_rdptr;
726349Sqs148142 uint64_t asc_ram = 0;
736349Sqs148142 hpi_handle_t handle;
746349Sqs148142 hpi_status_t status;
756349Sqs148142
766349Sqs148142 handle = hxgep->hpi_reg_handle;
776349Sqs148142
786349Sqs148142 /* Retrieve the saved entry */
796349Sqs148142 bcopy((void *)&hxgep->classifier.tcam_entries[location].tce,
806349Sqs148142 (void *)&tcam_rdptr, sizeof (hxge_tcam_entry_t));
816349Sqs148142
826349Sqs148142 /* Compare the entry */
836349Sqs148142 status = hpi_pfc_tcam_entry_read(handle, location, &tcam_rdptr);
846349Sqs148142 if (status == HPI_FAILURE) {
856349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
866349Sqs148142 " hxge_tcam_dump_entry: tcam read failed at location %d ",
876349Sqs148142 location));
886349Sqs148142 return (HXGE_ERROR);
896349Sqs148142 }
906349Sqs148142
916349Sqs148142 status = hpi_pfc_tcam_asc_ram_entry_read(handle, location, &asc_ram);
926349Sqs148142
936349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "location %x\n"
946349Sqs148142 " key: %llx %llx\n mask: %llx %llx\n ASC RAM %llx \n", location,
956349Sqs148142 tcam_rdptr.key0, tcam_rdptr.key1,
966349Sqs148142 tcam_rdptr.mask0, tcam_rdptr.mask1, asc_ram));
976349Sqs148142 return (HXGE_OK);
986349Sqs148142 }
996349Sqs148142
1006349Sqs148142 void
hxge_get_tcam(p_hxge_t hxgep,p_mblk_t mp)1016349Sqs148142 hxge_get_tcam(p_hxge_t hxgep, p_mblk_t mp)
1026349Sqs148142 {
1036349Sqs148142 uint32_t tcam_loc;
1046349Sqs148142 uint32_t *lptr;
1056349Sqs148142 int location;
1066349Sqs148142 int start_location = 0;
1076349Sqs148142 int stop_location = hxgep->classifier.tcam_size;
1086349Sqs148142
1096349Sqs148142 lptr = (uint32_t *)mp->b_rptr;
1106349Sqs148142 location = *lptr;
1116349Sqs148142
1126349Sqs148142 if ((location >= hxgep->classifier.tcam_size) || (location < -1)) {
1136349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1146349Sqs148142 "hxge_tcam_dump: Invalid location %d \n", location));
1156349Sqs148142 return;
1166349Sqs148142 }
1176349Sqs148142 if (location == -1) {
1186349Sqs148142 start_location = 0;
1196349Sqs148142 stop_location = hxgep->classifier.tcam_size;
1206349Sqs148142 } else {
1216349Sqs148142 start_location = location;
1226349Sqs148142 stop_location = location + 1;
1236349Sqs148142 }
1246349Sqs148142 for (tcam_loc = start_location; tcam_loc < stop_location; tcam_loc++)
1256349Sqs148142 (void) hxge_tcam_dump_entry(hxgep, tcam_loc);
1266349Sqs148142 }
1276349Sqs148142
1286349Sqs148142 /*ARGSUSED*/
1296349Sqs148142 static hxge_status_t
hxge_add_tcam_entry(p_hxge_t hxgep,flow_resource_t * flow_res)1306349Sqs148142 hxge_add_tcam_entry(p_hxge_t hxgep, flow_resource_t *flow_res)
1316349Sqs148142 {
1326349Sqs148142 return (HXGE_OK);
1336349Sqs148142 }
1346349Sqs148142
1356349Sqs148142 void
hxge_put_tcam(p_hxge_t hxgep,p_mblk_t mp)1366349Sqs148142 hxge_put_tcam(p_hxge_t hxgep, p_mblk_t mp)
1376349Sqs148142 {
1386349Sqs148142 flow_resource_t *fs;
1396349Sqs148142 fs = (flow_resource_t *)mp->b_rptr;
1406349Sqs148142
1416349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1426349Sqs148142 "hxge_put_tcam addr fs $%p type %x offset %x",
1436349Sqs148142 fs, fs->flow_spec.flow_type, fs->channel_cookie));
1446349Sqs148142
1456349Sqs148142 (void) hxge_add_tcam_entry(hxgep, fs);
1466349Sqs148142 }
1476349Sqs148142
1486349Sqs148142 static uint32_t
hxge_get_blade_id(p_hxge_t hxgep)1496349Sqs148142 hxge_get_blade_id(p_hxge_t hxgep)
1506349Sqs148142 {
1516349Sqs148142 phy_debug_training_vec_t blade_id;
1526349Sqs148142
1536349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_get_blade_id"));
1546349Sqs148142 HXGE_REG_RD32(hxgep->hpi_reg_handle, PHY_DEBUG_TRAINING_VEC,
1556349Sqs148142 &blade_id.value);
1566349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_get_blade_id: id = %d",
1576349Sqs148142 blade_id.bits.bld_num));
1586349Sqs148142
1596349Sqs148142 return (blade_id.bits.bld_num);
1606349Sqs148142 }
1616349Sqs148142
1626349Sqs148142 static hxge_status_t
hxge_tcam_default_add_entry(p_hxge_t hxgep,tcam_class_t class)1636349Sqs148142 hxge_tcam_default_add_entry(p_hxge_t hxgep, tcam_class_t class)
1646349Sqs148142 {
1656349Sqs148142 hpi_status_t rs = HPI_SUCCESS;
1666349Sqs148142 uint32_t location;
1676349Sqs148142 hxge_tcam_entry_t entry;
1686349Sqs148142 hxge_tcam_spread_t *key = NULL;
1696349Sqs148142 hxge_tcam_spread_t *mask = NULL;
1706349Sqs148142 hpi_handle_t handle;
1716349Sqs148142 p_hxge_hw_list_t hw_p;
1726349Sqs148142
1736349Sqs148142 if ((hw_p = hxgep->hxge_hw_p) == NULL) {
1746349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
1756349Sqs148142 " hxge_tcam_default_add_entry: common hardware not set"));
1766349Sqs148142 return (HXGE_ERROR);
1776349Sqs148142 }
1786349Sqs148142
1796349Sqs148142 bzero(&entry, sizeof (hxge_tcam_entry_t));
1806349Sqs148142
1816349Sqs148142 /*
1826349Sqs148142 * The class id and blade id are common for all classes
1836349Sqs148142 * Only use the blade id for matching and the rest are wild cards.
1846349Sqs148142 * This will allow one TCAM entry to match all traffic in order
1856349Sqs148142 * to spread the traffic using source hash.
1866349Sqs148142 */
1876349Sqs148142 key = &entry.key.spread;
1886349Sqs148142 mask = &entry.mask.spread;
1896349Sqs148142
1906349Sqs148142 key->blade_id = hxge_get_blade_id(hxgep);
1916349Sqs148142
1926864Sqs148142 mask->class_code = 0xf;
1936864Sqs148142 mask->class_code_l = 0x1;
1946349Sqs148142 mask->blade_id = 0;
1956349Sqs148142 mask->wild1 = 0x7ffffff;
1966864Sqs148142 mask->wild = 0xffffffff;
1976864Sqs148142 mask->wild_l = 0xffffffff;
1986349Sqs148142
1996349Sqs148142 location = class;
2006349Sqs148142
2016349Sqs148142 handle = hxgep->hpi_reg_handle;
2026349Sqs148142
2036349Sqs148142 MUTEX_ENTER(&hw_p->hxge_tcam_lock);
2046349Sqs148142 rs = hpi_pfc_tcam_entry_write(handle, location, &entry);
2056349Sqs148142 if (rs & HPI_PFC_ERROR) {
2066349Sqs148142 MUTEX_EXIT(&hw_p->hxge_tcam_lock);
2076349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2086349Sqs148142 " hxge_tcam_default_add_entry tcam entry write"
2096349Sqs148142 " failed for location %d", location));
2106349Sqs148142 return (HXGE_ERROR);
2116349Sqs148142 }
2126349Sqs148142
2136349Sqs148142 /* Add the associative portion */
2146349Sqs148142 entry.match_action.value = 0;
2156349Sqs148142
2166349Sqs148142 /* Use source hash to spread traffic */
2176349Sqs148142 entry.match_action.bits.channel_d = 0;
2186349Sqs148142 entry.match_action.bits.channel_c = 1;
2196349Sqs148142 entry.match_action.bits.channel_b = 2;
2206349Sqs148142 entry.match_action.bits.channel_a = 3;
2216349Sqs148142 entry.match_action.bits.source_hash = 1;
2226349Sqs148142 entry.match_action.bits.discard = 0;
2236349Sqs148142
2246349Sqs148142 rs = hpi_pfc_tcam_asc_ram_entry_write(handle,
2256349Sqs148142 location, entry.match_action.value);
2266349Sqs148142 if (rs & HPI_PFC_ERROR) {
2276349Sqs148142 MUTEX_EXIT(&hw_p->hxge_tcam_lock);
2286349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL,
2296349Sqs148142 " hxge_tcam_default_add_entry tcam entry write"
2306349Sqs148142 " failed for ASC RAM location %d", location));
2316349Sqs148142 return (HXGE_ERROR);
2326349Sqs148142 }
2336349Sqs148142
2346349Sqs148142 bcopy((void *) &entry,
2356349Sqs148142 (void *) &hxgep->classifier.tcam_entries[location].tce,
2366349Sqs148142 sizeof (hxge_tcam_entry_t));
2376349Sqs148142
2386349Sqs148142 MUTEX_EXIT(&hw_p->hxge_tcam_lock);
2396349Sqs148142
2406349Sqs148142 return (HXGE_OK);
2416349Sqs148142 }
2426349Sqs148142
2436349Sqs148142 /*
2446349Sqs148142 * Configure one TCAM entry for each class and make it match
2456349Sqs148142 * everything within the class in order to spread the traffic
2466349Sqs148142 * among the DMA channels based on the source hash.
2476349Sqs148142 *
2486349Sqs148142 * This is the default for now. This may change when Crossbow is
2496349Sqs148142 * available for configuring TCAM.
2506349Sqs148142 */
2516349Sqs148142 static hxge_status_t
hxge_tcam_default_config(p_hxge_t hxgep)2526349Sqs148142 hxge_tcam_default_config(p_hxge_t hxgep)
2536349Sqs148142 {
2546349Sqs148142 uint8_t class;
2556349Sqs148142 uint32_t class_config;
2566349Sqs148142 hxge_status_t status = HXGE_OK;
2576349Sqs148142
2586349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_tcam_default_config"));
2596349Sqs148142
2606349Sqs148142 /*
2616349Sqs148142 * Add TCAM and its associative ram entries
2626349Sqs148142 * A wild card will be used for the class code in order to match
2636349Sqs148142 * any classes.
2646349Sqs148142 */
2656349Sqs148142 class = 0;
2666349Sqs148142 status = hxge_tcam_default_add_entry(hxgep, class);
2676349Sqs148142 if (status != HXGE_OK) {
2686349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2696349Sqs148142 "hxge_tcam_default_config "
2706349Sqs148142 "hxge_tcam_default_add_entry failed class %d ",
2716349Sqs148142 class));
2726349Sqs148142 return (HXGE_ERROR);
2736349Sqs148142 }
2746349Sqs148142
2756349Sqs148142 /* Enable the classes */
2766349Sqs148142 for (class = TCAM_CLASS_TCP_IPV4;
2776349Sqs148142 class <= TCAM_CLASS_SCTP_IPV6; class++) {
2786349Sqs148142 /*
2796349Sqs148142 * By default, it is set to HXGE_CLASS_TCAM_LOOKUP in
2806349Sqs148142 * hxge_ndd.c. It may be overwritten in hxge.conf.
2816349Sqs148142 */
2826349Sqs148142 class_config = hxgep->class_config.class_cfg[class];
2836349Sqs148142
2846349Sqs148142 status = hxge_pfc_ip_class_config(hxgep, class, class_config);
2856349Sqs148142 if (status & HPI_PFC_ERROR) {
2866349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
2876349Sqs148142 "hxge_tcam_default_config "
2886349Sqs148142 "hxge_pfc_ip_class_config failed "
2896349Sqs148142 " class %d config %x ", class, class_config));
2906349Sqs148142 return (HXGE_ERROR);
2916349Sqs148142 }
2926349Sqs148142 }
2936349Sqs148142
2946349Sqs148142 status = hxge_pfc_config_tcam_enable(hxgep);
2956349Sqs148142
2966349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_tcam_default_config"));
2976349Sqs148142
2986349Sqs148142 return (status);
2996349Sqs148142 }
3006349Sqs148142
3016349Sqs148142 hxge_status_t
hxge_pfc_set_default_mac_addr(p_hxge_t hxgep)3026349Sqs148142 hxge_pfc_set_default_mac_addr(p_hxge_t hxgep)
3036349Sqs148142 {
3046349Sqs148142 hxge_status_t status;
3056349Sqs148142
3066349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_set_default_mac_addr"));
3076349Sqs148142
3086349Sqs148142 MUTEX_ENTER(&hxgep->ouraddr_lock);
3096349Sqs148142
3106349Sqs148142 /*
3116349Sqs148142 * Set new interface local address and re-init device.
3126349Sqs148142 * This is destructive to any other streams attached
3136349Sqs148142 * to this device.
3146349Sqs148142 */
3156349Sqs148142 RW_ENTER_WRITER(&hxgep->filter_lock);
3166349Sqs148142 status = hxge_pfc_set_mac_address(hxgep,
3176349Sqs148142 HXGE_MAC_DEFAULT_ADDR_SLOT, &hxgep->ouraddr);
3186349Sqs148142 RW_EXIT(&hxgep->filter_lock);
3196349Sqs148142
3206349Sqs148142 MUTEX_EXIT(&hxgep->ouraddr_lock);
3216349Sqs148142
3226349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_set_default_mac_addr"));
3236349Sqs148142 return (status);
3246349Sqs148142 }
3256349Sqs148142
3266349Sqs148142 /*
3276349Sqs148142 * Add a multicast address entry into the HW hash table
3286349Sqs148142 */
3296349Sqs148142 hxge_status_t
hxge_add_mcast_addr(p_hxge_t hxgep,struct ether_addr * addrp)3306349Sqs148142 hxge_add_mcast_addr(p_hxge_t hxgep, struct ether_addr *addrp)
3316349Sqs148142 {
3326349Sqs148142 uint32_t mchash;
3336349Sqs148142 p_hash_filter_t hash_filter;
3346349Sqs148142 uint16_t hash_bit;
3356349Sqs148142 boolean_t rx_init = B_FALSE;
3366349Sqs148142 uint_t j;
3376349Sqs148142 hxge_status_t status = HXGE_OK;
3386349Sqs148142
3396349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_add_mcast_addr"));
3406349Sqs148142
3416349Sqs148142 RW_ENTER_WRITER(&hxgep->filter_lock);
3426349Sqs148142 mchash = crc32_mchash(addrp);
3436349Sqs148142
3446349Sqs148142 if (hxgep->hash_filter == NULL) {
3456349Sqs148142 HXGE_DEBUG_MSG((NULL, STR_CTL,
3466349Sqs148142 "Allocating hash filter storage."));
3476349Sqs148142 hxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
3486349Sqs148142 KM_SLEEP);
3496349Sqs148142 }
3506349Sqs148142
3516349Sqs148142 hash_filter = hxgep->hash_filter;
3526349Sqs148142 /*
3536349Sqs148142 * Note that mchash is an 8 bit value and thus 0 <= mchash <= 255.
3546349Sqs148142 * Consequently, 0 <= j <= 15 and 0 <= mchash % HASH_REG_WIDTH <= 15.
3556349Sqs148142 */
3566349Sqs148142 j = mchash / HASH_REG_WIDTH;
3576349Sqs148142 hash_bit = (1 << (mchash % HASH_REG_WIDTH));
3586349Sqs148142 hash_filter->hash_filter_regs[j] |= hash_bit;
3596349Sqs148142
3606349Sqs148142 hash_filter->hash_bit_ref_cnt[mchash]++;
3616349Sqs148142 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
3626349Sqs148142 hash_filter->hash_ref_cnt++;
3636349Sqs148142 rx_init = B_TRUE;
3646349Sqs148142 }
3656349Sqs148142
3666349Sqs148142 if (rx_init) {
3676349Sqs148142 (void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, B_FALSE);
3686349Sqs148142 (void) hxge_pfc_load_hash_table(hxgep);
3696349Sqs148142 (void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, B_TRUE);
3706349Sqs148142 }
3716349Sqs148142
3726349Sqs148142 RW_EXIT(&hxgep->filter_lock);
3736349Sqs148142
3746349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_add_mcast_addr"));
3756349Sqs148142
3766349Sqs148142 return (HXGE_OK);
3776349Sqs148142 fail:
3786349Sqs148142 RW_EXIT(&hxgep->filter_lock);
3796349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_add_mcast_addr: "
3806349Sqs148142 "Unable to add multicast address"));
3816349Sqs148142
3826349Sqs148142 return (status);
3836349Sqs148142 }
3846349Sqs148142
3856349Sqs148142 /*
3866349Sqs148142 * Remove a multicast address entry from the HW hash table
3876349Sqs148142 */
3886349Sqs148142 hxge_status_t
hxge_del_mcast_addr(p_hxge_t hxgep,struct ether_addr * addrp)3896349Sqs148142 hxge_del_mcast_addr(p_hxge_t hxgep, struct ether_addr *addrp)
3906349Sqs148142 {
3916349Sqs148142 uint32_t mchash;
3926349Sqs148142 p_hash_filter_t hash_filter;
3936349Sqs148142 uint16_t hash_bit;
3946349Sqs148142 boolean_t rx_init = B_FALSE;
3956349Sqs148142 uint_t j;
3966349Sqs148142 hxge_status_t status = HXGE_OK;
3976349Sqs148142
3986349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_del_mcast_addr"));
3996349Sqs148142 RW_ENTER_WRITER(&hxgep->filter_lock);
4006349Sqs148142 mchash = crc32_mchash(addrp);
4016349Sqs148142 if (hxgep->hash_filter == NULL) {
4026349Sqs148142 HXGE_DEBUG_MSG((NULL, STR_CTL,
4036349Sqs148142 "Hash filter already de_allocated."));
4046349Sqs148142 RW_EXIT(&hxgep->filter_lock);
4056349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_del_mcast_addr"));
4066349Sqs148142 return (HXGE_OK);
4076349Sqs148142 }
4086349Sqs148142
4096349Sqs148142 hash_filter = hxgep->hash_filter;
4106349Sqs148142 hash_filter->hash_bit_ref_cnt[mchash]--;
4116349Sqs148142 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
4126349Sqs148142 j = mchash / HASH_REG_WIDTH;
4136349Sqs148142 hash_bit = (1 << (mchash % HASH_REG_WIDTH));
4146349Sqs148142 hash_filter->hash_filter_regs[j] &= ~hash_bit;
4156349Sqs148142 hash_filter->hash_ref_cnt--;
4166349Sqs148142 rx_init = B_TRUE;
4176349Sqs148142 }
4186349Sqs148142
4196349Sqs148142 if (hash_filter->hash_ref_cnt == 0) {
4206349Sqs148142 HXGE_DEBUG_MSG((NULL, STR_CTL,
4216349Sqs148142 "De-allocating hash filter storage."));
4226349Sqs148142 KMEM_FREE(hash_filter, sizeof (hash_filter_t));
4236349Sqs148142 hxgep->hash_filter = NULL;
4246349Sqs148142 }
4256349Sqs148142
4266349Sqs148142 if (rx_init) {
4276349Sqs148142 (void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, B_FALSE);
4286349Sqs148142 (void) hxge_pfc_load_hash_table(hxgep);
4296349Sqs148142
4306349Sqs148142 /* Enable hash only if there are any hash entries */
4316349Sqs148142 if (hxgep->hash_filter != NULL)
4326349Sqs148142 (void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle,
4336349Sqs148142 B_TRUE);
4346349Sqs148142 }
4356349Sqs148142
4366349Sqs148142 RW_EXIT(&hxgep->filter_lock);
4376349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_del_mcast_addr"));
4386349Sqs148142
4396349Sqs148142 return (HXGE_OK);
4406349Sqs148142 fail:
4416349Sqs148142 RW_EXIT(&hxgep->filter_lock);
4426349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_del_mcast_addr: "
4436349Sqs148142 "Unable to remove multicast address"));
4446349Sqs148142
4456349Sqs148142 return (status);
4466349Sqs148142 }
4476349Sqs148142
448*8718SMichael.Speer@Sun.COM hxge_status_t
hxge_pfc_clear_mac_address(p_hxge_t hxgep,uint32_t slot)449*8718SMichael.Speer@Sun.COM hxge_pfc_clear_mac_address(p_hxge_t hxgep, uint32_t slot)
450*8718SMichael.Speer@Sun.COM {
451*8718SMichael.Speer@Sun.COM hpi_status_t status;
4526349Sqs148142
453*8718SMichael.Speer@Sun.COM status = hpi_pfc_clear_mac_address(hxgep->hpi_reg_handle, slot);
454*8718SMichael.Speer@Sun.COM if (status != HPI_SUCCESS)
455*8718SMichael.Speer@Sun.COM return (HXGE_ERROR);
456*8718SMichael.Speer@Sun.COM
457*8718SMichael.Speer@Sun.COM return (HXGE_OK);
458*8718SMichael.Speer@Sun.COM }
459*8718SMichael.Speer@Sun.COM
460*8718SMichael.Speer@Sun.COM hxge_status_t
hxge_pfc_set_mac_address(p_hxge_t hxgep,uint32_t slot,struct ether_addr * addrp)4616349Sqs148142 hxge_pfc_set_mac_address(p_hxge_t hxgep, uint32_t slot,
4626349Sqs148142 struct ether_addr *addrp)
4636349Sqs148142 {
4646349Sqs148142 hpi_handle_t handle;
4656349Sqs148142 uint64_t addr;
4666349Sqs148142 hpi_status_t hpi_status;
4676349Sqs148142 uint8_t *address = addrp->ether_addr_octet;
4686349Sqs148142 uint64_t tmp;
4696349Sqs148142 int i;
4706349Sqs148142
4716349Sqs148142 if (hxgep->hxge_hw_p == NULL) {
4726349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
4736349Sqs148142 " hxge_pfc_set_mac_address: common hardware not set"));
4746349Sqs148142 return (HXGE_ERROR);
4756349Sqs148142 }
4766349Sqs148142
4776349Sqs148142 /*
4786349Sqs148142 * Convert a byte array to a 48 bit value.
4796349Sqs148142 * Need to check endianess if in doubt
4806349Sqs148142 */
4816349Sqs148142 addr = 0;
4826349Sqs148142 for (i = 0; i < ETHERADDRL; i++) {
4836349Sqs148142 tmp = address[i];
4846349Sqs148142 addr <<= 8;
4856349Sqs148142 addr |= tmp;
4866349Sqs148142 }
4876349Sqs148142
4886349Sqs148142 handle = hxgep->hpi_reg_handle;
4896349Sqs148142 hpi_status = hpi_pfc_set_mac_address(handle, slot, addr);
4906349Sqs148142
4916349Sqs148142 if (hpi_status != HPI_SUCCESS) {
4926349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
4936349Sqs148142 " hxge_pfc_set_mac_address: failed to set address"));
4946349Sqs148142 return (HXGE_ERROR);
4956349Sqs148142 }
4966349Sqs148142
4976349Sqs148142 return (HXGE_OK);
4986349Sqs148142 }
4996349Sqs148142
5006349Sqs148142 /*ARGSUSED*/
5016349Sqs148142 hxge_status_t
hxge_pfc_num_macs_get(p_hxge_t hxgep,uint8_t * nmacs)502*8718SMichael.Speer@Sun.COM hxge_pfc_num_macs_get(p_hxge_t hxgep, uint8_t *nmacs)
5036349Sqs148142 {
5046349Sqs148142 *nmacs = PFC_N_MAC_ADDRESSES;
5056349Sqs148142 return (HXGE_OK);
5066349Sqs148142 }
5076349Sqs148142
5086349Sqs148142
5096349Sqs148142 hxge_status_t
hxge_pfc_set_hash(p_hxge_t hxgep,uint32_t seed)5106349Sqs148142 hxge_pfc_set_hash(p_hxge_t hxgep, uint32_t seed)
5116349Sqs148142 {
5126349Sqs148142 hpi_status_t rs = HPI_SUCCESS;
5136349Sqs148142 hpi_handle_t handle;
5146349Sqs148142 p_hxge_class_pt_cfg_t p_class_cfgp;
5156349Sqs148142
5166349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_set_hash"));
5176349Sqs148142
5186349Sqs148142 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
5196349Sqs148142 p_class_cfgp->init_hash = seed;
5206349Sqs148142 handle = hxgep->hpi_reg_handle;
5216349Sqs148142
5226349Sqs148142 rs = hpi_pfc_set_hash_seed_value(handle, seed);
5236349Sqs148142 if (rs & HPI_PFC_ERROR) {
5246349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
5256349Sqs148142 " hxge_pfc_set_hash %x failed ", seed));
5266349Sqs148142 return (HXGE_ERROR | rs);
5276349Sqs148142 }
5286349Sqs148142
5296349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " <== hxge_pfc_set_hash"));
5306349Sqs148142
5316349Sqs148142 return (HXGE_OK);
5326349Sqs148142 }
5336349Sqs148142
5346349Sqs148142 hxge_status_t
hxge_pfc_config_tcam_enable(p_hxge_t hxgep)5356349Sqs148142 hxge_pfc_config_tcam_enable(p_hxge_t hxgep)
5366349Sqs148142 {
5376349Sqs148142 hpi_handle_t handle;
5386349Sqs148142 boolean_t enable = B_TRUE;
5396349Sqs148142 hpi_status_t hpi_status;
5406349Sqs148142
5416349Sqs148142 handle = hxgep->hpi_reg_handle;
5426349Sqs148142 if (hxgep->hxge_hw_p == NULL) {
5436349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
5446349Sqs148142 " hxge_pfc_config_tcam_enable: common hardware not set"));
5456349Sqs148142 return (HXGE_ERROR);
5466349Sqs148142 }
5476349Sqs148142
5486349Sqs148142 hpi_status = hpi_pfc_set_tcam_enable(handle, enable);
5496349Sqs148142 if (hpi_status != HPI_SUCCESS) {
5506349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
5516349Sqs148142 " hpi_pfc_set_tcam_enable: enable tcam failed"));
5526349Sqs148142 return (HXGE_ERROR);
5536349Sqs148142 }
5546349Sqs148142
5556349Sqs148142 return (HXGE_OK);
5566349Sqs148142 }
5576349Sqs148142
5586349Sqs148142 hxge_status_t
hxge_pfc_config_tcam_disable(p_hxge_t hxgep)5596349Sqs148142 hxge_pfc_config_tcam_disable(p_hxge_t hxgep)
5606349Sqs148142 {
5616349Sqs148142 hpi_handle_t handle;
5626349Sqs148142 boolean_t enable = B_FALSE;
5636349Sqs148142 hpi_status_t hpi_status;
5646349Sqs148142
5656349Sqs148142 handle = hxgep->hpi_reg_handle;
5666349Sqs148142 if (hxgep->hxge_hw_p == NULL) {
5676349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
5686349Sqs148142 " hxge_pfc_config_tcam_disable: common hardware not set"));
5696349Sqs148142 return (HXGE_ERROR);
5706349Sqs148142 }
5716349Sqs148142
5726349Sqs148142 hpi_status = hpi_pfc_set_tcam_enable(handle, enable);
5736349Sqs148142 if (hpi_status != HPI_SUCCESS) {
5746349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
5756349Sqs148142 " hpi_pfc_set_tcam_enable: disable tcam failed"));
5766349Sqs148142 return (HXGE_ERROR);
5776349Sqs148142 }
5786349Sqs148142
5796349Sqs148142 return (HXGE_OK);
5806349Sqs148142 }
5816349Sqs148142
5826349Sqs148142 static hxge_status_t
hxge_cfg_tcam_ip_class_get(p_hxge_t hxgep,tcam_class_t class,uint32_t * class_config)5836349Sqs148142 hxge_cfg_tcam_ip_class_get(p_hxge_t hxgep, tcam_class_t class,
5846349Sqs148142 uint32_t *class_config)
5856349Sqs148142 {
5866349Sqs148142 hpi_status_t rs = HPI_SUCCESS;
5876349Sqs148142 tcam_key_cfg_t cfg;
5886349Sqs148142 hpi_handle_t handle;
5896349Sqs148142 uint32_t ccfg = 0;
5906349Sqs148142
5916349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_cfg_tcam_ip_class_get"));
5926349Sqs148142
5936349Sqs148142 bzero(&cfg, sizeof (tcam_key_cfg_t));
5946349Sqs148142 handle = hxgep->hpi_reg_handle;
5956349Sqs148142
5966349Sqs148142 rs = hpi_pfc_get_l3_class_config(handle, class, &cfg);
5976349Sqs148142 if (rs & HPI_PFC_ERROR) {
5986349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
5996349Sqs148142 " hxge_cfg_tcam_ip_class opt %x for class %d failed ",
6006349Sqs148142 class_config, class));
6016349Sqs148142 return (HXGE_ERROR | rs);
6026349Sqs148142 }
6036349Sqs148142 if (cfg.discard)
6046349Sqs148142 ccfg |= HXGE_CLASS_DISCARD;
6056349Sqs148142
6066349Sqs148142 if (cfg.lookup_enable)
6076349Sqs148142 ccfg |= HXGE_CLASS_TCAM_LOOKUP;
6086349Sqs148142
6096349Sqs148142 *class_config = ccfg;
6106349Sqs148142
6116349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_cfg_tcam_ip_class_get %x",
6126349Sqs148142 ccfg));
6136349Sqs148142
6146349Sqs148142 return (HXGE_OK);
6156349Sqs148142 }
6166349Sqs148142
6176349Sqs148142 hxge_status_t
hxge_pfc_ip_class_config_get(p_hxge_t hxgep,tcam_class_t class,uint32_t * config)6186349Sqs148142 hxge_pfc_ip_class_config_get(p_hxge_t hxgep, tcam_class_t class,
6196349Sqs148142 uint32_t *config)
6206349Sqs148142 {
6216349Sqs148142 uint32_t t_class_config;
6226349Sqs148142 int t_status = HXGE_OK;
6236349Sqs148142
6246349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_ip_class_config_get"));
6256349Sqs148142 t_class_config = 0;
6266349Sqs148142 t_status = hxge_cfg_tcam_ip_class_get(hxgep, class, &t_class_config);
6276349Sqs148142
6286349Sqs148142 if (t_status & HPI_PFC_ERROR) {
6296349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
6306349Sqs148142 " hxge_pfc_ip_class_config_get for class %d tcam failed",
6316349Sqs148142 class));
6326349Sqs148142 return (t_status);
6336349Sqs148142 }
6346349Sqs148142
6356349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " hxge_pfc_ip_class_config tcam %x",
6366349Sqs148142 t_class_config));
6376349Sqs148142
6386349Sqs148142 *config = t_class_config;
6396349Sqs148142
6406349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_ip_class_config_get"));
6416349Sqs148142 return (HXGE_OK);
6426349Sqs148142 }
6436349Sqs148142
6446349Sqs148142 static hxge_status_t
hxge_pfc_config_init(p_hxge_t hxgep)6456349Sqs148142 hxge_pfc_config_init(p_hxge_t hxgep)
6466349Sqs148142 {
6476864Sqs148142 hpi_handle_t handle;
6486864Sqs148142 block_reset_t reset_reg;
6496349Sqs148142
6506349Sqs148142 handle = hxgep->hpi_reg_handle;
6516349Sqs148142 if (hxgep->hxge_hw_p == NULL) {
6526349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
6536349Sqs148142 " hxge_pfc_config_init: common hardware not set"));
6546349Sqs148142 return (HXGE_ERROR);
6556349Sqs148142 }
6566349Sqs148142
6576864Sqs148142 /* Reset PFC block from PEU to clear any previous state */
6586864Sqs148142 reset_reg.value = 0;
6596864Sqs148142 reset_reg.bits.pfc_rst = 1;
6606864Sqs148142 HXGE_REG_WR32(hxgep->hpi_handle, BLOCK_RESET, reset_reg.value);
6616864Sqs148142 HXGE_DELAY(1000);
6626864Sqs148142
6636349Sqs148142 (void) hpi_pfc_set_tcam_enable(handle, B_FALSE);
6646349Sqs148142 (void) hpi_pfc_set_l2_hash(handle, B_FALSE);
6658366SQiyan.Sun@Sun.COM (void) hpi_pfc_set_tcp_cksum(handle, B_TRUE);
6666349Sqs148142 (void) hpi_pfc_set_default_dma(handle, 0);
6676349Sqs148142 (void) hpi_pfc_mac_addr_enable(handle, 0);
6686349Sqs148142 (void) hpi_pfc_set_force_csum(handle, B_FALSE);
6696349Sqs148142
6706349Sqs148142 /* Set the drop log mask to ignore the logs */
6716349Sqs148142 (void) hpi_pfc_set_drop_log_mask(handle, 1, 1, 1, 1, 1);
6726349Sqs148142
6736349Sqs148142 /* Clear the interrupt masks to receive interrupts */
6746349Sqs148142 (void) hpi_pfc_set_interrupt_mask(handle, 0, 0, 0);
6756349Sqs148142
6766349Sqs148142 /* Clear the interrupt status */
6776349Sqs148142 (void) hpi_pfc_clear_interrupt_status(handle);
6786349Sqs148142
6796349Sqs148142 return (HXGE_OK);
6806349Sqs148142 }
6816349Sqs148142
6826349Sqs148142 static hxge_status_t
hxge_pfc_tcam_invalidate_all(p_hxge_t hxgep)6836349Sqs148142 hxge_pfc_tcam_invalidate_all(p_hxge_t hxgep)
6846349Sqs148142 {
6856349Sqs148142 hpi_status_t rs = HPI_SUCCESS;
6866349Sqs148142 hpi_handle_t handle;
6876349Sqs148142 p_hxge_hw_list_t hw_p;
6886349Sqs148142
6896349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL,
6906349Sqs148142 "==> hxge_pfc_tcam_invalidate_all"));
6916349Sqs148142 handle = hxgep->hpi_reg_handle;
6926349Sqs148142 if ((hw_p = hxgep->hxge_hw_p) == NULL) {
6936349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
6946349Sqs148142 " hxge_pfc_tcam_invalidate_all: common hardware not set"));
6956349Sqs148142 return (HXGE_ERROR);
6966349Sqs148142 }
6976349Sqs148142
6986349Sqs148142 MUTEX_ENTER(&hw_p->hxge_tcam_lock);
6996349Sqs148142 rs = hpi_pfc_tcam_invalidate_all(handle);
7006349Sqs148142 MUTEX_EXIT(&hw_p->hxge_tcam_lock);
7016349Sqs148142
7026349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_tcam_invalidate_all"));
7036349Sqs148142 if (rs != HPI_SUCCESS)
7046349Sqs148142 return (HXGE_ERROR);
7056349Sqs148142
7066349Sqs148142 return (HXGE_OK);
7076349Sqs148142 }
7086349Sqs148142
7096349Sqs148142 static hxge_status_t
hxge_pfc_tcam_init(p_hxge_t hxgep)7106349Sqs148142 hxge_pfc_tcam_init(p_hxge_t hxgep)
7116349Sqs148142 {
7126349Sqs148142 hpi_status_t rs = HPI_SUCCESS;
7136349Sqs148142 hpi_handle_t handle;
7146349Sqs148142
7156349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_tcam_init"));
7166349Sqs148142 handle = hxgep->hpi_reg_handle;
7176349Sqs148142
7186349Sqs148142 if (hxgep->hxge_hw_p == NULL) {
7196349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7206349Sqs148142 " hxge_pfc_tcam_init: common hardware not set"));
7216349Sqs148142 return (HXGE_ERROR);
7226349Sqs148142 }
7236349Sqs148142
7246349Sqs148142 /*
7256349Sqs148142 * Disable the TCAM.
7266349Sqs148142 */
7276349Sqs148142 rs = hpi_pfc_set_tcam_enable(handle, B_FALSE);
7286349Sqs148142 if (rs != HPI_SUCCESS) {
7296349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "failed TCAM Disable\n"));
7306349Sqs148142 return (HXGE_ERROR | rs);
7316349Sqs148142 }
7326349Sqs148142
7336349Sqs148142 /*
7346349Sqs148142 * Invalidate all the TCAM entries for this blade.
7356349Sqs148142 */
7366349Sqs148142 rs = hxge_pfc_tcam_invalidate_all(hxgep);
7376349Sqs148142 if (rs != HPI_SUCCESS) {
7386349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "failed TCAM Disable\n"));
7396349Sqs148142 return (HXGE_ERROR | rs);
7406349Sqs148142 }
7416349Sqs148142
7426349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_tcam_init"));
7436349Sqs148142 return (HXGE_OK);
7446349Sqs148142 }
7456349Sqs148142
7466349Sqs148142 static hxge_status_t
hxge_pfc_vlan_tbl_clear_all(p_hxge_t hxgep)7476349Sqs148142 hxge_pfc_vlan_tbl_clear_all(p_hxge_t hxgep)
7486349Sqs148142 {
7496349Sqs148142 hpi_handle_t handle;
7506349Sqs148142 hpi_status_t rs = HPI_SUCCESS;
7516349Sqs148142 p_hxge_hw_list_t hw_p;
7526349Sqs148142
7536349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_vlan_tbl_clear_all "));
7546349Sqs148142
7556349Sqs148142 handle = hxgep->hpi_reg_handle;
7566349Sqs148142 if ((hw_p = hxgep->hxge_hw_p) == NULL) {
7576349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7586349Sqs148142 " hxge_pfc_vlan_tbl_clear_all: common hardware not set"));
7596349Sqs148142 return (HXGE_ERROR);
7606349Sqs148142 }
7616349Sqs148142
762*8718SMichael.Speer@Sun.COM MUTEX_ENTER(&hw_p->hxge_vlan_lock);
7636349Sqs148142 rs = hpi_pfc_cfg_vlan_table_clear(handle);
764*8718SMichael.Speer@Sun.COM MUTEX_EXIT(&hw_p->hxge_vlan_lock);
7656349Sqs148142
7666349Sqs148142 if (rs != HPI_SUCCESS) {
7676349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
7686349Sqs148142 "failed vlan table clear\n"));
7696349Sqs148142 return (HXGE_ERROR | rs);
7706349Sqs148142 }
7716349Sqs148142
7726349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_vlan_tbl_clear_all "));
7736349Sqs148142 return (HXGE_OK);
7746349Sqs148142 }
7756349Sqs148142
7766349Sqs148142 hxge_status_t
hxge_pfc_ip_class_config(p_hxge_t hxgep,tcam_class_t class,uint32_t config)7776349Sqs148142 hxge_pfc_ip_class_config(p_hxge_t hxgep, tcam_class_t class, uint32_t config)
7786349Sqs148142 {
7796349Sqs148142 uint32_t class_config;
7806349Sqs148142 p_hxge_class_pt_cfg_t p_class_cfgp;
7816349Sqs148142 tcam_key_cfg_t cfg;
7826349Sqs148142 hpi_handle_t handle;
7836349Sqs148142 hpi_status_t rs = HPI_SUCCESS;
7846349Sqs148142
7856349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_ip_class_config"));
7866349Sqs148142 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
7876349Sqs148142 class_config = p_class_cfgp->class_cfg[class];
7886349Sqs148142
7896349Sqs148142 if (class_config != config) {
7906349Sqs148142 p_class_cfgp->class_cfg[class] = config;
7916349Sqs148142 class_config = config;
7926349Sqs148142 }
7936349Sqs148142
7946349Sqs148142 handle = hxgep->hpi_reg_handle;
7956349Sqs148142
7966349Sqs148142 if (class == TCAM_CLASS_ETYPE_1 || class == TCAM_CLASS_ETYPE_2) {
7976349Sqs148142 rs = hpi_pfc_set_l2_class_slot(handle,
7986349Sqs148142 class_config & HXGE_CLASS_ETHER_TYPE_MASK,
7996349Sqs148142 class_config & HXGE_CLASS_VALID,
8006349Sqs148142 class - TCAM_CLASS_ETYPE_1);
8016349Sqs148142 } else {
8026349Sqs148142 if (class_config & HXGE_CLASS_DISCARD)
8036349Sqs148142 cfg.discard = 1;
8046349Sqs148142 else
8056349Sqs148142 cfg.discard = 0;
8066349Sqs148142 if (class_config & HXGE_CLASS_TCAM_LOOKUP)
8076349Sqs148142 cfg.lookup_enable = 1;
8086349Sqs148142 else
8096349Sqs148142 cfg.lookup_enable = 0;
8106349Sqs148142
8116349Sqs148142 rs = hpi_pfc_set_l3_class_config(handle, class, cfg);
8126349Sqs148142 }
8136349Sqs148142
8146349Sqs148142 if (rs & HPI_PFC_ERROR) {
8156349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL,
8166349Sqs148142 " hxge_pfc_ip_class_config %x for class %d tcam failed",
8176349Sqs148142 config, class));
8186349Sqs148142 return (HXGE_ERROR);
8196349Sqs148142 }
8206349Sqs148142
8216349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_ip_class_config"));
8226349Sqs148142 return (HXGE_OK);
8236349Sqs148142 }
8246349Sqs148142
8256349Sqs148142 hxge_status_t
hxge_pfc_ip_class_config_all(p_hxge_t hxgep)8266349Sqs148142 hxge_pfc_ip_class_config_all(p_hxge_t hxgep)
8276349Sqs148142 {
8286349Sqs148142 uint32_t class_config;
8296349Sqs148142 tcam_class_t cl;
8306349Sqs148142 int status = HXGE_OK;
8316349Sqs148142
8326349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_ip_class_config_all"));
8336349Sqs148142
8346349Sqs148142 for (cl = TCAM_CLASS_ETYPE_1; cl <= TCAM_CLASS_SCTP_IPV6; cl++) {
8356349Sqs148142 if (cl == TCAM_CLASS_RESERVED_4 ||
8366349Sqs148142 cl == TCAM_CLASS_RESERVED_5 ||
8376349Sqs148142 cl == TCAM_CLASS_RESERVED_6 ||
8386349Sqs148142 cl == TCAM_CLASS_RESERVED_7)
8396349Sqs148142 continue;
8406349Sqs148142
8416349Sqs148142 class_config = hxgep->class_config.class_cfg[cl];
8426349Sqs148142 status = hxge_pfc_ip_class_config(hxgep, cl, class_config);
8436349Sqs148142 if (status & HPI_PFC_ERROR) {
8446349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
8456349Sqs148142 "hxge_pfc_ip_class_config failed "
8466349Sqs148142 " class %d config %x ", cl, class_config));
8476349Sqs148142 }
8486349Sqs148142 }
8496349Sqs148142
8506349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_ip_class_config_all"));
8516349Sqs148142 return (HXGE_OK);
8526349Sqs148142 }
8536349Sqs148142
8546349Sqs148142 static hxge_status_t
hxge_pfc_update_hw(p_hxge_t hxgep)8556349Sqs148142 hxge_pfc_update_hw(p_hxge_t hxgep)
8566349Sqs148142 {
8576349Sqs148142 hxge_status_t status = HXGE_OK;
8586349Sqs148142 hpi_handle_t handle;
8596349Sqs148142 p_hxge_param_t pa;
8606349Sqs148142 int i;
8616349Sqs148142 boolean_t parity = 0;
8626349Sqs148142 boolean_t implicit_valid = 0;
8636349Sqs148142 vlan_id_t implicit_vlan_id;
8647775SQiyan.Sun@Sun.COM uint32_t vlanid_group;
8657775SQiyan.Sun@Sun.COM uint64_t offset;
8667775SQiyan.Sun@Sun.COM int max_vlan_groups;
8677775SQiyan.Sun@Sun.COM int vlan_group_step;
8686349Sqs148142
8696349Sqs148142 p_hxge_class_pt_cfg_t p_class_cfgp;
8706349Sqs148142
8716349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_update_hw"));
8726349Sqs148142 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config;
8736349Sqs148142 handle = hxgep->hpi_reg_handle;
8746349Sqs148142
8756349Sqs148142 status = hxge_pfc_set_hash(hxgep, p_class_cfgp->init_hash);
8766349Sqs148142 if (status != HXGE_OK) {
8776349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "hxge_pfc_set_hash Failed"));
8786349Sqs148142 return (HXGE_ERROR);
8796349Sqs148142 }
8806349Sqs148142
8817775SQiyan.Sun@Sun.COM /*
8827775SQiyan.Sun@Sun.COM * configure vlan table to join all vlans in order for Solaris
8837775SQiyan.Sun@Sun.COM * network to receive vlan packets of any acceptible VIDs.
8847775SQiyan.Sun@Sun.COM * This may change when Solaris network passes VIDs down.
8857775SQiyan.Sun@Sun.COM */
8867775SQiyan.Sun@Sun.COM vlanid_group = 0xffffffff;
8877775SQiyan.Sun@Sun.COM max_vlan_groups = 128;
8887775SQiyan.Sun@Sun.COM vlan_group_step = 8;
8897775SQiyan.Sun@Sun.COM for (i = 0; i < max_vlan_groups; i++) {
8907775SQiyan.Sun@Sun.COM offset = PFC_VLAN_TABLE + i * vlan_group_step;
8917775SQiyan.Sun@Sun.COM REG_PIO_WRITE64(handle, offset, vlanid_group);
8926349Sqs148142 }
8936349Sqs148142
8946349Sqs148142 /* Configure the vlan_ctrl register */
8956349Sqs148142 /* Let hw generate the parity bits in pfc_vlan_table */
8966349Sqs148142 parity = 0;
8976349Sqs148142
8986349Sqs148142 pa = (p_hxge_param_t)&hxgep->param_arr[param_implicit_vlan_id];
8996349Sqs148142 implicit_vlan_id = (vlan_id_t)pa->value;
9006349Sqs148142
9016349Sqs148142 /*
9026349Sqs148142 * Enable it only if there is a valid implicity vlan id either in
9036349Sqs148142 * NDD table or the .conf file.
9046349Sqs148142 */
9056349Sqs148142 if (implicit_vlan_id >= VLAN_ID_MIN && implicit_vlan_id <= VLAN_ID_MAX)
9066349Sqs148142 implicit_valid = 1;
9076349Sqs148142
9086349Sqs148142 status = hpi_pfc_cfg_vlan_control_set(handle, parity, implicit_valid,
9096349Sqs148142 implicit_vlan_id);
9106349Sqs148142 if (status != HPI_SUCCESS) {
9116349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL,
9126349Sqs148142 "hxge_pfc_update_hw: hpi_pfc_cfg_vlan_control_set failed"));
9136349Sqs148142 return (HXGE_ERROR);
9146349Sqs148142 }
9156349Sqs148142
9166349Sqs148142 /* config MAC addresses */
9176349Sqs148142 /* Need to think about this */
9186349Sqs148142
9196349Sqs148142 /* Configure hash value and classes */
9206349Sqs148142 status = hxge_pfc_ip_class_config_all(hxgep);
9216349Sqs148142 if (status != HXGE_OK) {
9226349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
9236349Sqs148142 "hxge_pfc_ip_class_config_all Failed"));
9246349Sqs148142 return (HXGE_ERROR);
9256349Sqs148142 }
9266349Sqs148142
9276349Sqs148142 return (HXGE_OK);
9286349Sqs148142 }
9296349Sqs148142
9306349Sqs148142 hxge_status_t
hxge_pfc_hw_reset(p_hxge_t hxgep)9316349Sqs148142 hxge_pfc_hw_reset(p_hxge_t hxgep)
9326349Sqs148142 {
9336349Sqs148142 hxge_status_t status = HXGE_OK;
9346349Sqs148142
9356349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_hw_reset"));
9366349Sqs148142
9376349Sqs148142 status = hxge_pfc_config_init(hxgep);
9386349Sqs148142 if (status != HXGE_OK) {
9396349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
9406349Sqs148142 "failed PFC config init."));
9416349Sqs148142 return (status);
9426349Sqs148142 }
9436349Sqs148142
9446349Sqs148142 status = hxge_pfc_tcam_init(hxgep);
9456349Sqs148142 if (status != HXGE_OK) {
9466349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "failed TCAM init."));
9476349Sqs148142 return (status);
9486349Sqs148142 }
9496349Sqs148142
9506349Sqs148142 /*
9516349Sqs148142 * invalidate VLAN RDC tables
9526349Sqs148142 */
9536349Sqs148142 status = hxge_pfc_vlan_tbl_clear_all(hxgep);
9546349Sqs148142 if (status != HXGE_OK) {
9556349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
9566349Sqs148142 "failed VLAN Table Invalidate. "));
9576349Sqs148142 return (status);
9586349Sqs148142 }
9596349Sqs148142 hxgep->classifier.state |= HXGE_PFC_HW_RESET;
9606349Sqs148142
9616349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_hw_reset"));
9626349Sqs148142
9636349Sqs148142 return (HXGE_OK);
9646349Sqs148142 }
9656349Sqs148142
9666349Sqs148142 hxge_status_t
hxge_classify_init_hw(p_hxge_t hxgep)9676349Sqs148142 hxge_classify_init_hw(p_hxge_t hxgep)
9686349Sqs148142 {
9696349Sqs148142 hxge_status_t status = HXGE_OK;
9706349Sqs148142
9716349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_init_hw"));
9726349Sqs148142
9736349Sqs148142 if (hxgep->classifier.state & HXGE_PFC_HW_INIT) {
9746349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL,
9756349Sqs148142 "hxge_classify_init_hw already init"));
9766349Sqs148142 return (HXGE_OK);
9776349Sqs148142 }
9786349Sqs148142
9796349Sqs148142 /* Now do a real configuration */
9806349Sqs148142 status = hxge_pfc_update_hw(hxgep);
9816349Sqs148142 if (status != HXGE_OK) {
9826349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
9836349Sqs148142 "hxge_pfc_update_hw failed"));
9846349Sqs148142 return (HXGE_ERROR);
9856349Sqs148142 }
9866349Sqs148142
9876349Sqs148142 status = hxge_tcam_default_config(hxgep);
9886349Sqs148142 if (status != HXGE_OK) {
9896349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
9906349Sqs148142 "hxge_tcam_default_config failed"));
9916349Sqs148142 return (status);
9926349Sqs148142 }
9936349Sqs148142
9946349Sqs148142 hxgep->classifier.state |= HXGE_PFC_HW_INIT;
9956349Sqs148142
9966349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_init_hw"));
9976349Sqs148142
9986349Sqs148142 return (HXGE_OK);
9996349Sqs148142 }
10006349Sqs148142
10016349Sqs148142 hxge_status_t
hxge_classify_init_sw(p_hxge_t hxgep)10026349Sqs148142 hxge_classify_init_sw(p_hxge_t hxgep)
10036349Sqs148142 {
10046349Sqs148142 int alloc_size;
10056349Sqs148142 hxge_classify_t *classify_ptr;
10066349Sqs148142
10076349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_init_sw"));
10086349Sqs148142 classify_ptr = &hxgep->classifier;
10096349Sqs148142
10106349Sqs148142 if (classify_ptr->state & HXGE_PFC_SW_INIT) {
10116349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL,
10126349Sqs148142 "hxge_classify_init_sw already init"));
10136349Sqs148142 return (HXGE_OK);
10146349Sqs148142 }
10156349Sqs148142
10166349Sqs148142 /* Init SW structures */
10176349Sqs148142 classify_ptr->tcam_size = TCAM_HXGE_TCAM_MAX_ENTRY;
10186349Sqs148142
10196349Sqs148142 alloc_size = sizeof (tcam_flow_spec_t) * classify_ptr->tcam_size;
10206349Sqs148142 classify_ptr->tcam_entries = KMEM_ZALLOC(alloc_size, NULL);
10216349Sqs148142 bzero(classify_ptr->class_usage, sizeof (classify_ptr->class_usage));
10226349Sqs148142
10236349Sqs148142 /* Start from the beginning of TCAM */
10246349Sqs148142 hxgep->classifier.tcam_location = 0;
10256349Sqs148142 classify_ptr->state |= HXGE_PFC_SW_INIT;
10266349Sqs148142
10276349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_init_sw"));
10286349Sqs148142
10296349Sqs148142 return (HXGE_OK);
10306349Sqs148142 }
10316349Sqs148142
10326349Sqs148142 hxge_status_t
hxge_classify_exit_sw(p_hxge_t hxgep)10336349Sqs148142 hxge_classify_exit_sw(p_hxge_t hxgep)
10346349Sqs148142 {
10356349Sqs148142 int alloc_size;
10366349Sqs148142 hxge_classify_t *classify_ptr;
10376349Sqs148142 int fsize;
10386349Sqs148142
10396349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_exit_sw"));
10406349Sqs148142 classify_ptr = &hxgep->classifier;
10416349Sqs148142
10426349Sqs148142 fsize = sizeof (tcam_flow_spec_t);
10436349Sqs148142 if (classify_ptr->tcam_entries) {
10446349Sqs148142 alloc_size = fsize * classify_ptr->tcam_size;
10456349Sqs148142 KMEM_FREE((void *) classify_ptr->tcam_entries, alloc_size);
10466349Sqs148142 }
10476349Sqs148142 hxgep->classifier.state = NULL;
10486349Sqs148142
10496349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_exit_sw"));
10506349Sqs148142
10516349Sqs148142 return (HXGE_OK);
10526349Sqs148142 }
10536349Sqs148142
10546349Sqs148142 /*ARGSUSED*/
10556349Sqs148142 hxge_status_t
hxge_pfc_handle_sys_errors(p_hxge_t hxgep)10566349Sqs148142 hxge_pfc_handle_sys_errors(p_hxge_t hxgep)
10576349Sqs148142 {
10586349Sqs148142 return (HXGE_OK);
10596349Sqs148142 }
10606349Sqs148142
10616349Sqs148142 uint_t
hxge_pfc_intr(caddr_t arg1,caddr_t arg2)10626349Sqs148142 hxge_pfc_intr(caddr_t arg1, caddr_t arg2)
10636349Sqs148142 {
10646349Sqs148142 p_hxge_ldv_t ldvp = (p_hxge_ldv_t)arg1;
10656349Sqs148142 p_hxge_t hxgep = (p_hxge_t)arg2;
10666349Sqs148142 hpi_handle_t handle;
10676349Sqs148142 p_hxge_pfc_stats_t statsp;
10686349Sqs148142 pfc_int_status_t int_status;
10696349Sqs148142 pfc_bad_cs_counter_t bad_cs_count;
10706349Sqs148142 pfc_drop_counter_t drop_count;
10716349Sqs148142 pfc_drop_log_t drop_log;
10726349Sqs148142 pfc_vlan_par_err_log_t vlan_par_err_log;
10736349Sqs148142 pfc_tcam_par_err_log_t tcam_par_err_log;
10746349Sqs148142
10756349Sqs148142 if (ldvp == NULL) {
10766349Sqs148142 HXGE_DEBUG_MSG((NULL, INT_CTL,
10776349Sqs148142 "<== hxge_pfc_intr: hxgep $%p ldvp $%p", hxgep, ldvp));
10786349Sqs148142 return (DDI_INTR_UNCLAIMED);
10796349Sqs148142 }
10806349Sqs148142
10816349Sqs148142 if (arg2 == NULL || (void *) ldvp->hxgep != arg2) {
10826349Sqs148142 hxgep = ldvp->hxgep;
10836349Sqs148142 }
10846349Sqs148142
10856349Sqs148142 handle = hxgep->hpi_reg_handle;
10866349Sqs148142 statsp = (p_hxge_pfc_stats_t)&hxgep->statsp->pfc_stats;
10876349Sqs148142
10886349Sqs148142 /*
10896349Sqs148142 * need to read the pfc interrupt status register to figure out
10906349Sqs148142 * what is happenning
10916349Sqs148142 */
10926349Sqs148142 (void) hpi_pfc_get_interrupt_status(handle, &int_status);
10936349Sqs148142
10946349Sqs148142 if (int_status.bits.pkt_drop) {
10956349Sqs148142 statsp->pkt_drop++;
10966349Sqs148142 if (statsp->pkt_drop == 1)
10976349Sqs148142 HXGE_ERROR_MSG((hxgep, INT_CTL, "PFC pkt_drop"));
10986349Sqs148142
10996349Sqs148142 /* Collect each individual drops */
11006349Sqs148142 (void) hpi_pfc_get_drop_log(handle, &drop_log);
11016349Sqs148142
11026349Sqs148142 if (drop_log.bits.tcp_ctrl_drop)
11036349Sqs148142 statsp->errlog.tcp_ctrl_drop++;
11046349Sqs148142 if (drop_log.bits.l2_addr_drop)
11056349Sqs148142 statsp->errlog.l2_addr_drop++;
11066349Sqs148142 if (drop_log.bits.class_code_drop)
11076349Sqs148142 statsp->errlog.class_code_drop++;
11086349Sqs148142 if (drop_log.bits.tcam_drop)
11096349Sqs148142 statsp->errlog.tcam_drop++;
11106349Sqs148142 if (drop_log.bits.vlan_drop)
11116349Sqs148142 statsp->errlog.vlan_drop++;
11126349Sqs148142
11136349Sqs148142 /* Collect the total drops for all kinds */
11146349Sqs148142 (void) hpi_pfc_get_drop_counter(handle, &drop_count.value);
11156349Sqs148142 statsp->drop_count += drop_count.bits.drop_count;
11166349Sqs148142 }
11176349Sqs148142
11186349Sqs148142 if (int_status.bits.tcam_parity_err) {
11196349Sqs148142 statsp->tcam_parity_err++;
11206349Sqs148142
11216349Sqs148142 (void) hpi_pfc_get_tcam_parity_log(handle, &tcam_par_err_log);
11226349Sqs148142 statsp->errlog.tcam_par_err_log = tcam_par_err_log.bits.addr;
11236349Sqs148142
11246349Sqs148142 if (statsp->tcam_parity_err == 1)
11256349Sqs148142 HXGE_ERROR_MSG((hxgep,
11266349Sqs148142 INT_CTL, " TCAM parity error addr: 0x%x",
11276349Sqs148142 tcam_par_err_log.bits.addr));
11286349Sqs148142 }
11296349Sqs148142
11306349Sqs148142 if (int_status.bits.vlan_parity_err) {
11316349Sqs148142 statsp->vlan_parity_err++;
11326349Sqs148142
11336349Sqs148142 (void) hpi_pfc_get_vlan_parity_log(handle, &vlan_par_err_log);
11346349Sqs148142 statsp->errlog.vlan_par_err_log = vlan_par_err_log.bits.addr;
11356349Sqs148142
11366349Sqs148142 if (statsp->vlan_parity_err == 1)
11376349Sqs148142 HXGE_ERROR_MSG((hxgep, INT_CTL,
11386349Sqs148142 " vlan table parity error addr: 0x%x",
11396349Sqs148142 vlan_par_err_log.bits.addr));
11406349Sqs148142 }
11416349Sqs148142
11426349Sqs148142 (void) hpi_pfc_get_bad_csum_counter(handle, &bad_cs_count.value);
11436349Sqs148142 statsp->bad_cs_count += bad_cs_count.bits.bad_cs_count;
11446349Sqs148142
11456349Sqs148142 (void) hpi_pfc_clear_interrupt_status(handle);
11466349Sqs148142 return (DDI_INTR_CLAIMED);
11476349Sqs148142 }
11486349Sqs148142
11496349Sqs148142 static void
hxge_pfc_get_next_mac_addr(uint8_t * st_mac,struct ether_addr * final_mac)11506349Sqs148142 hxge_pfc_get_next_mac_addr(uint8_t *st_mac, struct ether_addr *final_mac)
11516349Sqs148142 {
11526349Sqs148142 uint64_t mac[ETHERADDRL];
11536349Sqs148142 uint64_t mac_addr = 0;
11546349Sqs148142 int i, j;
11556349Sqs148142
11566349Sqs148142 for (i = ETHERADDRL - 1, j = 0; j < ETHERADDRL; i--, j++) {
11576349Sqs148142 mac[j] = st_mac[i];
11586349Sqs148142 mac_addr |= (mac[j] << (j*8));
11596349Sqs148142 }
11606349Sqs148142
11616349Sqs148142 final_mac->ether_addr_octet[0] = (mac_addr & 0xff0000000000) >> 40;
11626349Sqs148142 final_mac->ether_addr_octet[1] = (mac_addr & 0xff00000000) >> 32;
11636349Sqs148142 final_mac->ether_addr_octet[2] = (mac_addr & 0xff000000) >> 24;
11646349Sqs148142 final_mac->ether_addr_octet[3] = (mac_addr & 0xff0000) >> 16;
11656349Sqs148142 final_mac->ether_addr_octet[4] = (mac_addr & 0xff00) >> 8;
11666349Sqs148142 final_mac->ether_addr_octet[5] = (mac_addr & 0xff);
11676349Sqs148142 }
11686349Sqs148142
11696349Sqs148142 hxge_status_t
hxge_pfc_mac_addrs_get(p_hxge_t hxgep)11706349Sqs148142 hxge_pfc_mac_addrs_get(p_hxge_t hxgep)
11716349Sqs148142 {
11726349Sqs148142 hxge_status_t status = HXGE_OK;
11736349Sqs148142 hpi_status_t hpi_status = HPI_SUCCESS;
11746349Sqs148142 hpi_handle_t handle = HXGE_DEV_HPI_HANDLE(hxgep);
11756349Sqs148142 uint8_t mac_addr[ETHERADDRL];
11766349Sqs148142
11776349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_mac_addr_get"));
11786349Sqs148142
11796349Sqs148142 hpi_status = hpi_pfc_mac_addr_get_i(handle, mac_addr, 0);
11806349Sqs148142 if (hpi_status != HPI_SUCCESS) {
11816349Sqs148142 status = (HXGE_ERROR | hpi_status);
11826349Sqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
11836349Sqs148142 "hxge_pfc_mac_addr_get: pfc_mac_addr_get_i failed"));
11846349Sqs148142 goto exit;
11856349Sqs148142 }
11866349Sqs148142
11876349Sqs148142 hxge_pfc_get_next_mac_addr(mac_addr, &hxgep->factaddr);
11886349Sqs148142 HXGE_ERROR_MSG((hxgep, PFC_CTL, "MAC Addr(0): %x:%x:%x:%x:%x:%x\n",
11896349Sqs148142 mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
11906349Sqs148142 mac_addr[4], mac_addr[5]));
11916349Sqs148142
11926349Sqs148142 exit:
11936349Sqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, "<== hxge_pfc_mac_addr_get, "
11946349Sqs148142 "status [0x%x]", status));
11956349Sqs148142 return (status);
11966349Sqs148142 }
11976349Sqs148142
11986349Sqs148142 /*
11996349Sqs148142 * Calculate the bit in the multicast address filter
12006349Sqs148142 * that selects the given * address.
12016349Sqs148142 * Note: For Hydra, the last 8-bits are used.
12026349Sqs148142 */
12036349Sqs148142 static uint32_t
crc32_mchash(p_ether_addr_t addr)12046349Sqs148142 crc32_mchash(p_ether_addr_t addr)
12056349Sqs148142 {
12066349Sqs148142 uint8_t *cp;
12076349Sqs148142 uint32_t crc;
12086349Sqs148142 uint32_t c;
12096349Sqs148142 int byte;
12106349Sqs148142 int bit;
12116349Sqs148142
12126349Sqs148142 cp = (uint8_t *)addr;
12136349Sqs148142 crc = (uint32_t)0xffffffff;
12146349Sqs148142 for (byte = 0; byte < ETHERADDRL; byte++) {
12156349Sqs148142 /* Hydra calculates the hash backwardly */
12166349Sqs148142 c = (uint32_t)cp[ETHERADDRL - 1 - byte];
12176349Sqs148142 for (bit = 0; bit < 8; bit++) {
12186349Sqs148142 if ((c & 0x1) ^ (crc & 0x1))
12196349Sqs148142 crc = (crc >> 1)^0xedb88320;
12206349Sqs148142 else
12216349Sqs148142 crc = (crc >> 1);
12226349Sqs148142 c >>= 1;
12236349Sqs148142 }
12246349Sqs148142 }
12256349Sqs148142 return ((~crc) >> (32 - HASH_BITS));
12266349Sqs148142 }
12276349Sqs148142
12286349Sqs148142 static hxge_status_t
hxge_pfc_load_hash_table(p_hxge_t hxgep)12296349Sqs148142 hxge_pfc_load_hash_table(p_hxge_t hxgep)
12306349Sqs148142 {
12316349Sqs148142 uint32_t i;
12326349Sqs148142 uint16_t hashtab_e;
12336349Sqs148142 p_hash_filter_t hash_filter;
12346349Sqs148142 hpi_handle_t handle;
12356349Sqs148142
12366349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_load_hash_table\n"));
12376349Sqs148142 handle = hxgep->hpi_reg_handle;
12386349Sqs148142
12396349Sqs148142 /*
12406349Sqs148142 * Load the multicast hash filter bits.
12416349Sqs148142 */
12426349Sqs148142 hash_filter = hxgep->hash_filter;
12436349Sqs148142 for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
12446349Sqs148142 if (hash_filter != NULL) {
12456349Sqs148142 hashtab_e = (uint16_t)hash_filter->hash_filter_regs[i];
12466349Sqs148142 } else {
12476349Sqs148142 hashtab_e = 0;
12486349Sqs148142 }
12496349Sqs148142
12506349Sqs148142 if (hpi_pfc_set_multicast_hash_table(handle, i,
12516349Sqs148142 hashtab_e) != HPI_SUCCESS)
12526349Sqs148142 return (HXGE_ERROR);
12536349Sqs148142 }
12546349Sqs148142
12556349Sqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_load_hash_table\n"));
12566349Sqs148142
12576349Sqs148142 return (HXGE_OK);
12586349Sqs148142 }
1259