13dec9fcdSqs148142 /* 23dec9fcdSqs148142 * CDDL HEADER START 33dec9fcdSqs148142 * 43dec9fcdSqs148142 * The contents of this file are subject to the terms of the 53dec9fcdSqs148142 * Common Development and Distribution License (the "License"). 63dec9fcdSqs148142 * You may not use this file except in compliance with the License. 73dec9fcdSqs148142 * 83dec9fcdSqs148142 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93dec9fcdSqs148142 * or http://www.opensolaris.org/os/licensing. 103dec9fcdSqs148142 * See the License for the specific language governing permissions 113dec9fcdSqs148142 * and limitations under the License. 123dec9fcdSqs148142 * 133dec9fcdSqs148142 * When distributing Covered Code, include this CDDL HEADER in each 143dec9fcdSqs148142 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153dec9fcdSqs148142 * If applicable, add the following below this CDDL HEADER, with the 163dec9fcdSqs148142 * fields enclosed by brackets "[]" replaced with your own identifying 173dec9fcdSqs148142 * information: Portions Copyright [yyyy] [name of copyright owner] 183dec9fcdSqs148142 * 193dec9fcdSqs148142 * CDDL HEADER END 203dec9fcdSqs148142 */ 213dec9fcdSqs148142 223dec9fcdSqs148142 /* 23*1ed83081SMichael Speer * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 243dec9fcdSqs148142 * Use is subject to license terms. 253dec9fcdSqs148142 */ 263dec9fcdSqs148142 273dec9fcdSqs148142 #include <hxge_impl.h> 283dec9fcdSqs148142 #include <hxge_classify.h> 293dec9fcdSqs148142 #include <hxge_pfc.h> 303dec9fcdSqs148142 #include <hpi_pfc.h> 313dec9fcdSqs148142 #include <sys/ethernet.h> 323dec9fcdSqs148142 333dec9fcdSqs148142 static uint32_t crc32_mchash(p_ether_addr_t addr); 343dec9fcdSqs148142 static hxge_status_t hxge_pfc_load_hash_table(p_hxge_t hxgep); 353dec9fcdSqs148142 static uint32_t hxge_get_blade_id(p_hxge_t hxgep); 363dec9fcdSqs148142 static hxge_status_t hxge_tcam_default_add_entry(p_hxge_t hxgep, 373dec9fcdSqs148142 tcam_class_t class); 383dec9fcdSqs148142 static hxge_status_t hxge_tcam_default_config(p_hxge_t hxgep); 393dec9fcdSqs148142 403dec9fcdSqs148142 hxge_status_t 413dec9fcdSqs148142 hxge_classify_init(p_hxge_t hxgep) 423dec9fcdSqs148142 { 433dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 443dec9fcdSqs148142 453dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_init")); 463dec9fcdSqs148142 473dec9fcdSqs148142 status = hxge_classify_init_sw(hxgep); 483dec9fcdSqs148142 if (status != HXGE_OK) 493dec9fcdSqs148142 return (status); 503dec9fcdSqs148142 513dec9fcdSqs148142 status = hxge_classify_init_hw(hxgep); 523dec9fcdSqs148142 if (status != HXGE_OK) { 533dec9fcdSqs148142 (void) hxge_classify_exit_sw(hxgep); 543dec9fcdSqs148142 return (status); 553dec9fcdSqs148142 } 563dec9fcdSqs148142 573dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_init")); 583dec9fcdSqs148142 593dec9fcdSqs148142 return (HXGE_OK); 603dec9fcdSqs148142 } 613dec9fcdSqs148142 623dec9fcdSqs148142 hxge_status_t 633dec9fcdSqs148142 hxge_classify_uninit(p_hxge_t hxgep) 643dec9fcdSqs148142 { 653dec9fcdSqs148142 return (hxge_classify_exit_sw(hxgep)); 663dec9fcdSqs148142 } 673dec9fcdSqs148142 683dec9fcdSqs148142 static hxge_status_t 693dec9fcdSqs148142 hxge_tcam_dump_entry(p_hxge_t hxgep, uint32_t location) 703dec9fcdSqs148142 { 713dec9fcdSqs148142 hxge_tcam_entry_t tcam_rdptr; 723dec9fcdSqs148142 uint64_t asc_ram = 0; 733dec9fcdSqs148142 hpi_handle_t handle; 743dec9fcdSqs148142 hpi_status_t status; 753dec9fcdSqs148142 763dec9fcdSqs148142 handle = hxgep->hpi_reg_handle; 773dec9fcdSqs148142 783dec9fcdSqs148142 /* Retrieve the saved entry */ 793dec9fcdSqs148142 bcopy((void *)&hxgep->classifier.tcam_entries[location].tce, 803dec9fcdSqs148142 (void *)&tcam_rdptr, sizeof (hxge_tcam_entry_t)); 813dec9fcdSqs148142 823dec9fcdSqs148142 /* Compare the entry */ 833dec9fcdSqs148142 status = hpi_pfc_tcam_entry_read(handle, location, &tcam_rdptr); 843dec9fcdSqs148142 if (status == HPI_FAILURE) { 853dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 863dec9fcdSqs148142 " hxge_tcam_dump_entry: tcam read failed at location %d ", 873dec9fcdSqs148142 location)); 883dec9fcdSqs148142 return (HXGE_ERROR); 893dec9fcdSqs148142 } 903dec9fcdSqs148142 913dec9fcdSqs148142 status = hpi_pfc_tcam_asc_ram_entry_read(handle, location, &asc_ram); 923dec9fcdSqs148142 933dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "location %x\n" 943dec9fcdSqs148142 " key: %llx %llx\n mask: %llx %llx\n ASC RAM %llx \n", location, 953dec9fcdSqs148142 tcam_rdptr.key0, tcam_rdptr.key1, 963dec9fcdSqs148142 tcam_rdptr.mask0, tcam_rdptr.mask1, asc_ram)); 973dec9fcdSqs148142 return (HXGE_OK); 983dec9fcdSqs148142 } 993dec9fcdSqs148142 1003dec9fcdSqs148142 void 1013dec9fcdSqs148142 hxge_get_tcam(p_hxge_t hxgep, p_mblk_t mp) 1023dec9fcdSqs148142 { 1033dec9fcdSqs148142 uint32_t tcam_loc; 1043dec9fcdSqs148142 uint32_t *lptr; 1053dec9fcdSqs148142 int location; 1063dec9fcdSqs148142 int start_location = 0; 1073dec9fcdSqs148142 int stop_location = hxgep->classifier.tcam_size; 1083dec9fcdSqs148142 1093dec9fcdSqs148142 lptr = (uint32_t *)mp->b_rptr; 1103dec9fcdSqs148142 location = *lptr; 1113dec9fcdSqs148142 1123dec9fcdSqs148142 if ((location >= hxgep->classifier.tcam_size) || (location < -1)) { 1133dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 1143dec9fcdSqs148142 "hxge_tcam_dump: Invalid location %d \n", location)); 1153dec9fcdSqs148142 return; 1163dec9fcdSqs148142 } 1173dec9fcdSqs148142 if (location == -1) { 1183dec9fcdSqs148142 start_location = 0; 1193dec9fcdSqs148142 stop_location = hxgep->classifier.tcam_size; 1203dec9fcdSqs148142 } else { 1213dec9fcdSqs148142 start_location = location; 1223dec9fcdSqs148142 stop_location = location + 1; 1233dec9fcdSqs148142 } 1243dec9fcdSqs148142 for (tcam_loc = start_location; tcam_loc < stop_location; tcam_loc++) 1253dec9fcdSqs148142 (void) hxge_tcam_dump_entry(hxgep, tcam_loc); 1263dec9fcdSqs148142 } 1273dec9fcdSqs148142 1283dec9fcdSqs148142 /*ARGSUSED*/ 1293dec9fcdSqs148142 static hxge_status_t 1303dec9fcdSqs148142 hxge_add_tcam_entry(p_hxge_t hxgep, flow_resource_t *flow_res) 1313dec9fcdSqs148142 { 1323dec9fcdSqs148142 return (HXGE_OK); 1333dec9fcdSqs148142 } 1343dec9fcdSqs148142 1353dec9fcdSqs148142 void 1363dec9fcdSqs148142 hxge_put_tcam(p_hxge_t hxgep, p_mblk_t mp) 1373dec9fcdSqs148142 { 1383dec9fcdSqs148142 flow_resource_t *fs; 1393dec9fcdSqs148142 fs = (flow_resource_t *)mp->b_rptr; 1403dec9fcdSqs148142 1413dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 1423dec9fcdSqs148142 "hxge_put_tcam addr fs $%p type %x offset %x", 1433dec9fcdSqs148142 fs, fs->flow_spec.flow_type, fs->channel_cookie)); 1443dec9fcdSqs148142 1453dec9fcdSqs148142 (void) hxge_add_tcam_entry(hxgep, fs); 1463dec9fcdSqs148142 } 1473dec9fcdSqs148142 1483dec9fcdSqs148142 static uint32_t 1493dec9fcdSqs148142 hxge_get_blade_id(p_hxge_t hxgep) 1503dec9fcdSqs148142 { 1513dec9fcdSqs148142 phy_debug_training_vec_t blade_id; 1523dec9fcdSqs148142 1533dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_get_blade_id")); 1543dec9fcdSqs148142 HXGE_REG_RD32(hxgep->hpi_reg_handle, PHY_DEBUG_TRAINING_VEC, 1553dec9fcdSqs148142 &blade_id.value); 1563dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_get_blade_id: id = %d", 1573dec9fcdSqs148142 blade_id.bits.bld_num)); 1583dec9fcdSqs148142 1593dec9fcdSqs148142 return (blade_id.bits.bld_num); 1603dec9fcdSqs148142 } 1613dec9fcdSqs148142 1623dec9fcdSqs148142 static hxge_status_t 1633dec9fcdSqs148142 hxge_tcam_default_add_entry(p_hxge_t hxgep, tcam_class_t class) 1643dec9fcdSqs148142 { 1653dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 1663dec9fcdSqs148142 uint32_t location; 1673dec9fcdSqs148142 hxge_tcam_entry_t entry; 1683dec9fcdSqs148142 hxge_tcam_spread_t *key = NULL; 1693dec9fcdSqs148142 hxge_tcam_spread_t *mask = NULL; 1703dec9fcdSqs148142 hpi_handle_t handle; 1713dec9fcdSqs148142 p_hxge_hw_list_t hw_p; 1723dec9fcdSqs148142 1733dec9fcdSqs148142 if ((hw_p = hxgep->hxge_hw_p) == NULL) { 1743dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 1753dec9fcdSqs148142 " hxge_tcam_default_add_entry: common hardware not set")); 1763dec9fcdSqs148142 return (HXGE_ERROR); 1773dec9fcdSqs148142 } 1783dec9fcdSqs148142 1793dec9fcdSqs148142 bzero(&entry, sizeof (hxge_tcam_entry_t)); 1803dec9fcdSqs148142 1813dec9fcdSqs148142 /* 1823dec9fcdSqs148142 * The class id and blade id are common for all classes 1833dec9fcdSqs148142 * Only use the blade id for matching and the rest are wild cards. 1843dec9fcdSqs148142 * This will allow one TCAM entry to match all traffic in order 1853dec9fcdSqs148142 * to spread the traffic using source hash. 1863dec9fcdSqs148142 */ 1873dec9fcdSqs148142 key = &entry.key.spread; 1883dec9fcdSqs148142 mask = &entry.mask.spread; 1893dec9fcdSqs148142 1903dec9fcdSqs148142 key->blade_id = hxge_get_blade_id(hxgep); 1913dec9fcdSqs148142 192fe930412Sqs148142 mask->class_code = 0xf; 193fe930412Sqs148142 mask->class_code_l = 0x1; 1943dec9fcdSqs148142 mask->blade_id = 0; 1953dec9fcdSqs148142 mask->wild1 = 0x7ffffff; 196fe930412Sqs148142 mask->wild = 0xffffffff; 197fe930412Sqs148142 mask->wild_l = 0xffffffff; 1983dec9fcdSqs148142 1993dec9fcdSqs148142 location = class; 2003dec9fcdSqs148142 2013dec9fcdSqs148142 handle = hxgep->hpi_reg_handle; 2023dec9fcdSqs148142 2033dec9fcdSqs148142 MUTEX_ENTER(&hw_p->hxge_tcam_lock); 2043dec9fcdSqs148142 rs = hpi_pfc_tcam_entry_write(handle, location, &entry); 2053dec9fcdSqs148142 if (rs & HPI_PFC_ERROR) { 2063dec9fcdSqs148142 MUTEX_EXIT(&hw_p->hxge_tcam_lock); 2073dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 2083dec9fcdSqs148142 " hxge_tcam_default_add_entry tcam entry write" 2093dec9fcdSqs148142 " failed for location %d", location)); 2103dec9fcdSqs148142 return (HXGE_ERROR); 2113dec9fcdSqs148142 } 2123dec9fcdSqs148142 2133dec9fcdSqs148142 /* Add the associative portion */ 2143dec9fcdSqs148142 entry.match_action.value = 0; 2153dec9fcdSqs148142 2163dec9fcdSqs148142 /* Use source hash to spread traffic */ 2173dec9fcdSqs148142 entry.match_action.bits.channel_d = 0; 2183dec9fcdSqs148142 entry.match_action.bits.channel_c = 1; 2193dec9fcdSqs148142 entry.match_action.bits.channel_b = 2; 2203dec9fcdSqs148142 entry.match_action.bits.channel_a = 3; 2213dec9fcdSqs148142 entry.match_action.bits.source_hash = 1; 2223dec9fcdSqs148142 entry.match_action.bits.discard = 0; 2233dec9fcdSqs148142 2243dec9fcdSqs148142 rs = hpi_pfc_tcam_asc_ram_entry_write(handle, 2253dec9fcdSqs148142 location, entry.match_action.value); 2263dec9fcdSqs148142 if (rs & HPI_PFC_ERROR) { 2273dec9fcdSqs148142 MUTEX_EXIT(&hw_p->hxge_tcam_lock); 2283dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, 2293dec9fcdSqs148142 " hxge_tcam_default_add_entry tcam entry write" 2303dec9fcdSqs148142 " failed for ASC RAM location %d", location)); 2313dec9fcdSqs148142 return (HXGE_ERROR); 2323dec9fcdSqs148142 } 2333dec9fcdSqs148142 2343dec9fcdSqs148142 bcopy((void *) &entry, 2353dec9fcdSqs148142 (void *) &hxgep->classifier.tcam_entries[location].tce, 2363dec9fcdSqs148142 sizeof (hxge_tcam_entry_t)); 2373dec9fcdSqs148142 2383dec9fcdSqs148142 MUTEX_EXIT(&hw_p->hxge_tcam_lock); 2393dec9fcdSqs148142 2403dec9fcdSqs148142 return (HXGE_OK); 2413dec9fcdSqs148142 } 2423dec9fcdSqs148142 2433dec9fcdSqs148142 /* 2443dec9fcdSqs148142 * Configure one TCAM entry for each class and make it match 2453dec9fcdSqs148142 * everything within the class in order to spread the traffic 2463dec9fcdSqs148142 * among the DMA channels based on the source hash. 2473dec9fcdSqs148142 * 2483dec9fcdSqs148142 * This is the default for now. This may change when Crossbow is 2493dec9fcdSqs148142 * available for configuring TCAM. 2503dec9fcdSqs148142 */ 2513dec9fcdSqs148142 static hxge_status_t 2523dec9fcdSqs148142 hxge_tcam_default_config(p_hxge_t hxgep) 2533dec9fcdSqs148142 { 2543dec9fcdSqs148142 uint8_t class; 2553dec9fcdSqs148142 uint32_t class_config; 2563dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 2573dec9fcdSqs148142 2583dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_tcam_default_config")); 2593dec9fcdSqs148142 2603dec9fcdSqs148142 /* 2613dec9fcdSqs148142 * Add TCAM and its associative ram entries 2623dec9fcdSqs148142 * A wild card will be used for the class code in order to match 2633dec9fcdSqs148142 * any classes. 2643dec9fcdSqs148142 */ 2653dec9fcdSqs148142 class = 0; 2663dec9fcdSqs148142 status = hxge_tcam_default_add_entry(hxgep, class); 2673dec9fcdSqs148142 if (status != HXGE_OK) { 2683dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 2693dec9fcdSqs148142 "hxge_tcam_default_config " 2703dec9fcdSqs148142 "hxge_tcam_default_add_entry failed class %d ", 2713dec9fcdSqs148142 class)); 2723dec9fcdSqs148142 return (HXGE_ERROR); 2733dec9fcdSqs148142 } 2743dec9fcdSqs148142 2753dec9fcdSqs148142 /* Enable the classes */ 2763dec9fcdSqs148142 for (class = TCAM_CLASS_TCP_IPV4; 2773dec9fcdSqs148142 class <= TCAM_CLASS_SCTP_IPV6; class++) { 2783dec9fcdSqs148142 /* 2793dec9fcdSqs148142 * By default, it is set to HXGE_CLASS_TCAM_LOOKUP in 2803dec9fcdSqs148142 * hxge_ndd.c. It may be overwritten in hxge.conf. 2813dec9fcdSqs148142 */ 2823dec9fcdSqs148142 class_config = hxgep->class_config.class_cfg[class]; 2833dec9fcdSqs148142 2843dec9fcdSqs148142 status = hxge_pfc_ip_class_config(hxgep, class, class_config); 2853dec9fcdSqs148142 if (status & HPI_PFC_ERROR) { 2863dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 2873dec9fcdSqs148142 "hxge_tcam_default_config " 2883dec9fcdSqs148142 "hxge_pfc_ip_class_config failed " 2893dec9fcdSqs148142 " class %d config %x ", class, class_config)); 2903dec9fcdSqs148142 return (HXGE_ERROR); 2913dec9fcdSqs148142 } 2923dec9fcdSqs148142 } 2933dec9fcdSqs148142 2943dec9fcdSqs148142 status = hxge_pfc_config_tcam_enable(hxgep); 2953dec9fcdSqs148142 2963dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_tcam_default_config")); 2973dec9fcdSqs148142 2983dec9fcdSqs148142 return (status); 2993dec9fcdSqs148142 } 3003dec9fcdSqs148142 3013dec9fcdSqs148142 hxge_status_t 3023dec9fcdSqs148142 hxge_pfc_set_default_mac_addr(p_hxge_t hxgep) 3033dec9fcdSqs148142 { 3043dec9fcdSqs148142 hxge_status_t status; 3053dec9fcdSqs148142 3063dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_set_default_mac_addr")); 3073dec9fcdSqs148142 3083dec9fcdSqs148142 MUTEX_ENTER(&hxgep->ouraddr_lock); 3093dec9fcdSqs148142 3103dec9fcdSqs148142 /* 3113dec9fcdSqs148142 * Set new interface local address and re-init device. 3123dec9fcdSqs148142 * This is destructive to any other streams attached 3133dec9fcdSqs148142 * to this device. 3143dec9fcdSqs148142 */ 3153dec9fcdSqs148142 RW_ENTER_WRITER(&hxgep->filter_lock); 3163dec9fcdSqs148142 status = hxge_pfc_set_mac_address(hxgep, 3173dec9fcdSqs148142 HXGE_MAC_DEFAULT_ADDR_SLOT, &hxgep->ouraddr); 3183dec9fcdSqs148142 RW_EXIT(&hxgep->filter_lock); 3193dec9fcdSqs148142 3203dec9fcdSqs148142 MUTEX_EXIT(&hxgep->ouraddr_lock); 3213dec9fcdSqs148142 3223dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_set_default_mac_addr")); 3233dec9fcdSqs148142 return (status); 3243dec9fcdSqs148142 } 3253dec9fcdSqs148142 3263dec9fcdSqs148142 /* 3273dec9fcdSqs148142 * Add a multicast address entry into the HW hash table 3283dec9fcdSqs148142 */ 3293dec9fcdSqs148142 hxge_status_t 3303dec9fcdSqs148142 hxge_add_mcast_addr(p_hxge_t hxgep, struct ether_addr *addrp) 3313dec9fcdSqs148142 { 3323dec9fcdSqs148142 uint32_t mchash; 3333dec9fcdSqs148142 p_hash_filter_t hash_filter; 3343dec9fcdSqs148142 uint16_t hash_bit; 3353dec9fcdSqs148142 boolean_t rx_init = B_FALSE; 3363dec9fcdSqs148142 uint_t j; 3373dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 3383dec9fcdSqs148142 3393dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_add_mcast_addr")); 3403dec9fcdSqs148142 3413dec9fcdSqs148142 RW_ENTER_WRITER(&hxgep->filter_lock); 3423dec9fcdSqs148142 mchash = crc32_mchash(addrp); 3433dec9fcdSqs148142 3443dec9fcdSqs148142 if (hxgep->hash_filter == NULL) { 3453dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, STR_CTL, 3463dec9fcdSqs148142 "Allocating hash filter storage.")); 3473dec9fcdSqs148142 hxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 3483dec9fcdSqs148142 KM_SLEEP); 3493dec9fcdSqs148142 } 3503dec9fcdSqs148142 3513dec9fcdSqs148142 hash_filter = hxgep->hash_filter; 3523dec9fcdSqs148142 /* 3533dec9fcdSqs148142 * Note that mchash is an 8 bit value and thus 0 <= mchash <= 255. 3543dec9fcdSqs148142 * Consequently, 0 <= j <= 15 and 0 <= mchash % HASH_REG_WIDTH <= 15. 3553dec9fcdSqs148142 */ 3563dec9fcdSqs148142 j = mchash / HASH_REG_WIDTH; 3573dec9fcdSqs148142 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 3583dec9fcdSqs148142 hash_filter->hash_filter_regs[j] |= hash_bit; 3593dec9fcdSqs148142 3603dec9fcdSqs148142 hash_filter->hash_bit_ref_cnt[mchash]++; 3613dec9fcdSqs148142 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 3623dec9fcdSqs148142 hash_filter->hash_ref_cnt++; 3633dec9fcdSqs148142 rx_init = B_TRUE; 3643dec9fcdSqs148142 } 3653dec9fcdSqs148142 3663dec9fcdSqs148142 if (rx_init) { 3673dec9fcdSqs148142 (void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, B_FALSE); 3683dec9fcdSqs148142 (void) hxge_pfc_load_hash_table(hxgep); 3693dec9fcdSqs148142 (void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, B_TRUE); 3703dec9fcdSqs148142 } 3713dec9fcdSqs148142 3723dec9fcdSqs148142 RW_EXIT(&hxgep->filter_lock); 3733dec9fcdSqs148142 3743dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_add_mcast_addr")); 3753dec9fcdSqs148142 3763dec9fcdSqs148142 return (HXGE_OK); 3773dec9fcdSqs148142 fail: 3783dec9fcdSqs148142 RW_EXIT(&hxgep->filter_lock); 3793dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_add_mcast_addr: " 3803dec9fcdSqs148142 "Unable to add multicast address")); 3813dec9fcdSqs148142 3823dec9fcdSqs148142 return (status); 3833dec9fcdSqs148142 } 3843dec9fcdSqs148142 3853dec9fcdSqs148142 /* 3863dec9fcdSqs148142 * Remove a multicast address entry from the HW hash table 3873dec9fcdSqs148142 */ 3883dec9fcdSqs148142 hxge_status_t 3893dec9fcdSqs148142 hxge_del_mcast_addr(p_hxge_t hxgep, struct ether_addr *addrp) 3903dec9fcdSqs148142 { 3913dec9fcdSqs148142 uint32_t mchash; 3923dec9fcdSqs148142 p_hash_filter_t hash_filter; 3933dec9fcdSqs148142 uint16_t hash_bit; 3943dec9fcdSqs148142 boolean_t rx_init = B_FALSE; 3953dec9fcdSqs148142 uint_t j; 3963dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 3973dec9fcdSqs148142 3983dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_del_mcast_addr")); 3993dec9fcdSqs148142 RW_ENTER_WRITER(&hxgep->filter_lock); 4003dec9fcdSqs148142 mchash = crc32_mchash(addrp); 4013dec9fcdSqs148142 if (hxgep->hash_filter == NULL) { 4023dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, STR_CTL, 4033dec9fcdSqs148142 "Hash filter already de_allocated.")); 4043dec9fcdSqs148142 RW_EXIT(&hxgep->filter_lock); 4053dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_del_mcast_addr")); 4063dec9fcdSqs148142 return (HXGE_OK); 4073dec9fcdSqs148142 } 4083dec9fcdSqs148142 4093dec9fcdSqs148142 hash_filter = hxgep->hash_filter; 4103dec9fcdSqs148142 hash_filter->hash_bit_ref_cnt[mchash]--; 4113dec9fcdSqs148142 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 4123dec9fcdSqs148142 j = mchash / HASH_REG_WIDTH; 4133dec9fcdSqs148142 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 4143dec9fcdSqs148142 hash_filter->hash_filter_regs[j] &= ~hash_bit; 4153dec9fcdSqs148142 hash_filter->hash_ref_cnt--; 4163dec9fcdSqs148142 rx_init = B_TRUE; 4173dec9fcdSqs148142 } 4183dec9fcdSqs148142 4193dec9fcdSqs148142 if (hash_filter->hash_ref_cnt == 0) { 4203dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, STR_CTL, 4213dec9fcdSqs148142 "De-allocating hash filter storage.")); 4223dec9fcdSqs148142 KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 4233dec9fcdSqs148142 hxgep->hash_filter = NULL; 4243dec9fcdSqs148142 } 4253dec9fcdSqs148142 4263dec9fcdSqs148142 if (rx_init) { 4273dec9fcdSqs148142 (void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, B_FALSE); 4283dec9fcdSqs148142 (void) hxge_pfc_load_hash_table(hxgep); 4293dec9fcdSqs148142 4303dec9fcdSqs148142 /* Enable hash only if there are any hash entries */ 4313dec9fcdSqs148142 if (hxgep->hash_filter != NULL) 4323dec9fcdSqs148142 (void) hpi_pfc_set_l2_hash(hxgep->hpi_reg_handle, 4333dec9fcdSqs148142 B_TRUE); 4343dec9fcdSqs148142 } 4353dec9fcdSqs148142 4363dec9fcdSqs148142 RW_EXIT(&hxgep->filter_lock); 4373dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_del_mcast_addr")); 4383dec9fcdSqs148142 4393dec9fcdSqs148142 return (HXGE_OK); 4403dec9fcdSqs148142 fail: 4413dec9fcdSqs148142 RW_EXIT(&hxgep->filter_lock); 4423dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_del_mcast_addr: " 4433dec9fcdSqs148142 "Unable to remove multicast address")); 4443dec9fcdSqs148142 4453dec9fcdSqs148142 return (status); 4463dec9fcdSqs148142 } 4473dec9fcdSqs148142 448*1ed83081SMichael Speer hxge_status_t 449*1ed83081SMichael Speer hxge_pfc_clear_mac_address(p_hxge_t hxgep, uint32_t slot) 450*1ed83081SMichael Speer { 451*1ed83081SMichael Speer hpi_status_t status; 4523dec9fcdSqs148142 453*1ed83081SMichael Speer status = hpi_pfc_clear_mac_address(hxgep->hpi_reg_handle, slot); 454*1ed83081SMichael Speer if (status != HPI_SUCCESS) 455*1ed83081SMichael Speer return (HXGE_ERROR); 456*1ed83081SMichael Speer 457*1ed83081SMichael Speer return (HXGE_OK); 458*1ed83081SMichael Speer } 459*1ed83081SMichael Speer 460*1ed83081SMichael Speer hxge_status_t 4613dec9fcdSqs148142 hxge_pfc_set_mac_address(p_hxge_t hxgep, uint32_t slot, 4623dec9fcdSqs148142 struct ether_addr *addrp) 4633dec9fcdSqs148142 { 4643dec9fcdSqs148142 hpi_handle_t handle; 4653dec9fcdSqs148142 uint64_t addr; 4663dec9fcdSqs148142 hpi_status_t hpi_status; 4673dec9fcdSqs148142 uint8_t *address = addrp->ether_addr_octet; 4683dec9fcdSqs148142 uint64_t tmp; 4693dec9fcdSqs148142 int i; 4703dec9fcdSqs148142 4713dec9fcdSqs148142 if (hxgep->hxge_hw_p == NULL) { 4723dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 4733dec9fcdSqs148142 " hxge_pfc_set_mac_address: common hardware not set")); 4743dec9fcdSqs148142 return (HXGE_ERROR); 4753dec9fcdSqs148142 } 4763dec9fcdSqs148142 4773dec9fcdSqs148142 /* 4783dec9fcdSqs148142 * Convert a byte array to a 48 bit value. 4793dec9fcdSqs148142 * Need to check endianess if in doubt 4803dec9fcdSqs148142 */ 4813dec9fcdSqs148142 addr = 0; 4823dec9fcdSqs148142 for (i = 0; i < ETHERADDRL; i++) { 4833dec9fcdSqs148142 tmp = address[i]; 4843dec9fcdSqs148142 addr <<= 8; 4853dec9fcdSqs148142 addr |= tmp; 4863dec9fcdSqs148142 } 4873dec9fcdSqs148142 4883dec9fcdSqs148142 handle = hxgep->hpi_reg_handle; 4893dec9fcdSqs148142 hpi_status = hpi_pfc_set_mac_address(handle, slot, addr); 4903dec9fcdSqs148142 4913dec9fcdSqs148142 if (hpi_status != HPI_SUCCESS) { 4923dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 4933dec9fcdSqs148142 " hxge_pfc_set_mac_address: failed to set address")); 4943dec9fcdSqs148142 return (HXGE_ERROR); 4953dec9fcdSqs148142 } 4963dec9fcdSqs148142 4973dec9fcdSqs148142 return (HXGE_OK); 4983dec9fcdSqs148142 } 4993dec9fcdSqs148142 5003dec9fcdSqs148142 /*ARGSUSED*/ 5013dec9fcdSqs148142 hxge_status_t 502*1ed83081SMichael Speer hxge_pfc_num_macs_get(p_hxge_t hxgep, uint8_t *nmacs) 5033dec9fcdSqs148142 { 5043dec9fcdSqs148142 *nmacs = PFC_N_MAC_ADDRESSES; 5053dec9fcdSqs148142 return (HXGE_OK); 5063dec9fcdSqs148142 } 5073dec9fcdSqs148142 5083dec9fcdSqs148142 5093dec9fcdSqs148142 hxge_status_t 5103dec9fcdSqs148142 hxge_pfc_set_hash(p_hxge_t hxgep, uint32_t seed) 5113dec9fcdSqs148142 { 5123dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 5133dec9fcdSqs148142 hpi_handle_t handle; 5143dec9fcdSqs148142 p_hxge_class_pt_cfg_t p_class_cfgp; 5153dec9fcdSqs148142 5163dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_set_hash")); 5173dec9fcdSqs148142 5183dec9fcdSqs148142 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config; 5193dec9fcdSqs148142 p_class_cfgp->init_hash = seed; 5203dec9fcdSqs148142 handle = hxgep->hpi_reg_handle; 5213dec9fcdSqs148142 5223dec9fcdSqs148142 rs = hpi_pfc_set_hash_seed_value(handle, seed); 5233dec9fcdSqs148142 if (rs & HPI_PFC_ERROR) { 5243dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 5253dec9fcdSqs148142 " hxge_pfc_set_hash %x failed ", seed)); 5263dec9fcdSqs148142 return (HXGE_ERROR | rs); 5273dec9fcdSqs148142 } 5283dec9fcdSqs148142 5293dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " <== hxge_pfc_set_hash")); 5303dec9fcdSqs148142 5313dec9fcdSqs148142 return (HXGE_OK); 5323dec9fcdSqs148142 } 5333dec9fcdSqs148142 5343dec9fcdSqs148142 hxge_status_t 5353dec9fcdSqs148142 hxge_pfc_config_tcam_enable(p_hxge_t hxgep) 5363dec9fcdSqs148142 { 5373dec9fcdSqs148142 hpi_handle_t handle; 5383dec9fcdSqs148142 boolean_t enable = B_TRUE; 5393dec9fcdSqs148142 hpi_status_t hpi_status; 5403dec9fcdSqs148142 5413dec9fcdSqs148142 handle = hxgep->hpi_reg_handle; 5423dec9fcdSqs148142 if (hxgep->hxge_hw_p == NULL) { 5433dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 5443dec9fcdSqs148142 " hxge_pfc_config_tcam_enable: common hardware not set")); 5453dec9fcdSqs148142 return (HXGE_ERROR); 5463dec9fcdSqs148142 } 5473dec9fcdSqs148142 5483dec9fcdSqs148142 hpi_status = hpi_pfc_set_tcam_enable(handle, enable); 5493dec9fcdSqs148142 if (hpi_status != HPI_SUCCESS) { 5503dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 5513dec9fcdSqs148142 " hpi_pfc_set_tcam_enable: enable tcam failed")); 5523dec9fcdSqs148142 return (HXGE_ERROR); 5533dec9fcdSqs148142 } 5543dec9fcdSqs148142 5553dec9fcdSqs148142 return (HXGE_OK); 5563dec9fcdSqs148142 } 5573dec9fcdSqs148142 5583dec9fcdSqs148142 hxge_status_t 5593dec9fcdSqs148142 hxge_pfc_config_tcam_disable(p_hxge_t hxgep) 5603dec9fcdSqs148142 { 5613dec9fcdSqs148142 hpi_handle_t handle; 5623dec9fcdSqs148142 boolean_t enable = B_FALSE; 5633dec9fcdSqs148142 hpi_status_t hpi_status; 5643dec9fcdSqs148142 5653dec9fcdSqs148142 handle = hxgep->hpi_reg_handle; 5663dec9fcdSqs148142 if (hxgep->hxge_hw_p == NULL) { 5673dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 5683dec9fcdSqs148142 " hxge_pfc_config_tcam_disable: common hardware not set")); 5693dec9fcdSqs148142 return (HXGE_ERROR); 5703dec9fcdSqs148142 } 5713dec9fcdSqs148142 5723dec9fcdSqs148142 hpi_status = hpi_pfc_set_tcam_enable(handle, enable); 5733dec9fcdSqs148142 if (hpi_status != HPI_SUCCESS) { 5743dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 5753dec9fcdSqs148142 " hpi_pfc_set_tcam_enable: disable tcam failed")); 5763dec9fcdSqs148142 return (HXGE_ERROR); 5773dec9fcdSqs148142 } 5783dec9fcdSqs148142 5793dec9fcdSqs148142 return (HXGE_OK); 5803dec9fcdSqs148142 } 5813dec9fcdSqs148142 5823dec9fcdSqs148142 static hxge_status_t 5833dec9fcdSqs148142 hxge_cfg_tcam_ip_class_get(p_hxge_t hxgep, tcam_class_t class, 5843dec9fcdSqs148142 uint32_t *class_config) 5853dec9fcdSqs148142 { 5863dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 5873dec9fcdSqs148142 tcam_key_cfg_t cfg; 5883dec9fcdSqs148142 hpi_handle_t handle; 5893dec9fcdSqs148142 uint32_t ccfg = 0; 5903dec9fcdSqs148142 5913dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_cfg_tcam_ip_class_get")); 5923dec9fcdSqs148142 5933dec9fcdSqs148142 bzero(&cfg, sizeof (tcam_key_cfg_t)); 5943dec9fcdSqs148142 handle = hxgep->hpi_reg_handle; 5953dec9fcdSqs148142 5963dec9fcdSqs148142 rs = hpi_pfc_get_l3_class_config(handle, class, &cfg); 5973dec9fcdSqs148142 if (rs & HPI_PFC_ERROR) { 5983dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 5993dec9fcdSqs148142 " hxge_cfg_tcam_ip_class opt %x for class %d failed ", 6003dec9fcdSqs148142 class_config, class)); 6013dec9fcdSqs148142 return (HXGE_ERROR | rs); 6023dec9fcdSqs148142 } 6033dec9fcdSqs148142 if (cfg.discard) 6043dec9fcdSqs148142 ccfg |= HXGE_CLASS_DISCARD; 6053dec9fcdSqs148142 6063dec9fcdSqs148142 if (cfg.lookup_enable) 6073dec9fcdSqs148142 ccfg |= HXGE_CLASS_TCAM_LOOKUP; 6083dec9fcdSqs148142 6093dec9fcdSqs148142 *class_config = ccfg; 6103dec9fcdSqs148142 6113dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_cfg_tcam_ip_class_get %x", 6123dec9fcdSqs148142 ccfg)); 6133dec9fcdSqs148142 6143dec9fcdSqs148142 return (HXGE_OK); 6153dec9fcdSqs148142 } 6163dec9fcdSqs148142 6173dec9fcdSqs148142 hxge_status_t 6183dec9fcdSqs148142 hxge_pfc_ip_class_config_get(p_hxge_t hxgep, tcam_class_t class, 6193dec9fcdSqs148142 uint32_t *config) 6203dec9fcdSqs148142 { 6213dec9fcdSqs148142 uint32_t t_class_config; 6223dec9fcdSqs148142 int t_status = HXGE_OK; 6233dec9fcdSqs148142 6243dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_ip_class_config_get")); 6253dec9fcdSqs148142 t_class_config = 0; 6263dec9fcdSqs148142 t_status = hxge_cfg_tcam_ip_class_get(hxgep, class, &t_class_config); 6273dec9fcdSqs148142 6283dec9fcdSqs148142 if (t_status & HPI_PFC_ERROR) { 6293dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 6303dec9fcdSqs148142 " hxge_pfc_ip_class_config_get for class %d tcam failed", 6313dec9fcdSqs148142 class)); 6323dec9fcdSqs148142 return (t_status); 6333dec9fcdSqs148142 } 6343dec9fcdSqs148142 6353dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " hxge_pfc_ip_class_config tcam %x", 6363dec9fcdSqs148142 t_class_config)); 6373dec9fcdSqs148142 6383dec9fcdSqs148142 *config = t_class_config; 6393dec9fcdSqs148142 6403dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_ip_class_config_get")); 6413dec9fcdSqs148142 return (HXGE_OK); 6423dec9fcdSqs148142 } 6433dec9fcdSqs148142 6443dec9fcdSqs148142 static hxge_status_t 6453dec9fcdSqs148142 hxge_pfc_config_init(p_hxge_t hxgep) 6463dec9fcdSqs148142 { 6473dec9fcdSqs148142 hpi_handle_t handle; 648fe930412Sqs148142 block_reset_t reset_reg; 6493dec9fcdSqs148142 6503dec9fcdSqs148142 handle = hxgep->hpi_reg_handle; 6513dec9fcdSqs148142 if (hxgep->hxge_hw_p == NULL) { 6523dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 6533dec9fcdSqs148142 " hxge_pfc_config_init: common hardware not set")); 6543dec9fcdSqs148142 return (HXGE_ERROR); 6553dec9fcdSqs148142 } 6563dec9fcdSqs148142 657fe930412Sqs148142 /* Reset PFC block from PEU to clear any previous state */ 658fe930412Sqs148142 reset_reg.value = 0; 659fe930412Sqs148142 reset_reg.bits.pfc_rst = 1; 660fe930412Sqs148142 HXGE_REG_WR32(hxgep->hpi_handle, BLOCK_RESET, reset_reg.value); 661fe930412Sqs148142 HXGE_DELAY(1000); 662fe930412Sqs148142 6633dec9fcdSqs148142 (void) hpi_pfc_set_tcam_enable(handle, B_FALSE); 6643dec9fcdSqs148142 (void) hpi_pfc_set_l2_hash(handle, B_FALSE); 66557c5371aSQiyan Sun - Sun Microsystems - San Diego United States (void) hpi_pfc_set_tcp_cksum(handle, B_TRUE); 6663dec9fcdSqs148142 (void) hpi_pfc_set_default_dma(handle, 0); 6673dec9fcdSqs148142 (void) hpi_pfc_mac_addr_enable(handle, 0); 6683dec9fcdSqs148142 (void) hpi_pfc_set_force_csum(handle, B_FALSE); 6693dec9fcdSqs148142 6703dec9fcdSqs148142 /* Set the drop log mask to ignore the logs */ 6713dec9fcdSqs148142 (void) hpi_pfc_set_drop_log_mask(handle, 1, 1, 1, 1, 1); 6723dec9fcdSqs148142 6733dec9fcdSqs148142 /* Clear the interrupt masks to receive interrupts */ 6743dec9fcdSqs148142 (void) hpi_pfc_set_interrupt_mask(handle, 0, 0, 0); 6753dec9fcdSqs148142 6763dec9fcdSqs148142 /* Clear the interrupt status */ 6773dec9fcdSqs148142 (void) hpi_pfc_clear_interrupt_status(handle); 6783dec9fcdSqs148142 6793dec9fcdSqs148142 return (HXGE_OK); 6803dec9fcdSqs148142 } 6813dec9fcdSqs148142 6823dec9fcdSqs148142 static hxge_status_t 6833dec9fcdSqs148142 hxge_pfc_tcam_invalidate_all(p_hxge_t hxgep) 6843dec9fcdSqs148142 { 6853dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 6863dec9fcdSqs148142 hpi_handle_t handle; 6873dec9fcdSqs148142 p_hxge_hw_list_t hw_p; 6883dec9fcdSqs148142 6893dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, 6903dec9fcdSqs148142 "==> hxge_pfc_tcam_invalidate_all")); 6913dec9fcdSqs148142 handle = hxgep->hpi_reg_handle; 6923dec9fcdSqs148142 if ((hw_p = hxgep->hxge_hw_p) == NULL) { 6933dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 6943dec9fcdSqs148142 " hxge_pfc_tcam_invalidate_all: common hardware not set")); 6953dec9fcdSqs148142 return (HXGE_ERROR); 6963dec9fcdSqs148142 } 6973dec9fcdSqs148142 6983dec9fcdSqs148142 MUTEX_ENTER(&hw_p->hxge_tcam_lock); 6993dec9fcdSqs148142 rs = hpi_pfc_tcam_invalidate_all(handle); 7003dec9fcdSqs148142 MUTEX_EXIT(&hw_p->hxge_tcam_lock); 7013dec9fcdSqs148142 7023dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_tcam_invalidate_all")); 7033dec9fcdSqs148142 if (rs != HPI_SUCCESS) 7043dec9fcdSqs148142 return (HXGE_ERROR); 7053dec9fcdSqs148142 7063dec9fcdSqs148142 return (HXGE_OK); 7073dec9fcdSqs148142 } 7083dec9fcdSqs148142 7093dec9fcdSqs148142 static hxge_status_t 7103dec9fcdSqs148142 hxge_pfc_tcam_init(p_hxge_t hxgep) 7113dec9fcdSqs148142 { 7123dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 7133dec9fcdSqs148142 hpi_handle_t handle; 7143dec9fcdSqs148142 7153dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_tcam_init")); 7163dec9fcdSqs148142 handle = hxgep->hpi_reg_handle; 7173dec9fcdSqs148142 7183dec9fcdSqs148142 if (hxgep->hxge_hw_p == NULL) { 7193dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 7203dec9fcdSqs148142 " hxge_pfc_tcam_init: common hardware not set")); 7213dec9fcdSqs148142 return (HXGE_ERROR); 7223dec9fcdSqs148142 } 7233dec9fcdSqs148142 7243dec9fcdSqs148142 /* 7253dec9fcdSqs148142 * Disable the TCAM. 7263dec9fcdSqs148142 */ 7273dec9fcdSqs148142 rs = hpi_pfc_set_tcam_enable(handle, B_FALSE); 7283dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 7293dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "failed TCAM Disable\n")); 7303dec9fcdSqs148142 return (HXGE_ERROR | rs); 7313dec9fcdSqs148142 } 7323dec9fcdSqs148142 7333dec9fcdSqs148142 /* 7343dec9fcdSqs148142 * Invalidate all the TCAM entries for this blade. 7353dec9fcdSqs148142 */ 7363dec9fcdSqs148142 rs = hxge_pfc_tcam_invalidate_all(hxgep); 7373dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 7383dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "failed TCAM Disable\n")); 7393dec9fcdSqs148142 return (HXGE_ERROR | rs); 7403dec9fcdSqs148142 } 7413dec9fcdSqs148142 7423dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_tcam_init")); 7433dec9fcdSqs148142 return (HXGE_OK); 7443dec9fcdSqs148142 } 7453dec9fcdSqs148142 7463dec9fcdSqs148142 static hxge_status_t 7473dec9fcdSqs148142 hxge_pfc_vlan_tbl_clear_all(p_hxge_t hxgep) 7483dec9fcdSqs148142 { 7493dec9fcdSqs148142 hpi_handle_t handle; 7503dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 7513dec9fcdSqs148142 p_hxge_hw_list_t hw_p; 7523dec9fcdSqs148142 7533dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_vlan_tbl_clear_all ")); 7543dec9fcdSqs148142 7553dec9fcdSqs148142 handle = hxgep->hpi_reg_handle; 7563dec9fcdSqs148142 if ((hw_p = hxgep->hxge_hw_p) == NULL) { 7573dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 7583dec9fcdSqs148142 " hxge_pfc_vlan_tbl_clear_all: common hardware not set")); 7593dec9fcdSqs148142 return (HXGE_ERROR); 7603dec9fcdSqs148142 } 7613dec9fcdSqs148142 762*1ed83081SMichael Speer MUTEX_ENTER(&hw_p->hxge_vlan_lock); 7633dec9fcdSqs148142 rs = hpi_pfc_cfg_vlan_table_clear(handle); 764*1ed83081SMichael Speer MUTEX_EXIT(&hw_p->hxge_vlan_lock); 7653dec9fcdSqs148142 7663dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 7673dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 7683dec9fcdSqs148142 "failed vlan table clear\n")); 7693dec9fcdSqs148142 return (HXGE_ERROR | rs); 7703dec9fcdSqs148142 } 7713dec9fcdSqs148142 7723dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_vlan_tbl_clear_all ")); 7733dec9fcdSqs148142 return (HXGE_OK); 7743dec9fcdSqs148142 } 7753dec9fcdSqs148142 7763dec9fcdSqs148142 hxge_status_t 7773dec9fcdSqs148142 hxge_pfc_ip_class_config(p_hxge_t hxgep, tcam_class_t class, uint32_t config) 7783dec9fcdSqs148142 { 7793dec9fcdSqs148142 uint32_t class_config; 7803dec9fcdSqs148142 p_hxge_class_pt_cfg_t p_class_cfgp; 7813dec9fcdSqs148142 tcam_key_cfg_t cfg; 7823dec9fcdSqs148142 hpi_handle_t handle; 7833dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 7843dec9fcdSqs148142 7853dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_ip_class_config")); 7863dec9fcdSqs148142 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config; 7873dec9fcdSqs148142 class_config = p_class_cfgp->class_cfg[class]; 7883dec9fcdSqs148142 7893dec9fcdSqs148142 if (class_config != config) { 7903dec9fcdSqs148142 p_class_cfgp->class_cfg[class] = config; 7913dec9fcdSqs148142 class_config = config; 7923dec9fcdSqs148142 } 7933dec9fcdSqs148142 7943dec9fcdSqs148142 handle = hxgep->hpi_reg_handle; 7953dec9fcdSqs148142 7963dec9fcdSqs148142 if (class == TCAM_CLASS_ETYPE_1 || class == TCAM_CLASS_ETYPE_2) { 7973dec9fcdSqs148142 rs = hpi_pfc_set_l2_class_slot(handle, 7983dec9fcdSqs148142 class_config & HXGE_CLASS_ETHER_TYPE_MASK, 7993dec9fcdSqs148142 class_config & HXGE_CLASS_VALID, 8003dec9fcdSqs148142 class - TCAM_CLASS_ETYPE_1); 8013dec9fcdSqs148142 } else { 8023dec9fcdSqs148142 if (class_config & HXGE_CLASS_DISCARD) 8033dec9fcdSqs148142 cfg.discard = 1; 8043dec9fcdSqs148142 else 8053dec9fcdSqs148142 cfg.discard = 0; 8063dec9fcdSqs148142 if (class_config & HXGE_CLASS_TCAM_LOOKUP) 8073dec9fcdSqs148142 cfg.lookup_enable = 1; 8083dec9fcdSqs148142 else 8093dec9fcdSqs148142 cfg.lookup_enable = 0; 8103dec9fcdSqs148142 8113dec9fcdSqs148142 rs = hpi_pfc_set_l3_class_config(handle, class, cfg); 8123dec9fcdSqs148142 } 8133dec9fcdSqs148142 8143dec9fcdSqs148142 if (rs & HPI_PFC_ERROR) { 8153dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, 8163dec9fcdSqs148142 " hxge_pfc_ip_class_config %x for class %d tcam failed", 8173dec9fcdSqs148142 config, class)); 8183dec9fcdSqs148142 return (HXGE_ERROR); 8193dec9fcdSqs148142 } 8203dec9fcdSqs148142 8213dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_ip_class_config")); 8223dec9fcdSqs148142 return (HXGE_OK); 8233dec9fcdSqs148142 } 8243dec9fcdSqs148142 8253dec9fcdSqs148142 hxge_status_t 8263dec9fcdSqs148142 hxge_pfc_ip_class_config_all(p_hxge_t hxgep) 8273dec9fcdSqs148142 { 8283dec9fcdSqs148142 uint32_t class_config; 8293dec9fcdSqs148142 tcam_class_t cl; 8303dec9fcdSqs148142 int status = HXGE_OK; 8313dec9fcdSqs148142 8323dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_ip_class_config_all")); 8333dec9fcdSqs148142 8343dec9fcdSqs148142 for (cl = TCAM_CLASS_ETYPE_1; cl <= TCAM_CLASS_SCTP_IPV6; cl++) { 8353dec9fcdSqs148142 if (cl == TCAM_CLASS_RESERVED_4 || 8363dec9fcdSqs148142 cl == TCAM_CLASS_RESERVED_5 || 8373dec9fcdSqs148142 cl == TCAM_CLASS_RESERVED_6 || 8383dec9fcdSqs148142 cl == TCAM_CLASS_RESERVED_7) 8393dec9fcdSqs148142 continue; 8403dec9fcdSqs148142 8413dec9fcdSqs148142 class_config = hxgep->class_config.class_cfg[cl]; 8423dec9fcdSqs148142 status = hxge_pfc_ip_class_config(hxgep, cl, class_config); 8433dec9fcdSqs148142 if (status & HPI_PFC_ERROR) { 8443dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 8453dec9fcdSqs148142 "hxge_pfc_ip_class_config failed " 8463dec9fcdSqs148142 " class %d config %x ", cl, class_config)); 8473dec9fcdSqs148142 } 8483dec9fcdSqs148142 } 8493dec9fcdSqs148142 8503dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_ip_class_config_all")); 8513dec9fcdSqs148142 return (HXGE_OK); 8523dec9fcdSqs148142 } 8533dec9fcdSqs148142 8543dec9fcdSqs148142 static hxge_status_t 8553dec9fcdSqs148142 hxge_pfc_update_hw(p_hxge_t hxgep) 8563dec9fcdSqs148142 { 8573dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 8583dec9fcdSqs148142 hpi_handle_t handle; 8593dec9fcdSqs148142 p_hxge_param_t pa; 8603dec9fcdSqs148142 int i; 8613dec9fcdSqs148142 boolean_t parity = 0; 8623dec9fcdSqs148142 boolean_t implicit_valid = 0; 8633dec9fcdSqs148142 vlan_id_t implicit_vlan_id; 864ff4f3770SQiyan Sun - Sun Microsystems - San Diego United States uint32_t vlanid_group; 865ff4f3770SQiyan Sun - Sun Microsystems - San Diego United States uint64_t offset; 866ff4f3770SQiyan Sun - Sun Microsystems - San Diego United States int max_vlan_groups; 867ff4f3770SQiyan Sun - Sun Microsystems - San Diego United States int vlan_group_step; 8683dec9fcdSqs148142 8693dec9fcdSqs148142 p_hxge_class_pt_cfg_t p_class_cfgp; 8703dec9fcdSqs148142 8713dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_update_hw")); 8723dec9fcdSqs148142 p_class_cfgp = (p_hxge_class_pt_cfg_t)&hxgep->class_config; 8733dec9fcdSqs148142 handle = hxgep->hpi_reg_handle; 8743dec9fcdSqs148142 8753dec9fcdSqs148142 status = hxge_pfc_set_hash(hxgep, p_class_cfgp->init_hash); 8763dec9fcdSqs148142 if (status != HXGE_OK) { 8773dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "hxge_pfc_set_hash Failed")); 8783dec9fcdSqs148142 return (HXGE_ERROR); 8793dec9fcdSqs148142 } 8803dec9fcdSqs148142 881ff4f3770SQiyan Sun - Sun Microsystems - San Diego United States /* 882ff4f3770SQiyan Sun - Sun Microsystems - San Diego United States * configure vlan table to join all vlans in order for Solaris 883ff4f3770SQiyan Sun - Sun Microsystems - San Diego United States * network to receive vlan packets of any acceptible VIDs. 884ff4f3770SQiyan Sun - Sun Microsystems - San Diego United States * This may change when Solaris network passes VIDs down. 885ff4f3770SQiyan Sun - Sun Microsystems - San Diego United States */ 886ff4f3770SQiyan Sun - Sun Microsystems - San Diego United States vlanid_group = 0xffffffff; 887ff4f3770SQiyan Sun - Sun Microsystems - San Diego United States max_vlan_groups = 128; 888ff4f3770SQiyan Sun - Sun Microsystems - San Diego United States vlan_group_step = 8; 889ff4f3770SQiyan Sun - Sun Microsystems - San Diego United States for (i = 0; i < max_vlan_groups; i++) { 890ff4f3770SQiyan Sun - Sun Microsystems - San Diego United States offset = PFC_VLAN_TABLE + i * vlan_group_step; 891ff4f3770SQiyan Sun - Sun Microsystems - San Diego United States REG_PIO_WRITE64(handle, offset, vlanid_group); 8923dec9fcdSqs148142 } 8933dec9fcdSqs148142 8943dec9fcdSqs148142 /* Configure the vlan_ctrl register */ 8953dec9fcdSqs148142 /* Let hw generate the parity bits in pfc_vlan_table */ 8963dec9fcdSqs148142 parity = 0; 8973dec9fcdSqs148142 8983dec9fcdSqs148142 pa = (p_hxge_param_t)&hxgep->param_arr[param_implicit_vlan_id]; 8993dec9fcdSqs148142 implicit_vlan_id = (vlan_id_t)pa->value; 9003dec9fcdSqs148142 9013dec9fcdSqs148142 /* 9023dec9fcdSqs148142 * Enable it only if there is a valid implicity vlan id either in 9033dec9fcdSqs148142 * NDD table or the .conf file. 9043dec9fcdSqs148142 */ 9053dec9fcdSqs148142 if (implicit_vlan_id >= VLAN_ID_MIN && implicit_vlan_id <= VLAN_ID_MAX) 9063dec9fcdSqs148142 implicit_valid = 1; 9073dec9fcdSqs148142 9083dec9fcdSqs148142 status = hpi_pfc_cfg_vlan_control_set(handle, parity, implicit_valid, 9093dec9fcdSqs148142 implicit_vlan_id); 9103dec9fcdSqs148142 if (status != HPI_SUCCESS) { 9113dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, 9123dec9fcdSqs148142 "hxge_pfc_update_hw: hpi_pfc_cfg_vlan_control_set failed")); 9133dec9fcdSqs148142 return (HXGE_ERROR); 9143dec9fcdSqs148142 } 9153dec9fcdSqs148142 9163dec9fcdSqs148142 /* config MAC addresses */ 9173dec9fcdSqs148142 /* Need to think about this */ 9183dec9fcdSqs148142 9193dec9fcdSqs148142 /* Configure hash value and classes */ 9203dec9fcdSqs148142 status = hxge_pfc_ip_class_config_all(hxgep); 9213dec9fcdSqs148142 if (status != HXGE_OK) { 9223dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 9233dec9fcdSqs148142 "hxge_pfc_ip_class_config_all Failed")); 9243dec9fcdSqs148142 return (HXGE_ERROR); 9253dec9fcdSqs148142 } 9263dec9fcdSqs148142 9273dec9fcdSqs148142 return (HXGE_OK); 9283dec9fcdSqs148142 } 9293dec9fcdSqs148142 9303dec9fcdSqs148142 hxge_status_t 9313dec9fcdSqs148142 hxge_pfc_hw_reset(p_hxge_t hxgep) 9323dec9fcdSqs148142 { 9333dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 9343dec9fcdSqs148142 9353dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, " ==> hxge_pfc_hw_reset")); 9363dec9fcdSqs148142 9373dec9fcdSqs148142 status = hxge_pfc_config_init(hxgep); 9383dec9fcdSqs148142 if (status != HXGE_OK) { 9393dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 9403dec9fcdSqs148142 "failed PFC config init.")); 9413dec9fcdSqs148142 return (status); 9423dec9fcdSqs148142 } 9433dec9fcdSqs148142 9443dec9fcdSqs148142 status = hxge_pfc_tcam_init(hxgep); 9453dec9fcdSqs148142 if (status != HXGE_OK) { 9463dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "failed TCAM init.")); 9473dec9fcdSqs148142 return (status); 9483dec9fcdSqs148142 } 9493dec9fcdSqs148142 9503dec9fcdSqs148142 /* 9513dec9fcdSqs148142 * invalidate VLAN RDC tables 9523dec9fcdSqs148142 */ 9533dec9fcdSqs148142 status = hxge_pfc_vlan_tbl_clear_all(hxgep); 9543dec9fcdSqs148142 if (status != HXGE_OK) { 9553dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 9563dec9fcdSqs148142 "failed VLAN Table Invalidate. ")); 9573dec9fcdSqs148142 return (status); 9583dec9fcdSqs148142 } 9593dec9fcdSqs148142 hxgep->classifier.state |= HXGE_PFC_HW_RESET; 9603dec9fcdSqs148142 9613dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_hw_reset")); 9623dec9fcdSqs148142 9633dec9fcdSqs148142 return (HXGE_OK); 9643dec9fcdSqs148142 } 9653dec9fcdSqs148142 9663dec9fcdSqs148142 hxge_status_t 9673dec9fcdSqs148142 hxge_classify_init_hw(p_hxge_t hxgep) 9683dec9fcdSqs148142 { 9693dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 9703dec9fcdSqs148142 9713dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_init_hw")); 9723dec9fcdSqs148142 9733dec9fcdSqs148142 if (hxgep->classifier.state & HXGE_PFC_HW_INIT) { 9743dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, 9753dec9fcdSqs148142 "hxge_classify_init_hw already init")); 9763dec9fcdSqs148142 return (HXGE_OK); 9773dec9fcdSqs148142 } 9783dec9fcdSqs148142 9793dec9fcdSqs148142 /* Now do a real configuration */ 9803dec9fcdSqs148142 status = hxge_pfc_update_hw(hxgep); 9813dec9fcdSqs148142 if (status != HXGE_OK) { 9823dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 9833dec9fcdSqs148142 "hxge_pfc_update_hw failed")); 9843dec9fcdSqs148142 return (HXGE_ERROR); 9853dec9fcdSqs148142 } 9863dec9fcdSqs148142 9873dec9fcdSqs148142 status = hxge_tcam_default_config(hxgep); 9883dec9fcdSqs148142 if (status != HXGE_OK) { 9893dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 9903dec9fcdSqs148142 "hxge_tcam_default_config failed")); 9913dec9fcdSqs148142 return (status); 9923dec9fcdSqs148142 } 9933dec9fcdSqs148142 9943dec9fcdSqs148142 hxgep->classifier.state |= HXGE_PFC_HW_INIT; 9953dec9fcdSqs148142 9963dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_init_hw")); 9973dec9fcdSqs148142 9983dec9fcdSqs148142 return (HXGE_OK); 9993dec9fcdSqs148142 } 10003dec9fcdSqs148142 10013dec9fcdSqs148142 hxge_status_t 10023dec9fcdSqs148142 hxge_classify_init_sw(p_hxge_t hxgep) 10033dec9fcdSqs148142 { 10043dec9fcdSqs148142 int alloc_size; 10053dec9fcdSqs148142 hxge_classify_t *classify_ptr; 10063dec9fcdSqs148142 10073dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_init_sw")); 10083dec9fcdSqs148142 classify_ptr = &hxgep->classifier; 10093dec9fcdSqs148142 10103dec9fcdSqs148142 if (classify_ptr->state & HXGE_PFC_SW_INIT) { 10113dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, 10123dec9fcdSqs148142 "hxge_classify_init_sw already init")); 10133dec9fcdSqs148142 return (HXGE_OK); 10143dec9fcdSqs148142 } 10153dec9fcdSqs148142 10163dec9fcdSqs148142 /* Init SW structures */ 10173dec9fcdSqs148142 classify_ptr->tcam_size = TCAM_HXGE_TCAM_MAX_ENTRY; 10183dec9fcdSqs148142 10193dec9fcdSqs148142 alloc_size = sizeof (tcam_flow_spec_t) * classify_ptr->tcam_size; 10203dec9fcdSqs148142 classify_ptr->tcam_entries = KMEM_ZALLOC(alloc_size, NULL); 10213dec9fcdSqs148142 bzero(classify_ptr->class_usage, sizeof (classify_ptr->class_usage)); 10223dec9fcdSqs148142 10233dec9fcdSqs148142 /* Start from the beginning of TCAM */ 10243dec9fcdSqs148142 hxgep->classifier.tcam_location = 0; 10253dec9fcdSqs148142 classify_ptr->state |= HXGE_PFC_SW_INIT; 10263dec9fcdSqs148142 10273dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_init_sw")); 10283dec9fcdSqs148142 10293dec9fcdSqs148142 return (HXGE_OK); 10303dec9fcdSqs148142 } 10313dec9fcdSqs148142 10323dec9fcdSqs148142 hxge_status_t 10333dec9fcdSqs148142 hxge_classify_exit_sw(p_hxge_t hxgep) 10343dec9fcdSqs148142 { 10353dec9fcdSqs148142 int alloc_size; 10363dec9fcdSqs148142 hxge_classify_t *classify_ptr; 10373dec9fcdSqs148142 int fsize; 10383dec9fcdSqs148142 10393dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_classify_exit_sw")); 10403dec9fcdSqs148142 classify_ptr = &hxgep->classifier; 10413dec9fcdSqs148142 10423dec9fcdSqs148142 fsize = sizeof (tcam_flow_spec_t); 10433dec9fcdSqs148142 if (classify_ptr->tcam_entries) { 10443dec9fcdSqs148142 alloc_size = fsize * classify_ptr->tcam_size; 10453dec9fcdSqs148142 KMEM_FREE((void *) classify_ptr->tcam_entries, alloc_size); 10463dec9fcdSqs148142 } 10473dec9fcdSqs148142 hxgep->classifier.state = NULL; 10483dec9fcdSqs148142 10493dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_classify_exit_sw")); 10503dec9fcdSqs148142 10513dec9fcdSqs148142 return (HXGE_OK); 10523dec9fcdSqs148142 } 10533dec9fcdSqs148142 10543dec9fcdSqs148142 /*ARGSUSED*/ 10553dec9fcdSqs148142 hxge_status_t 10563dec9fcdSqs148142 hxge_pfc_handle_sys_errors(p_hxge_t hxgep) 10573dec9fcdSqs148142 { 10583dec9fcdSqs148142 return (HXGE_OK); 10593dec9fcdSqs148142 } 10603dec9fcdSqs148142 10613dec9fcdSqs148142 uint_t 10623dec9fcdSqs148142 hxge_pfc_intr(caddr_t arg1, caddr_t arg2) 10633dec9fcdSqs148142 { 10643dec9fcdSqs148142 p_hxge_ldv_t ldvp = (p_hxge_ldv_t)arg1; 10653dec9fcdSqs148142 p_hxge_t hxgep = (p_hxge_t)arg2; 10663dec9fcdSqs148142 hpi_handle_t handle; 10673dec9fcdSqs148142 p_hxge_pfc_stats_t statsp; 10683dec9fcdSqs148142 pfc_int_status_t int_status; 10693dec9fcdSqs148142 pfc_bad_cs_counter_t bad_cs_count; 10703dec9fcdSqs148142 pfc_drop_counter_t drop_count; 10713dec9fcdSqs148142 pfc_drop_log_t drop_log; 10723dec9fcdSqs148142 pfc_vlan_par_err_log_t vlan_par_err_log; 10733dec9fcdSqs148142 pfc_tcam_par_err_log_t tcam_par_err_log; 10743dec9fcdSqs148142 10753dec9fcdSqs148142 if (ldvp == NULL) { 10763dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, INT_CTL, 10773dec9fcdSqs148142 "<== hxge_pfc_intr: hxgep $%p ldvp $%p", hxgep, ldvp)); 10783dec9fcdSqs148142 return (DDI_INTR_UNCLAIMED); 10793dec9fcdSqs148142 } 10803dec9fcdSqs148142 10813dec9fcdSqs148142 if (arg2 == NULL || (void *) ldvp->hxgep != arg2) { 10823dec9fcdSqs148142 hxgep = ldvp->hxgep; 10833dec9fcdSqs148142 } 10843dec9fcdSqs148142 10853dec9fcdSqs148142 handle = hxgep->hpi_reg_handle; 10863dec9fcdSqs148142 statsp = (p_hxge_pfc_stats_t)&hxgep->statsp->pfc_stats; 10873dec9fcdSqs148142 10883dec9fcdSqs148142 /* 10893dec9fcdSqs148142 * need to read the pfc interrupt status register to figure out 10903dec9fcdSqs148142 * what is happenning 10913dec9fcdSqs148142 */ 10923dec9fcdSqs148142 (void) hpi_pfc_get_interrupt_status(handle, &int_status); 10933dec9fcdSqs148142 10943dec9fcdSqs148142 if (int_status.bits.pkt_drop) { 10953dec9fcdSqs148142 statsp->pkt_drop++; 10963dec9fcdSqs148142 if (statsp->pkt_drop == 1) 10973dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, INT_CTL, "PFC pkt_drop")); 10983dec9fcdSqs148142 10993dec9fcdSqs148142 /* Collect each individual drops */ 11003dec9fcdSqs148142 (void) hpi_pfc_get_drop_log(handle, &drop_log); 11013dec9fcdSqs148142 11023dec9fcdSqs148142 if (drop_log.bits.tcp_ctrl_drop) 11033dec9fcdSqs148142 statsp->errlog.tcp_ctrl_drop++; 11043dec9fcdSqs148142 if (drop_log.bits.l2_addr_drop) 11053dec9fcdSqs148142 statsp->errlog.l2_addr_drop++; 11063dec9fcdSqs148142 if (drop_log.bits.class_code_drop) 11073dec9fcdSqs148142 statsp->errlog.class_code_drop++; 11083dec9fcdSqs148142 if (drop_log.bits.tcam_drop) 11093dec9fcdSqs148142 statsp->errlog.tcam_drop++; 11103dec9fcdSqs148142 if (drop_log.bits.vlan_drop) 11113dec9fcdSqs148142 statsp->errlog.vlan_drop++; 11123dec9fcdSqs148142 11133dec9fcdSqs148142 /* Collect the total drops for all kinds */ 11143dec9fcdSqs148142 (void) hpi_pfc_get_drop_counter(handle, &drop_count.value); 11153dec9fcdSqs148142 statsp->drop_count += drop_count.bits.drop_count; 11163dec9fcdSqs148142 } 11173dec9fcdSqs148142 11183dec9fcdSqs148142 if (int_status.bits.tcam_parity_err) { 11193dec9fcdSqs148142 statsp->tcam_parity_err++; 11203dec9fcdSqs148142 11213dec9fcdSqs148142 (void) hpi_pfc_get_tcam_parity_log(handle, &tcam_par_err_log); 11223dec9fcdSqs148142 statsp->errlog.tcam_par_err_log = tcam_par_err_log.bits.addr; 11233dec9fcdSqs148142 11243dec9fcdSqs148142 if (statsp->tcam_parity_err == 1) 11253dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, 11263dec9fcdSqs148142 INT_CTL, " TCAM parity error addr: 0x%x", 11273dec9fcdSqs148142 tcam_par_err_log.bits.addr)); 11283dec9fcdSqs148142 } 11293dec9fcdSqs148142 11303dec9fcdSqs148142 if (int_status.bits.vlan_parity_err) { 11313dec9fcdSqs148142 statsp->vlan_parity_err++; 11323dec9fcdSqs148142 11333dec9fcdSqs148142 (void) hpi_pfc_get_vlan_parity_log(handle, &vlan_par_err_log); 11343dec9fcdSqs148142 statsp->errlog.vlan_par_err_log = vlan_par_err_log.bits.addr; 11353dec9fcdSqs148142 11363dec9fcdSqs148142 if (statsp->vlan_parity_err == 1) 11373dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, INT_CTL, 11383dec9fcdSqs148142 " vlan table parity error addr: 0x%x", 11393dec9fcdSqs148142 vlan_par_err_log.bits.addr)); 11403dec9fcdSqs148142 } 11413dec9fcdSqs148142 11423dec9fcdSqs148142 (void) hpi_pfc_get_bad_csum_counter(handle, &bad_cs_count.value); 11433dec9fcdSqs148142 statsp->bad_cs_count += bad_cs_count.bits.bad_cs_count; 11443dec9fcdSqs148142 11453dec9fcdSqs148142 (void) hpi_pfc_clear_interrupt_status(handle); 11463dec9fcdSqs148142 return (DDI_INTR_CLAIMED); 11473dec9fcdSqs148142 } 11483dec9fcdSqs148142 11493dec9fcdSqs148142 static void 11503dec9fcdSqs148142 hxge_pfc_get_next_mac_addr(uint8_t *st_mac, struct ether_addr *final_mac) 11513dec9fcdSqs148142 { 11523dec9fcdSqs148142 uint64_t mac[ETHERADDRL]; 11533dec9fcdSqs148142 uint64_t mac_addr = 0; 11543dec9fcdSqs148142 int i, j; 11553dec9fcdSqs148142 11563dec9fcdSqs148142 for (i = ETHERADDRL - 1, j = 0; j < ETHERADDRL; i--, j++) { 11573dec9fcdSqs148142 mac[j] = st_mac[i]; 11583dec9fcdSqs148142 mac_addr |= (mac[j] << (j*8)); 11593dec9fcdSqs148142 } 11603dec9fcdSqs148142 11613dec9fcdSqs148142 final_mac->ether_addr_octet[0] = (mac_addr & 0xff0000000000) >> 40; 11623dec9fcdSqs148142 final_mac->ether_addr_octet[1] = (mac_addr & 0xff00000000) >> 32; 11633dec9fcdSqs148142 final_mac->ether_addr_octet[2] = (mac_addr & 0xff000000) >> 24; 11643dec9fcdSqs148142 final_mac->ether_addr_octet[3] = (mac_addr & 0xff0000) >> 16; 11653dec9fcdSqs148142 final_mac->ether_addr_octet[4] = (mac_addr & 0xff00) >> 8; 11663dec9fcdSqs148142 final_mac->ether_addr_octet[5] = (mac_addr & 0xff); 11673dec9fcdSqs148142 } 11683dec9fcdSqs148142 11693dec9fcdSqs148142 hxge_status_t 11703dec9fcdSqs148142 hxge_pfc_mac_addrs_get(p_hxge_t hxgep) 11713dec9fcdSqs148142 { 11723dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 11733dec9fcdSqs148142 hpi_status_t hpi_status = HPI_SUCCESS; 11743dec9fcdSqs148142 hpi_handle_t handle = HXGE_DEV_HPI_HANDLE(hxgep); 11753dec9fcdSqs148142 uint8_t mac_addr[ETHERADDRL]; 11763dec9fcdSqs148142 11773dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_mac_addr_get")); 11783dec9fcdSqs148142 11793dec9fcdSqs148142 hpi_status = hpi_pfc_mac_addr_get_i(handle, mac_addr, 0); 11803dec9fcdSqs148142 if (hpi_status != HPI_SUCCESS) { 11813dec9fcdSqs148142 status = (HXGE_ERROR | hpi_status); 11823dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 11833dec9fcdSqs148142 "hxge_pfc_mac_addr_get: pfc_mac_addr_get_i failed")); 11843dec9fcdSqs148142 goto exit; 11853dec9fcdSqs148142 } 11863dec9fcdSqs148142 11873dec9fcdSqs148142 hxge_pfc_get_next_mac_addr(mac_addr, &hxgep->factaddr); 11883dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, PFC_CTL, "MAC Addr(0): %x:%x:%x:%x:%x:%x\n", 11893dec9fcdSqs148142 mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], 11903dec9fcdSqs148142 mac_addr[4], mac_addr[5])); 11913dec9fcdSqs148142 11923dec9fcdSqs148142 exit: 11933dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, CFG_CTL, "<== hxge_pfc_mac_addr_get, " 11943dec9fcdSqs148142 "status [0x%x]", status)); 11953dec9fcdSqs148142 return (status); 11963dec9fcdSqs148142 } 11973dec9fcdSqs148142 11983dec9fcdSqs148142 /* 11993dec9fcdSqs148142 * Calculate the bit in the multicast address filter 12003dec9fcdSqs148142 * that selects the given * address. 12013dec9fcdSqs148142 * Note: For Hydra, the last 8-bits are used. 12023dec9fcdSqs148142 */ 12033dec9fcdSqs148142 static uint32_t 12043dec9fcdSqs148142 crc32_mchash(p_ether_addr_t addr) 12053dec9fcdSqs148142 { 12063dec9fcdSqs148142 uint8_t *cp; 12073dec9fcdSqs148142 uint32_t crc; 12083dec9fcdSqs148142 uint32_t c; 12093dec9fcdSqs148142 int byte; 12103dec9fcdSqs148142 int bit; 12113dec9fcdSqs148142 12123dec9fcdSqs148142 cp = (uint8_t *)addr; 12133dec9fcdSqs148142 crc = (uint32_t)0xffffffff; 12143dec9fcdSqs148142 for (byte = 0; byte < ETHERADDRL; byte++) { 12153dec9fcdSqs148142 /* Hydra calculates the hash backwardly */ 12163dec9fcdSqs148142 c = (uint32_t)cp[ETHERADDRL - 1 - byte]; 12173dec9fcdSqs148142 for (bit = 0; bit < 8; bit++) { 12183dec9fcdSqs148142 if ((c & 0x1) ^ (crc & 0x1)) 12193dec9fcdSqs148142 crc = (crc >> 1)^0xedb88320; 12203dec9fcdSqs148142 else 12213dec9fcdSqs148142 crc = (crc >> 1); 12223dec9fcdSqs148142 c >>= 1; 12233dec9fcdSqs148142 } 12243dec9fcdSqs148142 } 12253dec9fcdSqs148142 return ((~crc) >> (32 - HASH_BITS)); 12263dec9fcdSqs148142 } 12273dec9fcdSqs148142 12283dec9fcdSqs148142 static hxge_status_t 12293dec9fcdSqs148142 hxge_pfc_load_hash_table(p_hxge_t hxgep) 12303dec9fcdSqs148142 { 12313dec9fcdSqs148142 uint32_t i; 12323dec9fcdSqs148142 uint16_t hashtab_e; 12333dec9fcdSqs148142 p_hash_filter_t hash_filter; 12343dec9fcdSqs148142 hpi_handle_t handle; 12353dec9fcdSqs148142 12363dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "==> hxge_pfc_load_hash_table\n")); 12373dec9fcdSqs148142 handle = hxgep->hpi_reg_handle; 12383dec9fcdSqs148142 12393dec9fcdSqs148142 /* 12403dec9fcdSqs148142 * Load the multicast hash filter bits. 12413dec9fcdSqs148142 */ 12423dec9fcdSqs148142 hash_filter = hxgep->hash_filter; 12433dec9fcdSqs148142 for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 12443dec9fcdSqs148142 if (hash_filter != NULL) { 12453dec9fcdSqs148142 hashtab_e = (uint16_t)hash_filter->hash_filter_regs[i]; 12463dec9fcdSqs148142 } else { 12473dec9fcdSqs148142 hashtab_e = 0; 12483dec9fcdSqs148142 } 12493dec9fcdSqs148142 12503dec9fcdSqs148142 if (hpi_pfc_set_multicast_hash_table(handle, i, 12513dec9fcdSqs148142 hashtab_e) != HPI_SUCCESS) 12523dec9fcdSqs148142 return (HXGE_ERROR); 12533dec9fcdSqs148142 } 12543dec9fcdSqs148142 12553dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, PFC_CTL, "<== hxge_pfc_load_hash_table\n")); 12563dec9fcdSqs148142 12573dec9fcdSqs148142 return (HXGE_OK); 12583dec9fcdSqs148142 } 1259