| /* |
| * CDDL HEADER START |
| * |
| * The contents of this file are subject to the terms of the |
| * Common Development and Distribution License (the "License"). |
| * You may not use this file except in compliance with the License. |
| * |
| * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
| * or http://www.opensolaris.org/os/licensing. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * |
| * When distributing Covered Code, include this CDDL HEADER in each |
| * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
| * If applicable, add the following below this CDDL HEADER, with the |
| * fields enclosed by brackets "[]" replaced with your own identifying |
| * information: Portions Copyright [yyyy] [name of copyright owner] |
| * |
| * CDDL HEADER END |
| */ |
| /* |
| * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. |
| */ |
| |
| #include <sys/nxge/nxge_impl.h> |
| #include <sys/nxge/nxge_mac.h> |
| #include <sys/nxge/nxge_hio.h> |
| |
| /* |
| * Local defines for FWARC 2006/556 |
| */ |
| #define NXGE_NIU_TDMA_PROP_LEN 2 |
| #define NXGE_NIU_RDMA_PROP_LEN 2 |
| #define NXGE_NIU_0_INTR_PROP_LEN 19 |
| #define NXGE_NIU_1_INTR_PROP_LEN 17 |
| |
| /* |
| * Local functions. |
| */ |
| static void nxge_get_niu_property(dev_info_t *, niu_type_t *); |
| static nxge_status_t nxge_get_mac_addr_properties(p_nxge_t); |
| static nxge_status_t nxge_use_cfg_n2niu_properties(p_nxge_t); |
| static void nxge_use_cfg_neptune_properties(p_nxge_t); |
| static void nxge_use_cfg_dma_config(p_nxge_t); |
| static void nxge_use_cfg_vlan_class_config(p_nxge_t); |
| static void nxge_use_cfg_mac_class_config(p_nxge_t); |
| static void nxge_use_cfg_class_config(p_nxge_t); |
| static void nxge_use_cfg_link_cfg(p_nxge_t); |
| static void nxge_set_hw_dma_config(p_nxge_t); |
| static void nxge_set_hw_vlan_class_config(p_nxge_t); |
| static void nxge_set_hw_mac_class_config(p_nxge_t); |
| static void nxge_set_hw_class_config(p_nxge_t); |
| static nxge_status_t nxge_use_default_dma_config_n2(p_nxge_t); |
| static void nxge_ldgv_setup(p_nxge_ldg_t *, p_nxge_ldv_t *, uint8_t, |
| uint8_t, int *); |
| static void nxge_init_mmac(p_nxge_t, boolean_t); |
| static void nxge_set_rdc_intr_property(p_nxge_t); |
| |
| uint32_t nxge_use_hw_property = 1; |
| uint32_t nxge_groups_per_port = 2; |
| |
| extern uint32_t nxge_use_partition; |
| extern uint32_t nxge_dma_obp_props_only; |
| |
| extern uint_t nxge_rx_intr(void *, void *); |
| extern uint_t nxge_tx_intr(void *, void *); |
| extern uint_t nxge_mif_intr(void *, void *); |
| extern uint_t nxge_mac_intr(void *, void *); |
| extern uint_t nxge_syserr_intr(void *, void *); |
| extern void *nxge_list; |
| |
| #define NXGE_SHARED_REG_SW_SIM |
| |
| #ifdef NXGE_SHARED_REG_SW_SIM |
| uint64_t global_dev_ctrl = 0; |
| #endif |
| |
| #define MAX_SIBLINGS NXGE_MAX_PORTS |
| |
| extern uint32_t nxge_rbr_size; |
| extern uint32_t nxge_rcr_size; |
| extern uint32_t nxge_tx_ring_size; |
| extern uint32_t nxge_rbr_spare_size; |
| |
| extern npi_status_t npi_mac_altaddr_disable(npi_handle_t, uint8_t, uint8_t); |
| |
| static uint8_t p2_tx_fair[2] = {12, 12}; |
| static uint8_t p2_tx_equal[2] = {12, 12}; |
| static uint8_t p4_tx_fair[4] = {6, 6, 6, 6}; |
| static uint8_t p4_tx_equal[4] = {6, 6, 6, 6}; |
| static uint8_t p2_rx_fair[2] = {8, 8}; |
| static uint8_t p2_rx_equal[2] = {8, 8}; |
| static uint8_t p4_rx_fair[4] = {4, 4, 4, 4}; |
| static uint8_t p4_rx_equal[4] = {4, 4, 4, 4}; |
| |
| static uint8_t p2_rdcgrp_fair[2] = {4, 4}; |
| static uint8_t p2_rdcgrp_equal[2] = {4, 4}; |
| static uint8_t p4_rdcgrp_fair[4] = {2, 2, 1, 1}; |
| static uint8_t p4_rdcgrp_equal[4] = {2, 2, 2, 2}; |
| static uint8_t p2_rdcgrp_cls[2] = {1, 1}; |
| static uint8_t p4_rdcgrp_cls[4] = {1, 1, 1, 1}; |
| |
| static uint8_t rx_4_1G[4] = {4, 4, 4, 4}; |
| static uint8_t rx_2_10G[2] = {8, 8}; |
| static uint8_t rx_2_10G_2_1G[4] = {6, 6, 2, 2}; |
| static uint8_t rx_1_10G_3_1G[4] = {10, 2, 2, 2}; |
| static uint8_t rx_1_1G_1_10G_2_1G[4] = {2, 10, 2, 2}; |
| |
| static uint8_t tx_4_1G[4] = {6, 6, 6, 6}; |
| static uint8_t tx_2_10G[2] = {12, 12}; |
| static uint8_t tx_2_10G_2_1G[4] = {10, 10, 2, 2}; |
| static uint8_t tx_1_10G_3_1G[4] = {12, 4, 4, 4}; |
| static uint8_t tx_1_1G_1_10G_2_1G[4] = {4, 12, 4, 4}; |
| |
| typedef enum { |
| DEFAULT = 0, |
| EQUAL, |
| FAIR, |
| CUSTOM, |
| CLASSIFY, |
| L2_CLASSIFY, |
| L3_DISTRIBUTE, |
| L3_CLASSIFY, |
| L3_TCAM, |
| CONFIG_TOKEN_NONE |
| } config_token_t; |
| |
| static char *token_names[] = { |
| "default", |
| "equal", |
| "fair", |
| "custom", |
| "classify", |
| "l2_classify", |
| "l3_distribute", |
| "l3_classify", |
| "l3_tcam", |
| "none", |
| }; |
| |
| void nxge_virint_regs_dump(p_nxge_t nxgep); |
| |
| void |
| nxge_virint_regs_dump(p_nxge_t nxgep) |
| { |
| npi_handle_t handle; |
| |
| NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_virint_regs_dump")); |
| handle = NXGE_DEV_NPI_HANDLE(nxgep); |
| (void) npi_vir_dump_pio_fzc_regs_one(handle); |
| (void) npi_vir_dump_ldgnum(handle); |
| (void) npi_vir_dump_ldsv(handle); |
| (void) npi_vir_dump_imask0(handle); |
| (void) npi_vir_dump_sid(handle); |
| (void) npi_mac_dump_regs(handle, nxgep->function_num); |
| (void) npi_ipp_dump_regs(handle, nxgep->function_num); |
| (void) npi_fflp_dump_regs(handle); |
| NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_virint_regs_dump")); |
| } |
| |
| /* |
| * For now: we hard coded the DMA configurations. |
| * and assume for one partition only. |
| * |
| * OBP. Then OBP will pass this partition's |
| * Neptune configurations to fcode to create |
| * properties for them. |
| * |
| * Since Neptune(PCI-E) and NIU (Niagara-2) has |
| * different bus interfaces, the driver needs |
| * to know which bus it is connected to. |
| * Ravinder suggested: create a device property. |
| * In partitioning environment, we cannot |
| * use .conf file (need to check). If conf changes, |
| * need to reboot the system. |
| * The following function assumes that we will |
| * retrieve its properties from a virtualized nexus driver. |
| */ |
| |
| nxge_status_t |
| nxge_cntlops(dev_info_t *dip, nxge_ctl_enum_t ctlop, void *arg, void *result) |
| { |
| nxge_status_t status = NXGE_OK; |
| int instance; |
| p_nxge_t nxgep; |
| |
| #ifndef NXGE_SHARED_REG_SW_SIM |
| npi_handle_t handle; |
| uint16_t sr16, cr16; |
| #endif |
| instance = ddi_get_instance(dip); |
| NXGE_DEBUG_MSG((NULL, VIR_CTL, "Instance %d ", instance)); |
| |
| if (nxge_list == NULL) { |
| NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, |
| "nxge_cntlops: nxge_list null")); |
| return (NXGE_ERROR); |
| } |
| nxgep = (p_nxge_t)ddi_get_soft_state(nxge_list, instance); |
| if (nxgep == NULL) { |
| NXGE_ERROR_MSG((NULL, NXGE_ERR_CTL, |
| "nxge_cntlops: nxgep null")); |
| return (NXGE_ERROR); |
| } |
| #ifndef NXGE_SHARED_REG_SW_SIM |
| handle = nxgep->npi_reg_handle; |
| #endif |
| switch (ctlop) { |
| case NXGE_CTLOPS_NIUTYPE: |
| nxge_get_niu_property(dip, (niu_type_t *)result); |
| return (status); |
| |
| case NXGE_CTLOPS_GET_SHARED_REG: |
| #ifdef NXGE_SHARED_REG_SW_SIM |
| *(uint64_t *)result = global_dev_ctrl; |
| return (0); |
| #else |
| status = npi_dev_func_sr_sr_get(handle, &sr16); |
| *(uint16_t *)result = sr16; |
| NXGE_DEBUG_MSG((NULL, VIR_CTL, |
| "nxge_cntlops: NXGE_CTLOPS_GET_SHARED_REG")); |
| return (0); |
| #endif |
| |
| case NXGE_CTLOPS_SET_SHARED_REG_LOCK: |
| #ifdef NXGE_SHARED_REG_SW_SIM |
| global_dev_ctrl = *(uint64_t *)arg; |
| return (0); |
| #else |
| status = NPI_FAILURE; |
| while (status != NPI_SUCCESS) |
| status = npi_dev_func_sr_lock_enter(handle); |
| |
| sr16 = *(uint16_t *)arg; |
| status = npi_dev_func_sr_sr_set_only(handle, &sr16); |
| status = npi_dev_func_sr_lock_free(handle); |
| NXGE_DEBUG_MSG((NULL, VIR_CTL, |
| "nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG")); |
| return (0); |
| #endif |
| |
| case NXGE_CTLOPS_UPDATE_SHARED_REG: |
| #ifdef NXGE_SHARED_REG_SW_SIM |
| global_dev_ctrl |= *(uint64_t *)arg; |
| return (0); |
| #else |
| status = NPI_FAILURE; |
| while (status != NPI_SUCCESS) |
| status = npi_dev_func_sr_lock_enter(handle); |
| status = npi_dev_func_sr_sr_get(handle, &sr16); |
| sr16 |= *(uint16_t *)arg; |
| status = npi_dev_func_sr_sr_set_only(handle, &sr16); |
| status = npi_dev_func_sr_lock_free(handle); |
| NXGE_DEBUG_MSG((NULL, VIR_CTL, |
| "nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG")); |
| return (0); |
| #endif |
| |
| case NXGE_CTLOPS_CLEAR_BIT_SHARED_REG_UL: |
| #ifdef NXGE_SHARED_REG_SW_SIM |
| global_dev_ctrl |= *(uint64_t *)arg; |
| return (0); |
| #else |
| status = npi_dev_func_sr_sr_get(handle, &sr16); |
| cr16 = *(uint16_t *)arg; |
| sr16 &= ~cr16; |
| status = npi_dev_func_sr_sr_set_only(handle, &sr16); |
| NXGE_DEBUG_MSG((NULL, VIR_CTL, |
| "nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG")); |
| return (0); |
| #endif |
| |
| case NXGE_CTLOPS_CLEAR_BIT_SHARED_REG: |
| #ifdef NXGE_SHARED_REG_SW_SIM |
| global_dev_ctrl |= *(uint64_t *)arg; |
| return (0); |
| #else |
| status = NPI_FAILURE; |
| while (status != NPI_SUCCESS) |
| status = npi_dev_func_sr_lock_enter(handle); |
| status = npi_dev_func_sr_sr_get(handle, &sr16); |
| cr16 = *(uint16_t *)arg; |
| sr16 &= ~cr16; |
| status = npi_dev_func_sr_sr_set_only(handle, &sr16); |
| status = npi_dev_func_sr_lock_free(handle); |
| NXGE_DEBUG_MSG((NULL, VIR_CTL, |
| "nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG")); |
| return (0); |
| #endif |
| |
| case NXGE_CTLOPS_GET_LOCK_BLOCK: |
| #ifdef NXGE_SHARED_REG_SW_SIM |
| global_dev_ctrl |= *(uint64_t *)arg; |
| return (0); |
| #else |
| status = NPI_FAILURE; |
| while (status != NPI_SUCCESS) |
| status = npi_dev_func_sr_lock_enter(handle); |
| NXGE_DEBUG_MSG((NULL, VIR_CTL, |
| "nxge_cntlops: NXGE_CTLOPS_GET_LOCK_BLOCK")); |
| return (0); |
| #endif |
| case NXGE_CTLOPS_GET_LOCK_TRY: |
| #ifdef NXGE_SHARED_REG_SW_SIM |
| global_dev_ctrl |= *(uint64_t *)arg; |
| return (0); |
| #else |
| status = npi_dev_func_sr_lock_enter(handle); |
| NXGE_DEBUG_MSG((NULL, VIR_CTL, |
| "nxge_cntlops: NXGE_CTLOPS_GET_LOCK_TRY")); |
| if (status == NPI_SUCCESS) |
| return (NXGE_OK); |
| else |
| return (NXGE_ERROR); |
| #endif |
| case NXGE_CTLOPS_FREE_LOCK: |
| #ifdef NXGE_SHARED_REG_SW_SIM |
| global_dev_ctrl |= *(uint64_t *)arg; |
| return (0); |
| #else |
| status = npi_dev_func_sr_lock_free(handle); |
| NXGE_DEBUG_MSG((NULL, VIR_CTL, |
| "nxge_cntlops: NXGE_CTLOPS_GET_LOCK_FREE")); |
| if (status == NPI_SUCCESS) |
| return (NXGE_OK); |
| else |
| return (NXGE_ERROR); |
| #endif |
| |
| default: |
| status = NXGE_ERROR; |
| } |
| |
| return (status); |
| } |
| |
| void |
| nxge_common_lock_get(p_nxge_t nxgep) |
| { |
| uint32_t status = NPI_FAILURE; |
| npi_handle_t handle; |
| |
| #if defined(NXGE_SHARE_REG_SW_SIM) |
| return; |
| #endif |
| handle = nxgep->npi_reg_handle; |
| while (status != NPI_SUCCESS) |
| status = npi_dev_func_sr_lock_enter(handle); |
| } |
| |
| void |
| nxge_common_lock_free(p_nxge_t nxgep) |
| { |
| npi_handle_t handle; |
| |
| #if defined(NXGE_SHARE_REG_SW_SIM) |
| return; |
| #endif |
| handle = nxgep->npi_reg_handle; |
| (void) npi_dev_func_sr_lock_free(handle); |
| } |
| |
| |
| static void |
| nxge_get_niu_property(dev_info_t *dip, niu_type_t *niu_type) |
| { |
| uchar_t *prop_val; |
| uint_t prop_len; |
| |
| *niu_type = NIU_TYPE_NONE; |
| if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, 0, |
| "niu-type", (uchar_t **)&prop_val, |
| &prop_len) == DDI_PROP_SUCCESS) { |
| if (strncmp("niu", (caddr_t)prop_val, (size_t)prop_len) == 0) { |
| *niu_type = N2_NIU; |
| } |
| ddi_prop_free(prop_val); |
| } |
| } |
| |
| static config_token_t |
| nxge_get_config_token(char *prop) |
| { |
| config_token_t token = DEFAULT; |
| |
| while (token < CONFIG_TOKEN_NONE) { |
| if (strncmp(prop, token_names[token], 4) == 0) |
| break; |
| token++; |
| } |
| return (token); |
| } |
| |
| /* per port */ |
| |
| static nxge_status_t |
| nxge_update_rxdma_grp_properties(p_nxge_t nxgep, config_token_t token, |
| dev_info_t *s_dip[]) |
| { |
| nxge_status_t status = NXGE_OK; |
| int ddi_status; |
| int num_ports = nxgep->nports; |
| int port, bits, j; |
| uint8_t start_grp = 0, num_grps = 0; |
| p_nxge_param_t param_arr; |
| uint32_t grp_bitmap[MAX_SIBLINGS]; |
| int custom_start_grp[MAX_SIBLINGS]; |
| int custom_num_grp[MAX_SIBLINGS]; |
| uint8_t bad_config = B_FALSE; |
| char *start_prop, *num_prop, *cfg_prop; |
| |
| start_grp = 0; |
| param_arr = nxgep->param_arr; |
| start_prop = param_arr[param_rdc_grps_start].fcode_name; |
| num_prop = param_arr[param_rx_rdc_grps].fcode_name; |
| |
| switch (token) { |
| case FAIR: |
| cfg_prop = "fair"; |
| for (port = 0; port < num_ports; port++) { |
| custom_num_grp[port] = |
| (num_ports == 4) ? |
| p4_rdcgrp_fair[port] : |
| p2_rdcgrp_fair[port]; |
| custom_start_grp[port] = start_grp; |
| start_grp += custom_num_grp[port]; |
| } |
| break; |
| |
| case EQUAL: |
| cfg_prop = "equal"; |
| for (port = 0; port < num_ports; port++) { |
| custom_num_grp[port] = |
| (num_ports == 4) ? |
| p4_rdcgrp_equal[port] : |
| p2_rdcgrp_equal[port]; |
| custom_start_grp[port] = start_grp; |
| start_grp += custom_num_grp[port]; |
| } |
| break; |
| |
| |
| case CLASSIFY: |
| cfg_prop = "classify"; |
| for (port = 0; port < num_ports; port++) { |
| custom_num_grp[port] = (num_ports == 4) ? |
| p4_rdcgrp_cls[port] : p2_rdcgrp_cls[port]; |
| custom_start_grp[port] = start_grp; |
| start_grp += custom_num_grp[port]; |
| } |
| break; |
| |
| case CUSTOM: |
| cfg_prop = "custom"; |
| /* See if it is good config */ |
| num_grps = 0; |
| for (port = 0; port < num_ports; port++) { |
| custom_start_grp[port] = |
| ddi_prop_get_int(DDI_DEV_T_NONE, s_dip[port], |
| DDI_PROP_DONTPASS, start_prop, -1); |
| if ((custom_start_grp[port] == -1) || |
| (custom_start_grp[port] >= |
| NXGE_MAX_RDC_GRPS)) { |
| bad_config = B_TRUE; |
| break; |
| } |
| custom_num_grp[port] = ddi_prop_get_int( |
| DDI_DEV_T_NONE, |
| s_dip[port], |
| DDI_PROP_DONTPASS, |
| num_prop, -1); |
| |
| if ((custom_num_grp[port] == -1) || |
| (custom_num_grp[port] > |
| NXGE_MAX_RDC_GRPS) || |
| ((custom_num_grp[port] + |
| custom_start_grp[port]) >= |
| NXGE_MAX_RDC_GRPS)) { |
| bad_config = B_TRUE; |
| break; |
| } |
| num_grps += custom_num_grp[port]; |
| if (num_grps > NXGE_MAX_RDC_GRPS) { |
| bad_config = B_TRUE; |
| break; |
| } |
| grp_bitmap[port] = 0; |
| for (bits = 0; |
| bits < custom_num_grp[port]; |
| bits++) { |
| grp_bitmap[port] |= |
| (1 << (bits + custom_start_grp[port])); |
| } |
| |
| } |
| |
| if (bad_config == B_FALSE) { |
| /* check for overlap */ |
| for (port = 0; port < num_ports - 1; port++) { |
| for (j = port + 1; j < num_ports; j++) { |
| if (grp_bitmap[port] & |
| grp_bitmap[j]) { |
| bad_config = B_TRUE; |
| break; |
| } |
| } |
| if (bad_config == B_TRUE) |
| break; |
| } |
| } |
| if (bad_config == B_TRUE) { |
| /* use default config */ |
| for (port = 0; port < num_ports; port++) { |
| custom_num_grp[port] = |
| (num_ports == 4) ? |
| p4_rx_fair[port] : p2_rx_fair[port]; |
| custom_start_grp[port] = start_grp; |
| start_grp += custom_num_grp[port]; |
| } |
| } |
| break; |
| |
| default: |
| /* use default config */ |
| cfg_prop = "fair"; |
| for (port = 0; port < num_ports; port++) { |
| custom_num_grp[port] = (num_ports == 4) ? |
| p4_rx_fair[port] : p2_rx_fair[port]; |
| custom_start_grp[port] = start_grp; |
| start_grp += custom_num_grp[port]; |
| } |
| break; |
| } |
| |
| /* Now Update the rx properties */ |
| for (port = 0; port < num_ports; port++) { |
| ddi_status = ddi_prop_update_string(DDI_DEV_T_NONE, s_dip[port], |
| "rxdma-grp-cfg", cfg_prop); |
| if (ddi_status != DDI_PROP_SUCCESS) { |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| " property %s not updating", |
| cfg_prop)); |
| status |= NXGE_DDI_FAILED; |
| } |
| ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port], |
| num_prop, custom_num_grp[port]); |
| |
| if (ddi_status != DDI_PROP_SUCCESS) { |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| " property %s not updating", |
| num_prop)); |
| status |= NXGE_DDI_FAILED; |
| } |
| ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port], |
| start_prop, custom_start_grp[port]); |
| |
| if (ddi_status != DDI_PROP_SUCCESS) { |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| " property %s not updating", |
| start_prop)); |
| status |= NXGE_DDI_FAILED; |
| } |
| } |
| if (status & NXGE_DDI_FAILED) |
| status |= NXGE_ERROR; |
| |
| return (status); |
| } |
| |
| static nxge_status_t |
| nxge_update_rxdma_properties(p_nxge_t nxgep, config_token_t token, |
| dev_info_t *s_dip[]) |
| { |
| nxge_status_t status = NXGE_OK; |
| int ddi_status; |
| int num_ports = nxgep->nports; |
| int port, bits, j; |
| uint8_t start_rdc = 0, num_rdc = 0; |
| p_nxge_param_t param_arr; |
| uint32_t rdc_bitmap[MAX_SIBLINGS]; |
| int custom_start_rdc[MAX_SIBLINGS]; |
| int custom_num_rdc[MAX_SIBLINGS]; |
| uint8_t bad_config = B_FALSE; |
| int *prop_val; |
| uint_t prop_len; |
| char *start_rdc_prop, *num_rdc_prop, *cfg_prop; |
| |
| start_rdc = 0; |
| param_arr = nxgep->param_arr; |
| start_rdc_prop = param_arr[param_rxdma_channels_begin].fcode_name; |
| num_rdc_prop = param_arr[param_rxdma_channels].fcode_name; |
| |
| switch (token) { |
| case FAIR: |
| cfg_prop = "fair"; |
| for (port = 0; port < num_ports; port++) { |
| custom_num_rdc[port] = (num_ports == 4) ? |
| p4_rx_fair[port] : p2_rx_fair[port]; |
| custom_start_rdc[port] = start_rdc; |
| start_rdc += custom_num_rdc[port]; |
| } |
| break; |
| |
| case EQUAL: |
| cfg_prop = "equal"; |
| for (port = 0; port < num_ports; port++) { |
| custom_num_rdc[port] = (num_ports == 4) ? |
| p4_rx_equal[port] : |
| p2_rx_equal[port]; |
| custom_start_rdc[port] = start_rdc; |
| start_rdc += custom_num_rdc[port]; |
| } |
| break; |
| |
| case CUSTOM: |
| cfg_prop = "custom"; |
| /* See if it is good config */ |
| num_rdc = 0; |
| for (port = 0; port < num_ports; port++) { |
| ddi_status = ddi_prop_lookup_int_array( |
| DDI_DEV_T_ANY, |
| s_dip[port], 0, |
| start_rdc_prop, |
| &prop_val, |
| &prop_len); |
| if (ddi_status == DDI_SUCCESS) |
| custom_start_rdc[port] = *prop_val; |
| else { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " %s custom start port %d" |
| " read failed ", |
| " rxdma-cfg", port)); |
| bad_config = B_TRUE; |
| status |= NXGE_DDI_FAILED; |
| } |
| if ((custom_start_rdc[port] == -1) || |
| (custom_start_rdc[port] >= |
| NXGE_MAX_RDCS)) { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " %s custom start %d" |
| " out of range %x ", |
| " rxdma-cfg", |
| port, |
| custom_start_rdc[port])); |
| bad_config = B_TRUE; |
| break; |
| } |
| ddi_status = ddi_prop_lookup_int_array( |
| DDI_DEV_T_ANY, |
| s_dip[port], |
| 0, |
| num_rdc_prop, |
| &prop_val, |
| &prop_len); |
| |
| if (ddi_status == DDI_SUCCESS) |
| custom_num_rdc[port] = *prop_val; |
| else { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " %s custom num port %d" |
| " read failed ", |
| "rxdma-cfg", port)); |
| bad_config = B_TRUE; |
| status |= NXGE_DDI_FAILED; |
| } |
| |
| if ((custom_num_rdc[port] == -1) || |
| (custom_num_rdc[port] > |
| NXGE_MAX_RDCS) || |
| ((custom_num_rdc[port] + |
| custom_start_rdc[port]) > |
| NXGE_MAX_RDCS)) { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " %s custom num %d" |
| " out of range %x ", |
| " rxdma-cfg", |
| port, custom_num_rdc[port])); |
| bad_config = B_TRUE; |
| break; |
| } |
| num_rdc += custom_num_rdc[port]; |
| if (num_rdc > NXGE_MAX_RDCS) { |
| bad_config = B_TRUE; |
| break; |
| } |
| rdc_bitmap[port] = 0; |
| for (bits = 0; |
| bits < custom_num_rdc[port]; bits++) { |
| rdc_bitmap[port] |= |
| (1 << (bits + custom_start_rdc[port])); |
| } |
| } |
| |
| if (bad_config == B_FALSE) { |
| /* check for overlap */ |
| for (port = 0; port < num_ports - 1; port++) { |
| for (j = port + 1; j < num_ports; j++) { |
| if (rdc_bitmap[port] & |
| rdc_bitmap[j]) { |
| NXGE_DEBUG_MSG((nxgep, |
| CFG_CTL, |
| " rxdma-cfg" |
| " property custom" |
| " bit overlap" |
| " %d %d ", |
| port, j)); |
| bad_config = B_TRUE; |
| break; |
| } |
| } |
| if (bad_config == B_TRUE) |
| break; |
| } |
| } |
| if (bad_config == B_TRUE) { |
| /* use default config */ |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " rxdma-cfg property:" |
| " bad custom config:" |
| " use default")); |
| for (port = 0; port < num_ports; port++) { |
| custom_num_rdc[port] = |
| (num_ports == 4) ? |
| p4_rx_fair[port] : |
| p2_rx_fair[port]; |
| custom_start_rdc[port] = start_rdc; |
| start_rdc += custom_num_rdc[port]; |
| } |
| } |
| break; |
| |
| default: |
| /* use default config */ |
| cfg_prop = "fair"; |
| for (port = 0; port < num_ports; port++) { |
| custom_num_rdc[port] = (num_ports == 4) ? |
| p4_rx_fair[port] : p2_rx_fair[port]; |
| custom_start_rdc[port] = start_rdc; |
| start_rdc += custom_num_rdc[port]; |
| } |
| break; |
| } |
| |
| /* Now Update the rx properties */ |
| for (port = 0; port < num_ports; port++) { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " update property rxdma-cfg with %s ", cfg_prop)); |
| ddi_status = ddi_prop_update_string(DDI_DEV_T_NONE, s_dip[port], |
| "rxdma-cfg", cfg_prop); |
| if (ddi_status != DDI_PROP_SUCCESS) { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " property rxdma-cfg is not updating to %s", |
| cfg_prop)); |
| status |= NXGE_DDI_FAILED; |
| } |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, " update property %s with %d ", |
| num_rdc_prop, custom_num_rdc[port])); |
| |
| ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port], |
| num_rdc_prop, custom_num_rdc[port]); |
| |
| if (ddi_status != DDI_PROP_SUCCESS) { |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| " property %s not updating with %d", |
| num_rdc_prop, custom_num_rdc[port])); |
| status |= NXGE_DDI_FAILED; |
| } |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, " update property %s with %d ", |
| start_rdc_prop, custom_start_rdc[port])); |
| ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port], |
| start_rdc_prop, custom_start_rdc[port]); |
| |
| if (ddi_status != DDI_PROP_SUCCESS) { |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| " property %s not updating with %d ", |
| start_rdc_prop, custom_start_rdc[port])); |
| status |= NXGE_DDI_FAILED; |
| } |
| } |
| if (status & NXGE_DDI_FAILED) |
| status |= NXGE_ERROR; |
| return (status); |
| } |
| |
| static nxge_status_t |
| nxge_update_txdma_properties(p_nxge_t nxgep, config_token_t token, |
| dev_info_t *s_dip[]) |
| { |
| nxge_status_t status = NXGE_OK; |
| int ddi_status = DDI_SUCCESS; |
| int num_ports = nxgep->nports; |
| int port, bits, j; |
| uint8_t start_tdc, num_tdc = 0; |
| p_nxge_param_t param_arr; |
| uint32_t tdc_bitmap[MAX_SIBLINGS]; |
| int custom_start_tdc[MAX_SIBLINGS]; |
| int custom_num_tdc[MAX_SIBLINGS]; |
| uint8_t bad_config = B_FALSE; |
| int *prop_val; |
| uint_t prop_len; |
| char *start_tdc_prop, *num_tdc_prop, *cfg_prop; |
| |
| start_tdc = 0; |
| param_arr = nxgep->param_arr; |
| start_tdc_prop = param_arr[param_txdma_channels_begin].fcode_name; |
| num_tdc_prop = param_arr[param_txdma_channels].fcode_name; |
| |
| switch (token) { |
| case FAIR: |
| cfg_prop = "fair"; |
| for (port = 0; port < num_ports; port++) { |
| custom_num_tdc[port] = (num_ports == 4) ? |
| p4_tx_fair[port] : p2_tx_fair[port]; |
| custom_start_tdc[port] = start_tdc; |
| start_tdc += custom_num_tdc[port]; |
| } |
| break; |
| |
| case EQUAL: |
| cfg_prop = "equal"; |
| for (port = 0; port < num_ports; port++) { |
| custom_num_tdc[port] = (num_ports == 4) ? |
| p4_tx_equal[port] : p2_tx_equal[port]; |
| custom_start_tdc[port] = start_tdc; |
| start_tdc += custom_num_tdc[port]; |
| } |
| break; |
| |
| case CUSTOM: |
| cfg_prop = "custom"; |
| /* See if it is good config */ |
| num_tdc = 0; |
| for (port = 0; port < num_ports; port++) { |
| ddi_status = ddi_prop_lookup_int_array( |
| DDI_DEV_T_ANY, s_dip[port], 0, start_tdc_prop, |
| &prop_val, &prop_len); |
| if (ddi_status == DDI_SUCCESS) |
| custom_start_tdc[port] = *prop_val; |
| else { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " %s custom start port %d" |
| " read failed ", " txdma-cfg", port)); |
| bad_config = B_TRUE; |
| status |= NXGE_DDI_FAILED; |
| } |
| |
| if ((custom_start_tdc[port] == -1) || |
| (custom_start_tdc[port] >= |
| NXGE_MAX_RDCS)) { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " %s custom start %d" |
| " out of range %x ", " txdma-cfg", |
| port, custom_start_tdc[port])); |
| bad_config = B_TRUE; |
| break; |
| } |
| |
| ddi_status = ddi_prop_lookup_int_array( |
| DDI_DEV_T_ANY, s_dip[port], 0, num_tdc_prop, |
| &prop_val, &prop_len); |
| if (ddi_status == DDI_SUCCESS) |
| custom_num_tdc[port] = *prop_val; |
| else { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " %s custom num port %d" |
| " read failed ", " txdma-cfg", port)); |
| bad_config = B_TRUE; |
| status |= NXGE_DDI_FAILED; |
| } |
| |
| if ((custom_num_tdc[port] == -1) || |
| (custom_num_tdc[port] > |
| NXGE_MAX_TDCS) || |
| ((custom_num_tdc[port] + |
| custom_start_tdc[port]) > |
| NXGE_MAX_TDCS)) { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " %s custom num %d" |
| " out of range %x ", " rxdma-cfg", |
| port, custom_num_tdc[port])); |
| bad_config = B_TRUE; |
| break; |
| } |
| num_tdc += custom_num_tdc[port]; |
| if (num_tdc > NXGE_MAX_TDCS) { |
| bad_config = B_TRUE; |
| break; |
| } |
| tdc_bitmap[port] = 0; |
| for (bits = 0; |
| bits < custom_num_tdc[port]; bits++) { |
| tdc_bitmap[port] |= |
| (1 << |
| (bits + custom_start_tdc[port])); |
| } |
| |
| } |
| |
| if (bad_config == B_FALSE) { |
| /* check for overlap */ |
| for (port = 0; port < num_ports - 1; port++) { |
| for (j = port + 1; j < num_ports; j++) { |
| if (tdc_bitmap[port] & |
| tdc_bitmap[j]) { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " rxdma-cfg" |
| " property custom" |
| " bit overlap" |
| " %d %d ", |
| port, j)); |
| bad_config = B_TRUE; |
| break; |
| } |
| } |
| if (bad_config == B_TRUE) |
| break; |
| } |
| } |
| if (bad_config == B_TRUE) { |
| /* use default config */ |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " txdma-cfg property:" |
| " bad custom config:" " use default")); |
| |
| for (port = 0; port < num_ports; port++) { |
| custom_num_tdc[port] = (num_ports == 4) ? |
| p4_tx_fair[port] : p2_tx_fair[port]; |
| custom_start_tdc[port] = start_tdc; |
| start_tdc += custom_num_tdc[port]; |
| } |
| } |
| break; |
| |
| default: |
| /* use default config */ |
| cfg_prop = "fair"; |
| for (port = 0; port < num_ports; port++) { |
| custom_num_tdc[port] = (num_ports == 4) ? |
| p4_tx_fair[port] : p2_tx_fair[port]; |
| custom_start_tdc[port] = start_tdc; |
| start_tdc += custom_num_tdc[port]; |
| } |
| break; |
| } |
| |
| /* Now Update the tx properties */ |
| for (port = 0; port < num_ports; port++) { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " update property txdma-cfg with %s ", cfg_prop)); |
| ddi_status = ddi_prop_update_string(DDI_DEV_T_NONE, s_dip[port], |
| "txdma-cfg", cfg_prop); |
| if (ddi_status != DDI_PROP_SUCCESS) { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " property txdma-cfg is not updating to %s", |
| cfg_prop)); |
| status |= NXGE_DDI_FAILED; |
| } |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, " update property %s with %d ", |
| num_tdc_prop, custom_num_tdc[port])); |
| |
| ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port], |
| num_tdc_prop, custom_num_tdc[port]); |
| |
| if (ddi_status != DDI_PROP_SUCCESS) { |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| " property %s not updating with %d", |
| num_tdc_prop, |
| custom_num_tdc[port])); |
| status |= NXGE_DDI_FAILED; |
| } |
| |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, " update property %s with %d ", |
| start_tdc_prop, custom_start_tdc[port])); |
| |
| ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, s_dip[port], |
| start_tdc_prop, custom_start_tdc[port]); |
| if (ddi_status != DDI_PROP_SUCCESS) { |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| " property %s not updating with %d ", |
| start_tdc_prop, custom_start_tdc[port])); |
| status |= NXGE_DDI_FAILED; |
| } |
| } |
| if (status & NXGE_DDI_FAILED) |
| status |= NXGE_ERROR; |
| return (status); |
| } |
| |
| static nxge_status_t |
| nxge_update_cfg_properties(p_nxge_t nxgep, uint32_t flags, |
| config_token_t token, dev_info_t *s_dip[]) |
| { |
| nxge_status_t status = NXGE_OK; |
| |
| switch (flags) { |
| case COMMON_TXDMA_CFG: |
| if (nxge_dma_obp_props_only == 0) |
| status = nxge_update_txdma_properties(nxgep, |
| token, s_dip); |
| break; |
| case COMMON_RXDMA_CFG: |
| if (nxge_dma_obp_props_only == 0) |
| status = nxge_update_rxdma_properties(nxgep, |
| token, s_dip); |
| |
| break; |
| case COMMON_RXDMA_GRP_CFG: |
| status = nxge_update_rxdma_grp_properties(nxgep, |
| token, s_dip); |
| break; |
| default: |
| return (NXGE_ERROR); |
| } |
| return (status); |
| } |
| |
| /* |
| * verify consistence. |
| * (May require publishing the properties on all the ports. |
| * |
| * What if properties are published on function 0 device only? |
| * |
| * |
| * rxdma-cfg, txdma-cfg, rxdma-grp-cfg (required ) |
| * What about class configs? |
| * |
| * If consistent, update the property on all the siblings. |
| * set a flag on hardware shared register |
| * The rest of the siblings will check the flag |
| * if the flag is set, they will use the updated property |
| * without doing any validation. |
| */ |
| |
| nxge_status_t |
| nxge_cfg_verify_set_classify_prop(p_nxge_t nxgep, char *prop, |
| uint64_t known_cfg, uint32_t override, dev_info_t *c_dip[]) |
| { |
| nxge_status_t status = NXGE_OK; |
| int ddi_status = DDI_SUCCESS; |
| int i = 0, found = 0, update_prop = B_TRUE; |
| int *cfg_val; |
| uint_t new_value, cfg_value[MAX_SIBLINGS]; |
| uint_t prop_len; |
| uint_t known_cfg_value; |
| |
| known_cfg_value = (uint_t)known_cfg; |
| |
| if (override == B_TRUE) { |
| new_value = known_cfg_value; |
| for (i = 0; i < nxgep->nports; i++) { |
| ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, |
| c_dip[i], prop, new_value); |
| #ifdef NXGE_DEBUG_ERROR |
| if (ddi_status != DDI_PROP_SUCCESS) |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| " property %s failed update ", prop)); |
| #endif |
| } |
| if (ddi_status != DDI_PROP_SUCCESS) |
| return (NXGE_ERROR | NXGE_DDI_FAILED); |
| } |
| for (i = 0; i < nxgep->nports; i++) { |
| cfg_value[i] = known_cfg_value; |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, c_dip[i], 0, |
| prop, &cfg_val, |
| &prop_len) == DDI_PROP_SUCCESS) { |
| cfg_value[i] = *cfg_val; |
| ddi_prop_free(cfg_val); |
| found++; |
| } |
| } |
| |
| if (found != i) { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " property %s not specified on all ports", prop)); |
| if (found == 0) { |
| /* not specified: Use default */ |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " property %s not specified on any port:" |
| " Using default", prop)); |
| new_value = known_cfg_value; |
| } else { |
| /* specified on some */ |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " property %s not specified" |
| " on some ports: Using default", prop)); |
| /* ? use p0 value instead ? */ |
| new_value = known_cfg_value; |
| } |
| } else { |
| /* check type and consistence */ |
| /* found on all devices */ |
| for (i = 1; i < found; i++) { |
| if (cfg_value[i] != cfg_value[i - 1]) { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " property %s inconsistent:" |
| " Using default", prop)); |
| new_value = known_cfg_value; |
| break; |
| } |
| /* |
| * Found on all the ports and consistent. Nothing to |
| * do. |
| */ |
| update_prop = B_FALSE; |
| } |
| } |
| |
| if (update_prop == B_TRUE) { |
| for (i = 0; i < nxgep->nports; i++) { |
| ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, |
| c_dip[i], prop, new_value); |
| #ifdef NXGE_DEBUG_ERROR |
| if (ddi_status != DDI_SUCCESS) |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| " property %s not updating with %d" |
| " Using default", |
| prop, new_value)); |
| #endif |
| if (ddi_status != DDI_PROP_SUCCESS) |
| status |= NXGE_DDI_FAILED; |
| } |
| } |
| if (status & NXGE_DDI_FAILED) |
| status |= NXGE_ERROR; |
| |
| return (status); |
| } |
| |
| static uint64_t |
| nxge_class_get_known_cfg(p_nxge_t nxgep, int class_prop, int rx_quick_cfg) |
| { |
| int start_prop; |
| uint64_t cfg_value; |
| p_nxge_param_t param_arr; |
| |
| param_arr = nxgep->param_arr; |
| cfg_value = param_arr[class_prop].value; |
| start_prop = param_h1_init_value; |
| |
| /* update the properties per quick config */ |
| switch (rx_quick_cfg) { |
| case CFG_L3_WEB: |
| case CFG_L3_DISTRIBUTE: |
| cfg_value = nxge_classify_get_cfg_value(nxgep, |
| rx_quick_cfg, class_prop - start_prop); |
| break; |
| default: |
| cfg_value = param_arr[class_prop].value; |
| break; |
| } |
| return (cfg_value); |
| } |
| |
| static nxge_status_t |
| nxge_cfg_verify_set_classify(p_nxge_t nxgep, dev_info_t *c_dip[]) |
| { |
| nxge_status_t status = NXGE_OK; |
| int rx_quick_cfg, class_prop, start_prop, end_prop; |
| char *prop_name; |
| int override = B_TRUE; |
| uint64_t cfg_value; |
| p_nxge_param_t param_arr; |
| |
| param_arr = nxgep->param_arr; |
| rx_quick_cfg = param_arr[param_rx_quick_cfg].value; |
| start_prop = param_h1_init_value; |
| end_prop = param_class_opt_ipv6_sctp; |
| |
| /* update the properties per quick config */ |
| if (rx_quick_cfg == CFG_NOT_SPECIFIED) |
| override = B_FALSE; |
| |
| /* |
| * these parameter affect the classification outcome. |
| * these parameters are used to configure the Flow key and |
| * the TCAM key for each of the IP classes. |
| * Included here are also the H1 and H2 initial values |
| * which affect the distribution as well as final hash value |
| * (hence the offset into RDC table and FCRAM bucket location) |
| * |
| */ |
| for (class_prop = start_prop; class_prop <= end_prop; class_prop++) { |
| prop_name = param_arr[class_prop].fcode_name; |
| cfg_value = nxge_class_get_known_cfg(nxgep, |
| class_prop, rx_quick_cfg); |
| status = nxge_cfg_verify_set_classify_prop(nxgep, prop_name, |
| cfg_value, override, c_dip); |
| } |
| |
| /* |
| * these properties do not affect the actual classification outcome. |
| * used to enable/disable or tune the fflp hardware |
| * |
| * fcram_access_ratio, tcam_access_ratio, tcam_enable, llc_snap_enable |
| * |
| */ |
| override = B_FALSE; |
| for (class_prop = param_fcram_access_ratio; |
| class_prop <= param_llc_snap_enable; class_prop++) { |
| prop_name = param_arr[class_prop].fcode_name; |
| cfg_value = param_arr[class_prop].value; |
| status = nxge_cfg_verify_set_classify_prop(nxgep, prop_name, |
| cfg_value, override, c_dip); |
| } |
| |
| return (status); |
| } |
| |
| nxge_status_t |
| nxge_cfg_verify_set(p_nxge_t nxgep, uint32_t flag) |
| { |
| nxge_status_t status = NXGE_OK; |
| int i = 0, found = 0; |
| int num_siblings; |
| dev_info_t *c_dip[MAX_SIBLINGS + 1]; |
| char *prop_val[MAX_SIBLINGS]; |
| config_token_t c_token[MAX_SIBLINGS]; |
| char *prop; |
| |
| if (nxge_dma_obp_props_only) |
| return (NXGE_OK); |
| |
| num_siblings = 0; |
| c_dip[num_siblings] = ddi_get_child(nxgep->p_dip); |
| while (c_dip[num_siblings]) { |
| c_dip[num_siblings + 1] = |
| ddi_get_next_sibling(c_dip[num_siblings]); |
| num_siblings++; |
| } |
| |
| switch (flag) { |
| case COMMON_TXDMA_CFG: |
| prop = "txdma-cfg"; |
| break; |
| case COMMON_RXDMA_CFG: |
| prop = "rxdma-cfg"; |
| break; |
| case COMMON_RXDMA_GRP_CFG: |
| prop = "rxdma-grp-cfg"; |
| break; |
| case COMMON_CLASS_CFG: |
| status = nxge_cfg_verify_set_classify(nxgep, c_dip); |
| return (status); |
| default: |
| return (NXGE_ERROR); |
| } |
| |
| i = 0; |
| while (i < num_siblings) { |
| if (ddi_prop_lookup_string(DDI_DEV_T_ANY, c_dip[i], 0, prop, |
| (char **)&prop_val[i]) == DDI_PROP_SUCCESS) { |
| c_token[i] = nxge_get_config_token(prop_val[i]); |
| ddi_prop_free(prop_val[i]); |
| found++; |
| } else |
| c_token[i] = CONFIG_TOKEN_NONE; |
| i++; |
| } |
| |
| if (found != i) { |
| if (found == 0) { |
| /* not specified: Use default */ |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " property %s not specified on any port:" |
| " Using default", prop)); |
| |
| status = nxge_update_cfg_properties(nxgep, |
| flag, FAIR, c_dip); |
| return (status); |
| } else { |
| /* |
| * if the convention is to use function 0 device then |
| * populate the other devices with this configuration. |
| * |
| * The other alternative is to use the default config. |
| */ |
| /* not specified: Use default */ |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " property %s not specified on some ports:" |
| " Using default", prop)); |
| status = nxge_update_cfg_properties(nxgep, |
| flag, FAIR, c_dip); |
| return (status); |
| } |
| } |
| |
| /* check type and consistence */ |
| /* found on all devices */ |
| for (i = 1; i < found; i++) { |
| if (c_token[i] != c_token[i - 1]) { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " property %s inconsistent:" |
| " Using default", prop)); |
| status = nxge_update_cfg_properties(nxgep, |
| flag, FAIR, c_dip); |
| return (status); |
| } |
| } |
| |
| /* |
| * Found on all the ports check if it is custom configuration. if |
| * custom, then verify consistence |
| * |
| * finally create soft properties |
| */ |
| status = nxge_update_cfg_properties(nxgep, flag, c_token[0], c_dip); |
| return (status); |
| } |
| |
| nxge_status_t |
| nxge_cfg_verify_set_quick_config(p_nxge_t nxgep) |
| { |
| nxge_status_t status = NXGE_OK; |
| int ddi_status = DDI_SUCCESS; |
| char *prop_val; |
| char *rx_prop; |
| char *prop; |
| uint32_t cfg_value = CFG_NOT_SPECIFIED; |
| p_nxge_param_t param_arr; |
| |
| param_arr = nxgep->param_arr; |
| rx_prop = param_arr[param_rx_quick_cfg].fcode_name; |
| |
| prop = "rx-quick-cfg"; |
| |
| /* |
| * good value are |
| * |
| * "web-server" "generic-server" "l3-classify" "flow-classify" |
| */ |
| if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0, |
| prop, (char **)&prop_val) != DDI_PROP_SUCCESS) { |
| NXGE_DEBUG_MSG((nxgep, VPD_CTL, |
| " property %s not specified: using default ", prop)); |
| cfg_value = CFG_NOT_SPECIFIED; |
| } else { |
| cfg_value = CFG_L3_DISTRIBUTE; |
| if (strncmp("web-server", (caddr_t)prop_val, 8) == 0) { |
| cfg_value = CFG_L3_WEB; |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " %s: web server ", prop)); |
| } |
| if (strncmp("generic-server", (caddr_t)prop_val, 8) == 0) { |
| cfg_value = CFG_L3_DISTRIBUTE; |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| " %s: distribute ", prop)); |
| } |
| /* more */ |
| ddi_prop_free(prop_val); |
| } |
| |
| ddi_status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip, |
| rx_prop, cfg_value); |
| if (ddi_status != DDI_PROP_SUCCESS) |
| status |= NXGE_DDI_FAILED; |
| |
| /* now handle specified cases: */ |
| if (status & NXGE_DDI_FAILED) |
| status |= NXGE_ERROR; |
| return (status); |
| } |
| |
| /* |
| * Device properties adv-autoneg-cap etc are defined by FWARC |
| * http://sac.sfbay/FWARC/2002/345/20020610_asif.haswarey |
| */ |
| static void |
| nxge_use_cfg_link_cfg(p_nxge_t nxgep) |
| { |
| int *prop_val; |
| uint_t prop_len; |
| dev_info_t *dip; |
| int speed; |
| int duplex; |
| int adv_autoneg_cap; |
| int adv_10gfdx_cap; |
| int adv_10ghdx_cap; |
| int adv_1000fdx_cap; |
| int adv_1000hdx_cap; |
| int adv_100fdx_cap; |
| int adv_100hdx_cap; |
| int adv_10fdx_cap; |
| int adv_10hdx_cap; |
| int status = DDI_SUCCESS; |
| |
| dip = nxgep->dip; |
| |
| /* |
| * first find out the card type and the supported link speeds and |
| * features |
| */ |
| /* add code for card type */ |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-autoneg-cap", |
| &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| ddi_prop_free(prop_val); |
| return; |
| } |
| |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-10gfdx-cap", |
| &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| ddi_prop_free(prop_val); |
| return; |
| } |
| |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-1000hdx-cap", |
| &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| ddi_prop_free(prop_val); |
| return; |
| } |
| |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-1000fdx-cap", |
| &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| ddi_prop_free(prop_val); |
| return; |
| } |
| |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-100fdx-cap", |
| &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| ddi_prop_free(prop_val); |
| return; |
| } |
| |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-100hdx-cap", |
| &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| ddi_prop_free(prop_val); |
| return; |
| } |
| |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-10fdx-cap", |
| &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| ddi_prop_free(prop_val); |
| return; |
| } |
| |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "adv-10hdx-cap", |
| &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| ddi_prop_free(prop_val); |
| return; |
| } |
| |
| if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, 0, "speed", |
| (uchar_t **)&prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| if (strncmp("10000", (caddr_t)prop_val, |
| (size_t)prop_len) == 0) { |
| speed = 10000; |
| } else if (strncmp("1000", (caddr_t)prop_val, |
| (size_t)prop_len) == 0) { |
| speed = 1000; |
| } else if (strncmp("100", (caddr_t)prop_val, |
| (size_t)prop_len) == 0) { |
| speed = 100; |
| } else if (strncmp("10", (caddr_t)prop_val, |
| (size_t)prop_len) == 0) { |
| speed = 10; |
| } else if (strncmp("auto", (caddr_t)prop_val, |
| (size_t)prop_len) == 0) { |
| speed = 0; |
| } else { |
| NXGE_ERROR_MSG((nxgep, NXGE_NOTE, |
| "speed property is invalid reverting to auto")); |
| speed = 0; |
| } |
| ddi_prop_free(prop_val); |
| } else |
| speed = 0; |
| |
| if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, 0, "duplex", |
| (uchar_t **)&prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| if (strncmp("full", (caddr_t)prop_val, |
| (size_t)prop_len) == 0) { |
| duplex = 2; |
| } else if (strncmp("half", (caddr_t)prop_val, |
| (size_t)prop_len) == 0) { |
| duplex = 1; |
| } else if (strncmp("auto", (caddr_t)prop_val, |
| (size_t)prop_len) == 0) { |
| duplex = 0; |
| } else { |
| NXGE_ERROR_MSG((nxgep, NXGE_NOTE, |
| "duplex property is invalid" |
| " reverting to auto")); |
| duplex = 0; |
| } |
| ddi_prop_free(prop_val); |
| } else |
| duplex = 0; |
| |
| /* speed == 0 or duplex == 0 means auto negotiation. */ |
| adv_autoneg_cap = (speed == 0) || (duplex == 0); |
| if (adv_autoneg_cap == 0) { |
| adv_10gfdx_cap = ((speed == 10000) && (duplex == 2)); |
| adv_10ghdx_cap = adv_10gfdx_cap; |
| adv_10ghdx_cap |= ((speed == 10000) && (duplex == 1)); |
| adv_1000fdx_cap = adv_10ghdx_cap; |
| adv_1000fdx_cap |= ((speed == 1000) && (duplex == 2)); |
| adv_1000hdx_cap = adv_1000fdx_cap; |
| adv_1000hdx_cap |= ((speed == 1000) && (duplex == 1)); |
| adv_100fdx_cap = adv_1000hdx_cap; |
| adv_100fdx_cap |= ((speed == 100) && (duplex == 2)); |
| adv_100hdx_cap = adv_100fdx_cap; |
| adv_100hdx_cap |= ((speed == 100) && (duplex == 1)); |
| adv_10fdx_cap = adv_100hdx_cap; |
| adv_10fdx_cap |= ((speed == 10) && (duplex == 2)); |
| adv_10hdx_cap = adv_10fdx_cap; |
| adv_10hdx_cap |= ((speed == 10) && (duplex == 1)); |
| } else if (speed == 0) { |
| adv_10gfdx_cap = (duplex == 2); |
| adv_10ghdx_cap = (duplex == 1); |
| adv_1000fdx_cap = (duplex == 2); |
| adv_1000hdx_cap = (duplex == 1); |
| adv_100fdx_cap = (duplex == 2); |
| adv_100hdx_cap = (duplex == 1); |
| adv_10fdx_cap = (duplex == 2); |
| adv_10hdx_cap = (duplex == 1); |
| } |
| if (duplex == 0) { |
| adv_10gfdx_cap = (speed == 0); |
| adv_10gfdx_cap |= (speed == 10000); |
| adv_10ghdx_cap = adv_10gfdx_cap; |
| adv_10ghdx_cap |= (speed == 10000); |
| adv_1000fdx_cap = adv_10ghdx_cap; |
| adv_1000fdx_cap |= (speed == 1000); |
| adv_1000hdx_cap = adv_1000fdx_cap; |
| adv_1000hdx_cap |= (speed == 1000); |
| adv_100fdx_cap = adv_1000hdx_cap; |
| adv_100fdx_cap |= (speed == 100); |
| adv_100hdx_cap = adv_100fdx_cap; |
| adv_100hdx_cap |= (speed == 100); |
| adv_10fdx_cap = adv_100hdx_cap; |
| adv_10fdx_cap |= (speed == 10); |
| adv_10hdx_cap = adv_10fdx_cap; |
| adv_10hdx_cap |= (speed == 10); |
| } |
| status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, |
| "adv-autoneg-cap", &adv_autoneg_cap, 1); |
| if (status) |
| return; |
| |
| status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, |
| "adv-10gfdx-cap", &adv_10gfdx_cap, 1); |
| if (status) |
| goto nxge_map_myargs_to_gmii_fail1; |
| |
| status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, |
| "adv-10ghdx-cap", &adv_10ghdx_cap, 1); |
| if (status) |
| goto nxge_map_myargs_to_gmii_fail2; |
| |
| status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, |
| "adv-1000fdx-cap", &adv_1000fdx_cap, 1); |
| if (status) |
| goto nxge_map_myargs_to_gmii_fail3; |
| |
| status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, |
| "adv-1000hdx-cap", &adv_1000hdx_cap, 1); |
| if (status) |
| goto nxge_map_myargs_to_gmii_fail4; |
| |
| status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, |
| "adv-100fdx-cap", &adv_100fdx_cap, 1); |
| if (status) |
| goto nxge_map_myargs_to_gmii_fail5; |
| |
| status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, |
| "adv-100hdx-cap", &adv_100hdx_cap, 1); |
| if (status) |
| goto nxge_map_myargs_to_gmii_fail6; |
| |
| status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, |
| "adv-10fdx-cap", &adv_10fdx_cap, 1); |
| if (status) |
| goto nxge_map_myargs_to_gmii_fail7; |
| |
| status = ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, |
| "adv-10hdx-cap", &adv_10hdx_cap, 1); |
| if (status) |
| goto nxge_map_myargs_to_gmii_fail8; |
| |
| return; |
| |
| nxge_map_myargs_to_gmii_fail9: |
| (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-10hdx-cap"); |
| |
| nxge_map_myargs_to_gmii_fail8: |
| (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-10fdx-cap"); |
| |
| nxge_map_myargs_to_gmii_fail7: |
| (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-100hdx-cap"); |
| |
| nxge_map_myargs_to_gmii_fail6: |
| (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-100fdx-cap"); |
| |
| nxge_map_myargs_to_gmii_fail5: |
| (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-1000hdx-cap"); |
| |
| nxge_map_myargs_to_gmii_fail4: |
| (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-1000fdx-cap"); |
| |
| nxge_map_myargs_to_gmii_fail3: |
| (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-10ghdx-cap"); |
| |
| nxge_map_myargs_to_gmii_fail2: |
| (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-10gfdx-cap"); |
| |
| nxge_map_myargs_to_gmii_fail1: |
| (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "adv-autoneg-cap"); |
| } |
| |
| nxge_status_t |
| nxge_get_config_properties(p_nxge_t nxgep) |
| { |
| nxge_status_t status = NXGE_OK; |
| p_nxge_hw_list_t hw_p; |
| char **prop_val; |
| uint_t prop_len; |
| uint_t i; |
| |
| NXGE_DEBUG_MSG((nxgep, VPD_CTL, " ==> nxge_get_config_properties")); |
| |
| if ((hw_p = nxgep->nxge_hw_p) == NULL) { |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| " nxge_get_config_properties:" |
| " common hardware not set", nxgep->niu_type)); |
| return (NXGE_ERROR); |
| } |
| |
| /* |
| * Get info on how many ports Neptune card has. |
| */ |
| nxgep->nports = nxge_get_nports(nxgep); |
| if (nxgep->nports <= 0) { |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| "<==nxge_get_config_properties: Invalid Neptune type 0x%x", |
| nxgep->niu_type)); |
| return (NXGE_ERROR); |
| } |
| nxgep->classifier.tcam_size = TCAM_NIU_TCAM_MAX_ENTRY; |
| if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { |
| nxgep->classifier.tcam_size = TCAM_NXGE_TCAM_MAX_ENTRY; |
| } |
| if (nxgep->function_num >= nxgep->nports) { |
| return (NXGE_ERROR); |
| } |
| |
| status = nxge_get_mac_addr_properties(nxgep); |
| if (status != NXGE_OK) |
| return (NXGE_ERROR); |
| |
| /* |
| * read the configuration type. If none is specified, used default. |
| * Config types: equal: (default) DMA channels, RDC groups, TCAM, FCRAM |
| * are shared equally across all the ports. |
| * |
| * Fair: DMA channels, RDC groups, TCAM, FCRAM are shared proportional |
| * to the port speed. |
| * |
| * |
| * custom: DMA channels, RDC groups, TCAM, FCRAM partition is |
| * specified in nxge.conf. Need to read each parameter and set |
| * up the parameters in nxge structures. |
| * |
| */ |
| switch (nxgep->niu_type) { |
| case N2_NIU: |
| NXGE_DEBUG_MSG((nxgep, VPD_CTL, |
| " ==> nxge_get_config_properties: N2")); |
| MUTEX_ENTER(&hw_p->nxge_cfg_lock); |
| if ((hw_p->flags & COMMON_CFG_VALID) != |
| COMMON_CFG_VALID) { |
| status = nxge_cfg_verify_set(nxgep, |
| COMMON_RXDMA_GRP_CFG); |
| status = nxge_cfg_verify_set(nxgep, |
| COMMON_CLASS_CFG); |
| hw_p->flags |= COMMON_CFG_VALID; |
| } |
| MUTEX_EXIT(&hw_p->nxge_cfg_lock); |
| status = nxge_use_cfg_n2niu_properties(nxgep); |
| break; |
| default: |
| if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| " nxge_get_config_properties:" |
| " unknown NIU type 0x%x", nxgep->niu_type)); |
| return (NXGE_ERROR); |
| } |
| |
| NXGE_DEBUG_MSG((nxgep, VPD_CTL, |
| " ==> nxge_get_config_properties: Neptune")); |
| status = nxge_cfg_verify_set_quick_config(nxgep); |
| MUTEX_ENTER(&hw_p->nxge_cfg_lock); |
| if ((hw_p->flags & COMMON_CFG_VALID) != |
| COMMON_CFG_VALID) { |
| status = nxge_cfg_verify_set(nxgep, |
| COMMON_TXDMA_CFG); |
| status = nxge_cfg_verify_set(nxgep, |
| COMMON_RXDMA_CFG); |
| status = nxge_cfg_verify_set(nxgep, |
| COMMON_RXDMA_GRP_CFG); |
| status = nxge_cfg_verify_set(nxgep, |
| COMMON_CLASS_CFG); |
| hw_p->flags |= COMMON_CFG_VALID; |
| } |
| MUTEX_EXIT(&hw_p->nxge_cfg_lock); |
| nxge_use_cfg_neptune_properties(nxgep); |
| status = NXGE_OK; |
| break; |
| } |
| |
| /* |
| * Get the software LSO enable flag property from the |
| * driver configuration file (nxge.conf). |
| * This flag will be set to disable (0) if this property |
| * does not exist. |
| */ |
| nxgep->soft_lso_enable = ddi_prop_get_int(DDI_DEV_T_ANY, nxgep->dip, |
| DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "soft-lso-enable", 0); |
| NXGE_DEBUG_MSG((nxgep, VPD_CTL, |
| "nxge_get_config_properties: software lso %d\n", |
| nxgep->soft_lso_enable)); |
| |
| nxgep->niu_hw_type = NIU_HW_TYPE_DEFAULT; |
| if (nxgep->niu_type == N2_NIU) { |
| |
| uchar_t *s_prop_val; |
| |
| /* |
| * For NIU, the next generation KT has |
| * a few differences in features that the |
| * driver needs to handle them |
| * accordingly. |
| */ |
| if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, nxgep->dip, 0, |
| "compatible", &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| for (i = 0; i < prop_len; i++) { |
| if ((strcmp((caddr_t)prop_val[i], |
| KT_NIU_COMPATIBLE) == 0)) { |
| nxgep->niu_hw_type = NIU_HW_TYPE_RF; |
| NXGE_DEBUG_MSG((nxgep, VPD_CTL, |
| "NIU type %d", nxgep->niu_hw_type)); |
| break; |
| } |
| } |
| } |
| |
| ddi_prop_free(prop_val); |
| /* |
| * Some Serdes and PHY properties may also be provided as OBP |
| * properties |
| */ |
| if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0, |
| "tx-cfg-l", &s_prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| nxgep->srds_prop.tx_cfg_l = |
| (uint16_t)(*(uint32_t *)s_prop_val); |
| NXGE_DEBUG_MSG((nxgep, VPD_CTL, |
| "nxge_get_config_properties: " |
| "tx_cfg_l 0x%x, Read from OBP", |
| nxgep->srds_prop.tx_cfg_l)); |
| nxgep->srds_prop.prop_set |= NXGE_SRDS_TXCFGL; |
| ddi_prop_free(s_prop_val); |
| } |
| if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0, |
| "tx-cfg-h", &s_prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| nxgep->srds_prop.tx_cfg_h = |
| (uint16_t)(*(uint32_t *)s_prop_val); |
| NXGE_DEBUG_MSG((nxgep, VPD_CTL, |
| "nxge_get_config_properties: " |
| "tx_cfg_h 0x%x, Read from OBP", |
| nxgep->srds_prop.tx_cfg_h)); |
| nxgep->srds_prop.prop_set |= NXGE_SRDS_TXCFGH; |
| ddi_prop_free(s_prop_val); |
| } |
| if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0, |
| "rx-cfg-l", &s_prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| nxgep->srds_prop.rx_cfg_l = |
| (uint16_t)(*(uint32_t *)s_prop_val); |
| NXGE_DEBUG_MSG((nxgep, VPD_CTL, |
| "nxge_get_config_properties: " |
| "rx_cfg_l 0x%x, Read from OBP", |
| nxgep->srds_prop.rx_cfg_l)); |
| nxgep->srds_prop.prop_set |= NXGE_SRDS_RXCFGL; |
| ddi_prop_free(s_prop_val); |
| } |
| if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0, |
| "rx-cfg-h", &s_prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| nxgep->srds_prop.rx_cfg_h = |
| (uint16_t)(*(uint32_t *)s_prop_val); |
| NXGE_DEBUG_MSG((nxgep, VPD_CTL, |
| "nxge_get_config_properties: " |
| "rx_cfg_h 0x%x, Read from OBP", |
| nxgep->srds_prop.rx_cfg_h)); |
| nxgep->srds_prop.prop_set |= NXGE_SRDS_RXCFGH; |
| ddi_prop_free(s_prop_val); |
| } |
| if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0, |
| "pll-cfg", &s_prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| nxgep->srds_prop.pll_cfg_l = |
| (uint16_t)(*(uint32_t *)s_prop_val); |
| NXGE_DEBUG_MSG((nxgep, VPD_CTL, |
| "nxge_get_config_properties: " |
| "pll_cfg_l 0x%x, Read from OBP", |
| nxgep->srds_prop.pll_cfg_l)); |
| nxgep->srds_prop.prop_set |= NXGE_SRDS_PLLCFGL; |
| ddi_prop_free(s_prop_val); |
| } |
| if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, nxgep->dip, 0, |
| "phy-reg-values", &s_prop_val, &prop_len) == |
| DDI_PROP_SUCCESS) { |
| |
| int tun_cnt, i; |
| uchar_t *arr = s_prop_val; |
| |
| tun_cnt = prop_len / 6; /* 3 values, 2 bytes each */ |
| nxgep->phy_prop.arr = |
| KMEM_ZALLOC(sizeof (nxge_phy_mdio_val_t) * tun_cnt, |
| KM_SLEEP); |
| nxgep->phy_prop.cnt = tun_cnt; |
| for (i = 0; i < tun_cnt; i++) { |
| nxgep->phy_prop.arr[i].dev = *(uint16_t *)arr; |
| arr += 2; |
| nxgep->phy_prop.arr[i].reg = *(uint16_t *)arr; |
| arr += 2; |
| nxgep->phy_prop.arr[i].val = *(uint16_t *)arr; |
| arr += 2; |
| NXGE_DEBUG_MSG((nxgep, VPD_CTL, |
| "nxge_get_config_properties: From OBP, " |
| "read PHY <dev.reg.val> = " |
| "<0x%x.0x%x.0x%x>", |
| nxgep->phy_prop.arr[i].dev, |
| nxgep->phy_prop.arr[i].reg, |
| nxgep->phy_prop.arr[i].val)); |
| } |
| ddi_prop_free(s_prop_val); |
| } |
| } |
| |
| NXGE_DEBUG_MSG((nxgep, VPD_CTL, " <== nxge_get_config_properties")); |
| return (status); |
| } |
| |
| static nxge_status_t |
| nxge_use_cfg_n2niu_properties(p_nxge_t nxgep) |
| { |
| nxge_status_t status = NXGE_OK; |
| |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_use_cfg_n2niu_properties")); |
| |
| status = nxge_use_default_dma_config_n2(nxgep); |
| if (status != NXGE_OK) { |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| " ==> nxge_use_cfg_n2niu_properties (err 0x%x)", |
| status)); |
| return (status | NXGE_ERROR); |
| } |
| |
| (void) nxge_use_cfg_vlan_class_config(nxgep); |
| (void) nxge_use_cfg_mac_class_config(nxgep); |
| (void) nxge_use_cfg_class_config(nxgep); |
| (void) nxge_use_cfg_link_cfg(nxgep); |
| |
| /* |
| * Read in the hardware (fcode) properties. Use the ndd array to read |
| * each property. |
| */ |
| (void) nxge_get_param_soft_properties(nxgep); |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_use_cfg_n2niu_properties")); |
| |
| return (status); |
| } |
| |
| static void |
| nxge_use_cfg_neptune_properties(p_nxge_t nxgep) |
| { |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_use_cfg_neptune_properties")); |
| |
| (void) nxge_use_cfg_dma_config(nxgep); |
| (void) nxge_use_cfg_vlan_class_config(nxgep); |
| (void) nxge_use_cfg_mac_class_config(nxgep); |
| (void) nxge_use_cfg_class_config(nxgep); |
| (void) nxge_use_cfg_link_cfg(nxgep); |
| |
| /* |
| * Read in the hardware (fcode) properties. Use the ndd array to read |
| * each property. |
| */ |
| (void) nxge_get_param_soft_properties(nxgep); |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_use_cfg_neptune_properties")); |
| } |
| |
| /* |
| * FWARC 2006/556 for N2 NIU. Get the properties |
| * from the prom. |
| */ |
| static nxge_status_t |
| nxge_use_default_dma_config_n2(p_nxge_t nxgep) |
| { |
| int ndmas; |
| uint8_t func; |
| p_nxge_dma_pt_cfg_t p_dma_cfgp; |
| p_nxge_hw_pt_cfg_t p_cfgp; |
| int *prop_val; |
| uint_t prop_len; |
| int i; |
| nxge_status_t status = NXGE_OK; |
| |
| NXGE_DEBUG_MSG((nxgep, OBP_CTL, "==> nxge_use_default_dma_config_n2")); |
| |
| p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; |
| p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; |
| |
| func = nxgep->function_num; |
| p_cfgp->function_number = func; |
| ndmas = NXGE_TDMA_PER_NIU_PORT; |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, |
| "tx-dma-channels", (int **)&prop_val, |
| &prop_len) == DDI_PROP_SUCCESS) { |
| if (prop_len != NXGE_NIU_TDMA_PROP_LEN) { |
| ddi_prop_free(prop_val); |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| "==> nxge_use_default_dma_config_n2: " |
| "invalid tx-dma-channels property for the NIU, " |
| "using defaults")); |
| /* |
| * Just failover to defaults |
| */ |
| p_cfgp->tdc.start = (func * NXGE_TDMA_PER_NIU_PORT); |
| ndmas = NXGE_TDMA_PER_NIU_PORT; |
| } else { |
| p_cfgp->tdc.start = prop_val[0]; |
| NXGE_DEBUG_MSG((nxgep, OBP_CTL, |
| "==> nxge_use_default_dma_config_n2: tdc starts %d " |
| "(#%d)", p_cfgp->tdc.start, prop_len)); |
| |
| ndmas = prop_val[1]; |
| NXGE_DEBUG_MSG((nxgep, OBP_CTL, |
| "==> nxge_use_default_dma_config_n2: #tdc %d (#%d)", |
| ndmas, prop_len)); |
| ddi_prop_free(prop_val); |
| } |
| } else { |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| "==> nxge_use_default_dma_config_n2: " |
| "get tx-dma-channels failed")); |
| return (NXGE_DDI_FAILED); |
| } |
| |
| p_cfgp->tdc.count = ndmas; |
| p_cfgp->tdc.owned = p_cfgp->tdc.count; |
| |
| NXGE_DEBUG_MSG((nxgep, OBP_CTL, "==> nxge_use_default_dma_config_n2: " |
| "p_cfgp 0x%llx max_tdcs %d start %d", |
| p_cfgp, p_cfgp->tdc.count, p_cfgp->tdc.start)); |
| |
| /* Receive DMA */ |
| ndmas = NXGE_RDMA_PER_NIU_PORT; |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, |
| "rx-dma-channels", (int **)&prop_val, |
| &prop_len) == DDI_PROP_SUCCESS) { |
| if (prop_len != NXGE_NIU_RDMA_PROP_LEN) { |
| ddi_prop_free(prop_val); |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| "==> nxge_use_default_dma_config_n2: " |
| "invalid rx-dma-channels property for the NIU, " |
| "using defaults")); |
| /* |
| * Just failover to defaults |
| */ |
| p_cfgp->start_rdc = (func * NXGE_RDMA_PER_NIU_PORT); |
| ndmas = NXGE_RDMA_PER_NIU_PORT; |
| } else { |
| p_cfgp->start_rdc = prop_val[0]; |
| NXGE_DEBUG_MSG((nxgep, OBP_CTL, |
| "==> nxge_use_default_dma_config_n2(obp):" |
| " rdc start %d (#%d)", |
| p_cfgp->start_rdc, prop_len)); |
| ndmas = prop_val[1]; |
| NXGE_DEBUG_MSG((nxgep, OBP_CTL, |
| "==> nxge_use_default_dma_config_n2(obp): " |
| "#rdc %d (#%d)", ndmas, prop_len)); |
| ddi_prop_free(prop_val); |
| } |
| } else { |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| "==> nxge_use_default_dma_config_n2: " |
| "get rx-dma-channel failed")); |
| return (NXGE_DDI_FAILED); |
| } |
| |
| p_cfgp->max_rdcs = ndmas; |
| nxgep->rdc_mask = (ndmas - 1); |
| |
| /* Hypervisor: rdc # and group # use the same # !! */ |
| p_cfgp->max_grpids = p_cfgp->max_rdcs + p_cfgp->tdc.owned; |
| p_cfgp->mif_ldvid = p_cfgp->mac_ldvid = p_cfgp->ser_ldvid = 0; |
| |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, |
| "interrupts", (int **)&prop_val, |
| &prop_len) == DDI_PROP_SUCCESS) { |
| if ((prop_len != NXGE_NIU_0_INTR_PROP_LEN) && |
| (prop_len != NXGE_NIU_1_INTR_PROP_LEN)) { |
| ddi_prop_free(prop_val); |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| "==> nxge_use_default_dma_config_n2: " |
| "get interrupts failed")); |
| return (NXGE_DDI_FAILED); |
| } |
| |
| /* |
| * For each device assigned, the content of each interrupts |
| * property is its logical device group. |
| * |
| * Assignment of interrupts property is in the the following |
| * order: |
| * |
| * MAC MIF (if configured) SYSTEM ERROR (if configured) first |
| * receive channel next channel...... last receive channel |
| * first transmit channel next channel...... last transmit |
| * channel |
| * |
| * prop_len should be at least for one mac and total # of rx and |
| * tx channels. Function 0 owns MIF and ERROR |
| */ |
| NXGE_DEBUG_MSG((nxgep, OBP_CTL, |
| "==> nxge_use_default_dma_config_n2(obp): " |
| "# interrupts %d", prop_len)); |
| |
| switch (func) { |
| case 0: |
| p_cfgp->ldg_chn_start = 3; |
| p_cfgp->mac_ldvid = NXGE_MAC_LD_PORT0; |
| p_cfgp->mif_ldvid = NXGE_MIF_LD; |
| p_cfgp->ser_ldvid = NXGE_SYS_ERROR_LD; |
| |
| break; |
| case 1: |
| p_cfgp->ldg_chn_start = 1; |
| p_cfgp->mac_ldvid = NXGE_MAC_LD_PORT1; |
| |
| break; |
| default: |
| status = NXGE_DDI_FAILED; |
| break; |
| } |
| |
| if (status != NXGE_OK) |
| return (status); |
| |
| for (i = 0; i < prop_len; i++) { |
| p_cfgp->ldg[i] = prop_val[i]; |
| NXGE_DEBUG_MSG((nxgep, OBP_CTL, |
| "==> nxge_use_default_dma_config_n2(obp): " |
| "F%d: interrupt #%d, ldg %d", |
| nxgep->function_num, i, p_cfgp->ldg[i])); |
| } |
| |
| p_cfgp->max_grpids = prop_len; |
| NXGE_DEBUG_MSG((nxgep, OBP_CTL, |
| "==> nxge_use_default_dma_config_n2(obp): %d " |
| "(#%d) maxgrpids %d channel starts %d", |
| p_cfgp->mac_ldvid, i, p_cfgp->max_grpids, |
| p_cfgp->ldg_chn_start)); |
| ddi_prop_free(prop_val); |
| } else { |
| NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, |
| "==> nxge_use_default_dma_config_n2: " |
| "get interrupts failed")); |
| return (NXGE_DDI_FAILED); |
| } |
| |
| p_cfgp->max_ldgs = p_cfgp->max_grpids; |
| NXGE_DEBUG_MSG((nxgep, OBP_CTL, |
| "==> nxge_use_default_dma_config_n2: p_cfgp 0x%llx max_rdcs %d " |
| "max_grpids %d macid %d mifid %d serrid %d", |
| p_cfgp, p_cfgp->max_rdcs, p_cfgp->max_grpids, |
| p_cfgp->mac_ldvid, p_cfgp->mif_ldvid, p_cfgp->ser_ldvid)); |
| |
| |
| NXGE_DEBUG_MSG((nxgep, OBP_CTL, "==> nxge_use_default_dma_config_n2: " |
| "p_cfgp p%p start_ldg %d nxgep->max_ldgs %d", |
| p_cfgp, p_cfgp->start_ldg, p_cfgp->max_ldgs)); |
| |
| /* |
| * RDC groups and the beginning RDC group assigned to this function. |
| */ |
| p_cfgp->max_rdc_grpids = NXGE_MAX_RDC_GROUPS / nxgep->nports; |
| p_cfgp->def_mac_rxdma_grpid = |
| nxgep->function_num * NXGE_MAX_RDC_GROUPS / nxgep->nports; |
| p_cfgp->def_mac_txdma_grpid = |
| nxgep->function_num * NXGE_MAX_TDC_GROUPS / nxgep->nports; |
| |
| if ((p_cfgp->def_mac_rxdma_grpid = nxge_fzc_rdc_tbl_bind(nxgep, |
| p_cfgp->def_mac_rxdma_grpid, B_TRUE)) >= NXGE_MAX_RDC_GRPS) { |
| NXGE_ERROR_MSG((nxgep, CFG_CTL, |
| "nxge_use_default_dma_config_n2(): " |
| "nxge_fzc_rdc_tbl_bind failed")); |
| return (NXGE_DDI_FAILED); |
| } |
| |
| status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip, |
| "rx-rdc-grps", p_cfgp->max_rdc_grpids); |
| if (status) { |
| return (NXGE_DDI_FAILED); |
| } |
| status = ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip, |
| "rx-rdc-grps-begin", p_cfgp->def_mac_rxdma_grpid); |
| if (status) { |
| (void) ddi_prop_remove(DDI_DEV_T_NONE, nxgep->dip, |
| "rx-rdc-grps"); |
| return (NXGE_DDI_FAILED); |
| } |
| NXGE_DEBUG_MSG((nxgep, OBP_CTL, "==> nxge_use_default_dma_config_n2: " |
| "p_cfgp $%p # rdc groups %d start rdc group id %d", |
| p_cfgp, p_cfgp->max_rdc_grpids, |
| p_cfgp->def_mac_rxdma_grpid)); |
| |
| nxgep->intr_timeout = NXGE_RDC_RCR_TIMEOUT; |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, |
| "rxdma-intr-time", (int **)&prop_val, &prop_len) == |
| DDI_PROP_SUCCESS) { |
| if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) { |
| nxgep->intr_timeout = prop_val[0]; |
| (void) ddi_prop_update_int_array(DDI_DEV_T_NONE, |
| nxgep->dip, "rxdma-intr-time", prop_val, prop_len); |
| } |
| ddi_prop_free(prop_val); |
| } |
| |
| nxgep->intr_threshold = NXGE_RDC_RCR_THRESHOLD; |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, |
| "rxdma-intr-pkts", (int **)&prop_val, &prop_len) == |
| DDI_PROP_SUCCESS) { |
| if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) { |
| nxgep->intr_threshold = prop_val[0]; |
| (void) ddi_prop_update_int_array(DDI_DEV_T_NONE, |
| nxgep->dip, "rxdma-intr-pkts", prop_val, prop_len); |
| } |
| ddi_prop_free(prop_val); |
| } |
| |
| nxge_set_hw_dma_config(nxgep); |
| NXGE_DEBUG_MSG((nxgep, OBP_CTL, "<== nxge_use_default_dma_config_n2")); |
| return (status); |
| } |
| |
| static void |
| nxge_use_cfg_dma_config(p_nxge_t nxgep) |
| { |
| int tx_ndmas, rx_ndmas, nrxgp, st_txdma, st_rxdma; |
| p_nxge_dma_pt_cfg_t p_dma_cfgp; |
| p_nxge_hw_pt_cfg_t p_cfgp; |
| dev_info_t *dip; |
| p_nxge_param_t param_arr; |
| char *prop; |
| int *prop_val; |
| uint_t prop_len; |
| int i; |
| uint8_t *ch_arr_p; |
| |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_use_cfg_dma_config")); |
| param_arr = nxgep->param_arr; |
| |
| p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; |
| p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; |
| dip = nxgep->dip; |
| p_cfgp->function_number = nxgep->function_num; |
| prop = param_arr[param_txdma_channels_begin].fcode_name; |
| |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop, |
| &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| p_cfgp->tdc.start = *prop_val; |
| ddi_prop_free(prop_val); |
| } else { |
| switch (nxgep->niu_type) { |
| case NEPTUNE_4_1GC: |
| ch_arr_p = &tx_4_1G[0]; |
| break; |
| case NEPTUNE_2_10GF: |
| ch_arr_p = &tx_2_10G[0]; |
| break; |
| case NEPTUNE_2_10GF_2_1GC: |
| case NEPTUNE_2_10GF_2_1GRF: |
| ch_arr_p = &tx_2_10G_2_1G[0]; |
| break; |
| case NEPTUNE_1_10GF_3_1GC: |
| ch_arr_p = &tx_1_10G_3_1G[0]; |
| break; |
| case NEPTUNE_1_1GC_1_10GF_2_1GC: |
| ch_arr_p = &tx_1_1G_1_10G_2_1G[0]; |
| break; |
| default: |
| switch (nxgep->platform_type) { |
| case P_NEPTUNE_ALONSO: |
| ch_arr_p = &tx_2_10G_2_1G[0]; |
| break; |
| default: |
| ch_arr_p = &p4_tx_equal[0]; |
| break; |
| } |
| break; |
| } |
| st_txdma = 0; |
| for (i = 0; i < nxgep->function_num; i++, ch_arr_p++) |
| st_txdma += *ch_arr_p; |
| |
| (void) ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip, |
| prop, st_txdma); |
| p_cfgp->tdc.start = st_txdma; |
| } |
| |
| prop = param_arr[param_txdma_channels].fcode_name; |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop, |
| &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| tx_ndmas = *prop_val; |
| ddi_prop_free(prop_val); |
| } else { |
| switch (nxgep->niu_type) { |
| case NEPTUNE_4_1GC: |
| tx_ndmas = tx_4_1G[nxgep->function_num]; |
| break; |
| case NEPTUNE_2_10GF: |
| tx_ndmas = tx_2_10G[nxgep->function_num]; |
| break; |
| case NEPTUNE_2_10GF_2_1GC: |
| case NEPTUNE_2_10GF_2_1GRF: |
| tx_ndmas = tx_2_10G_2_1G[nxgep->function_num]; |
| break; |
| case NEPTUNE_1_10GF_3_1GC: |
| tx_ndmas = tx_1_10G_3_1G[nxgep->function_num]; |
| break; |
| case NEPTUNE_1_1GC_1_10GF_2_1GC: |
| tx_ndmas = tx_1_1G_1_10G_2_1G[nxgep->function_num]; |
| break; |
| default: |
| switch (nxgep->platform_type) { |
| case P_NEPTUNE_ALONSO: |
| tx_ndmas = tx_2_10G_2_1G[nxgep->function_num]; |
| break; |
| default: |
| tx_ndmas = p4_tx_equal[nxgep->function_num]; |
| break; |
| } |
| break; |
| } |
| (void) ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip, |
| prop, tx_ndmas); |
| } |
| |
| p_cfgp->tdc.count = tx_ndmas; |
| p_cfgp->tdc.owned = p_cfgp->tdc.count; |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_use_cfg_dma_config: " |
| "p_cfgp 0x%llx max_tdcs %d", p_cfgp, p_cfgp->tdc.count)); |
| |
| prop = param_arr[param_rxdma_channels_begin].fcode_name; |
| |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop, |
| &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| p_cfgp->start_rdc = *prop_val; |
| ddi_prop_free(prop_val); |
| } else { |
| switch (nxgep->niu_type) { |
| case NEPTUNE_4_1GC: |
| ch_arr_p = &rx_4_1G[0]; |
| break; |
| case NEPTUNE_2_10GF: |
| ch_arr_p = &rx_2_10G[0]; |
| break; |
| case NEPTUNE_2_10GF_2_1GC: |
| case NEPTUNE_2_10GF_2_1GRF: |
| ch_arr_p = &rx_2_10G_2_1G[0]; |
| break; |
| case NEPTUNE_1_10GF_3_1GC: |
| ch_arr_p = &rx_1_10G_3_1G[0]; |
| break; |
| case NEPTUNE_1_1GC_1_10GF_2_1GC: |
| ch_arr_p = &rx_1_1G_1_10G_2_1G[0]; |
| break; |
| default: |
| switch (nxgep->platform_type) { |
| case P_NEPTUNE_ALONSO: |
| ch_arr_p = &rx_2_10G_2_1G[0]; |
| break; |
| default: |
| ch_arr_p = &p4_rx_equal[0]; |
| break; |
| } |
| break; |
| } |
| st_rxdma = 0; |
| for (i = 0; i < nxgep->function_num; i++, ch_arr_p++) |
| st_rxdma += *ch_arr_p; |
| |
| (void) ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip, |
| prop, st_rxdma); |
| p_cfgp->start_rdc = st_rxdma; |
| } |
| |
| prop = param_arr[param_rxdma_channels].fcode_name; |
| |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop, |
| &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| rx_ndmas = *prop_val; |
| ddi_prop_free(prop_val); |
| } else { |
| switch (nxgep->niu_type) { |
| case NEPTUNE_4_1GC: |
| rx_ndmas = rx_4_1G[nxgep->function_num]; |
| break; |
| case NEPTUNE_2_10GF: |
| rx_ndmas = rx_2_10G[nxgep->function_num]; |
| break; |
| case NEPTUNE_2_10GF_2_1GC: |
| case NEPTUNE_2_10GF_2_1GRF: |
| rx_ndmas = rx_2_10G_2_1G[nxgep->function_num]; |
| break; |
| case NEPTUNE_1_10GF_3_1GC: |
| rx_ndmas = rx_1_10G_3_1G[nxgep->function_num]; |
| break; |
| case NEPTUNE_1_1GC_1_10GF_2_1GC: |
| rx_ndmas = rx_1_1G_1_10G_2_1G[nxgep->function_num]; |
| break; |
| default: |
| switch (nxgep->platform_type) { |
| case P_NEPTUNE_ALONSO: |
| rx_ndmas = rx_2_10G_2_1G[nxgep->function_num]; |
| break; |
| default: |
| rx_ndmas = p4_rx_equal[nxgep->function_num]; |
| break; |
| } |
| break; |
| } |
| (void) ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip, |
| prop, rx_ndmas); |
| } |
| |
| p_cfgp->max_rdcs = rx_ndmas; |
| |
| /* |
| * RDC groups and the beginning RDC group assigned to this function. |
| * XXX: this may be wrong if prop value is used. |
| */ |
| p_cfgp->def_mac_rxdma_grpid = |
| nxgep->function_num * NXGE_MAX_RDC_GROUPS / nxgep->nports; |
| p_cfgp->def_mac_txdma_grpid = |
| nxgep->function_num * NXGE_MAX_TDC_GROUPS / nxgep->nports; |
| |
| if ((p_cfgp->def_mac_rxdma_grpid = nxge_fzc_rdc_tbl_bind(nxgep, |
| p_cfgp->def_mac_rxdma_grpid, B_TRUE)) >= NXGE_MAX_RDC_GRPS) { |
| NXGE_ERROR_MSG((nxgep, CFG_CTL, |
| "nxge_use_default_dma_config2(): " |
| "nxge_fzc_rdc_tbl_bind failed")); |
| goto nxge_use_cfg_dma_config_exit; |
| } |
| |
| prop = param_arr[param_rx_rdc_grps].fcode_name; |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop, |
| &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| nrxgp = *prop_val; |
| ddi_prop_free(prop_val); |
| } else { |
| nrxgp = NXGE_MAX_RDC_GRPS / nxgep->nports; |
| (void) ddi_prop_update_int(DDI_DEV_T_NONE, nxgep->dip, |
| prop, nrxgp); |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, |
| "==> nxge_use_default_dma_config: " |
| "num_rdc_grpid not found: use def:# of " |
| "rdc groups %d\n", nrxgp)); |
| } |
| p_cfgp->max_rdc_grpids = nrxgp; |
| |
| /* |
| * 2/4 ports have the same hard-wired logical groups assigned. |
| */ |
| p_cfgp->start_ldg = nxgep->function_num * NXGE_LDGRP_PER_4PORTS; |
| p_cfgp->max_ldgs = NXGE_LDGRP_PER_4PORTS; |
| |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_use_default_dma_config: " |
| "p_cfgp 0x%llx max_rdcs %d max_grpids %d default_grpid %d", |
| p_cfgp, p_cfgp->max_rdcs, p_cfgp->max_grpids, |
| p_cfgp->def_mac_rxdma_grpid)); |
| |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_use_cfg_dma_config: " |
| "p_cfgp 0x%016llx start_ldg %d nxgep->max_ldgs %d " |
| "def_mac_rxdma_grpid %d", |
| p_cfgp, p_cfgp->start_ldg, p_cfgp->max_ldgs, |
| p_cfgp->def_mac_rxdma_grpid)); |
| |
| nxgep->intr_timeout = NXGE_RDC_RCR_TIMEOUT; |
| prop = param_arr[param_rxdma_intr_time].fcode_name; |
| |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop, |
| &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) { |
| nxgep->intr_timeout = prop_val[0]; |
| (void) ddi_prop_update_int_array(DDI_DEV_T_NONE, |
| nxgep->dip, prop, prop_val, prop_len); |
| } |
| ddi_prop_free(prop_val); |
| } |
| |
| nxgep->intr_threshold = NXGE_RDC_RCR_THRESHOLD; |
| prop = param_arr[param_rxdma_intr_pkts].fcode_name; |
| |
| if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, prop, |
| &prop_val, &prop_len) == DDI_PROP_SUCCESS) { |
| if ((prop_len > 0) && (prop_len <= p_cfgp->max_rdcs)) { |
| nxgep->intr_threshold = prop_val[0]; |
| (void) ddi_prop_update_int_array(DDI_DEV_T_NONE, |
| nxgep->dip, prop, prop_val, prop_len); |
| } |
| ddi_prop_free(prop_val); |
| } |
| nxge_set_hw_dma_config(nxgep); |
| |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_use_cfg_dma_config: " |
| "sTDC[%d] nTDC[%d] sRDC[%d] nRDC[%d]", |
| p_cfgp->tdc.start, p_cfgp->tdc.count, |
| p_cfgp->start_rdc, p_cfgp->max_rdcs)); |
| |
| nxge_use_cfg_dma_config_exit: |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, "<== nxge_use_cfg_dma_config")); |
| } |
| |
| void |
| nxge_get_logical_props(p_nxge_t nxgep) |
| { |
| nxge_dma_pt_cfg_t *port = &nxgep->pt_config; |
| nxge_hw_pt_cfg_t *hardware; |
| nxge_rdc_grp_t *group; |
| |
| (void) memset(port, 0, sizeof (*port)); |
| |
| port->mac_port = nxgep->function_num; /* := function number */ |
| |
| /* |
| * alloc_buf_size: |
| * dead variables. |
| */ |
| port->rbr_size = nxge_rbr_size; |
| port->rcr_size = nxge_rcr_size; |
| |
| port->tx_dma_map = 0; /* Transmit DMA channel bit map */ |
| |
| nxge_set_rdc_intr_property(nxgep); |
| |
| port->rcr_full_header = NXGE_RCR_FULL_HEADER; |
| port->rx_drr_weight = PT_DRR_WT_DEFAULT_10G; |
| |
| /* ----------------------------------------------------- */ |
| hardware = &port->hw_config; |
| |
| (void) memset(hardware, 0, sizeof (*hardware)); |
| |
| /* |
| * partition_id, read_write_mode: |
| * dead variables. |
| */ |
| |
| /* |
| * drr_wt, rx_full_header, *_ldg?, start_mac_entry, |
| * mac_pref, def_mac_rxdma_grpid, start_vlan, max_vlans, |
| * start_ldgs, max_ldgs, max_ldvs, |
| * vlan_pref, def_vlan_rxdma_grpid are meaningful only |
| * in the service domain. |
| */ |
| |
| group = &port->rdc_grps[0]; |
| |
| group->flag = B_TRUE; /* configured */ |
| group->config_method = RDC_TABLE_ENTRY_METHOD_REP; |
| group->port = NXGE_GET_PORT_NUM(nxgep->function_num); |
| |
| /* HIO futures: this is still an open question. */ |
| hardware->max_macs = 1; |
| } |
| |
| static void |
| nxge_use_cfg_vlan_class_config(p_nxge_t nxgep) |
| { |
| uint_t vlan_cnt; |
| int *vlan_cfg_val; |
| int status; |
| p_nxge_param_t param_arr; |
| char *prop; |
| |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_use_cfg_vlan_config")); |
| param_arr = nxgep->param_arr; |
| prop = param_arr[param_vlan_2rdc_grp].fcode_name; |
| |
| status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop, |
| &vlan_cfg_val, &vlan_cnt); |
| if (status == DDI_PROP_SUCCESS) { |
| status = ddi_prop_update_int_array(DDI_DEV_T_NONE, |
| nxgep->dip, prop, vlan_cfg_val, vlan_cnt); |
| ddi_prop_free(vlan_cfg_val); |
| } |
| nxge_set_hw_vlan_class_config(nxgep); |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_use_cfg_vlan_config")); |
| } |
| |
| static void |
| nxge_use_cfg_mac_class_config(p_nxge_t nxgep) |
| { |
| p_nxge_dma_pt_cfg_t p_dma_cfgp; |
| p_nxge_hw_pt_cfg_t p_cfgp; |
| uint_t mac_cnt; |
| int *mac_cfg_val; |
| int status; |
| p_nxge_param_t param_arr; |
| char *prop; |
| |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_use_cfg_mac_class_config")); |
| p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; |
| p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; |
| p_cfgp->start_mac_entry = 0; |
| param_arr = nxgep->param_arr; |
| prop = param_arr[param_mac_2rdc_grp].fcode_name; |
| |
| switch (nxgep->function_num) { |
| case 0: |
| case 1: |
| /* 10G ports */ |
| p_cfgp->max_macs = NXGE_MAX_MACS_XMACS; |
| break; |
| case 2: |
| case 3: |
| /* 1G ports */ |
| default: |
| p_cfgp->max_macs = NXGE_MAX_MACS_BMACS; |
| break; |
| } |
| |
| p_cfgp->mac_pref = 1; |
| NXGE_DEBUG_MSG((nxgep, OBP_CTL, |
| "== nxge_use_cfg_mac_class_config: " |
| " mac_pref bit set def_mac_rxdma_grpid %d", |
| p_cfgp->def_mac_rxdma_grpid)); |
| |
| status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxgep->dip, 0, prop, |
| &mac_cfg_val, &mac_cnt); |
| if (status == DDI_PROP_SUCCESS) { |
| if (mac_cnt <= p_cfgp->max_macs) |
| status = ddi_prop_update_int_array(DDI_DEV_T_NONE, |
| nxgep->dip, prop, mac_cfg_val, mac_cnt); |
| ddi_prop_free(mac_cfg_val); |
| } |
| nxge_set_hw_mac_class_config(nxgep); |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_use_cfg_mac_class_config")); |
| } |
| |
| static void |
| nxge_use_cfg_class_config(p_nxge_t nxgep) |
| { |
| nxge_set_hw_class_config(nxgep); |
| } |
| |
| static void |
| nxge_set_rdc_intr_property(p_nxge_t nxgep) |
| { |
| int i; |
| p_nxge_dma_pt_cfg_t p_dma_cfgp; |
| |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, " ==> nxge_set_rdc_intr_property")); |
| p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; |
| |
| for (i = 0; i < NXGE_MAX_RDCS; i++) { |
| p_dma_cfgp->rcr_timeout[i] = nxgep->intr_timeout; |
| p_dma_cfgp->rcr_threshold[i] = nxgep->intr_threshold; |
| } |
| |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, " <== nxge_set_rdc_intr_property")); |
| } |
| |
| static void |
| nxge_set_hw_dma_config(p_nxge_t nxgep) |
| { |
| int i, j, ngrps, bitmap, end, st_rdc; |
| p_nxge_dma_pt_cfg_t p_dma_cfgp; |
| p_nxge_hw_pt_cfg_t p_cfgp; |
| p_nxge_rdc_grp_t rdc_grp_p; |
| p_nxge_tdc_grp_t tdc_grp_p; |
| nxge_grp_t *group; |
| uint8_t nrdcs; |
| dc_map_t map = 0; |
| |
| NXGE_DEBUG_MSG((nxgep, CFG_CTL, "==> nxge_set_hw_dma_config")); |
| |
| p_dma_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; |
| p_cfgp = (p_nxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config; |
| |
| switch (nxgep->niu_type) { |
| case NEPTUNE_4_1GC: |
| case NEPTUNE_2_10GF_2_1GC: |
| case NEPTUNE_1_10GF_3_1GC: |
| case NEPTUNE_1_1GC_1_10GF_2_1GC: |
| case NEPTUNE_2_10GF_2_1GRF: |
| default: |
| ngrps = 2; |
| break; |
| case NEPTUNE_2_10GF: |
| case NEPTUNE_2_1GRF: |
| case N2_NIU: |
| ngrps = 4; |
| break; |
| } |
| |
| /* |
| * Setup TDC groups |
| */ |
| bitmap = 0; |
| end = p_cfgp->tdc.start + p_cfgp->tdc.owned; |
| for (i = p_cfgp->tdc.start; i < end; i++) { |
| bitmap |= (1 << i); |
| } |
| |
| nxgep->tx_set.owned.map |= bitmap; /* Owned, & not shared. */ |
| nxgep->tx_set.owned.count = p_cfgp->tdc.owned; |
| p_dma_cfgp->tx_dma_map = bitmap; |
| |
| for (i = 0; i < ngrps; i++) { |
| group = (nxge_grp_t *)nxge_grp_add(nxgep, |
| NXGE_TRANSMIT_GROUP); |
| tdc_grp_p = &p_dma_cfgp->tdc_grps[ |
| p_cfgp->def_mac_txdma_grpid + i]; |
| if (i == 0) |
| tdc_grp_p->map = bitmap; |
| else |
| tdc_grp_p->map = 0; |
| /* no ring is associated with a group initially */ |
| tdc_grp_p->start_tdc = 0; |
| tdc_grp_p->max_tdcs = 0; |
| tdc_grp_p->grp_index = group->index; |
| } |
| |
| /* |
| * Setup RDC groups |
| */ |
| st_rdc = p_cfgp->start_rdc; |
| for (i = 0; i < ngrps; i++) { |
| /* |
| * All rings are associated with the default group initially |
| */ |
| if (i == 0) { |
| /* default group */ |
| switch (nxgep->niu_type) { |
| case NEPTUNE_4_1GC: |
| nrdcs = rx_4_1G[nxgep->function_num]; |
| break; |
| case N2_NIU: |
| case NEPTUNE_2_10GF: |
| nrdcs = rx_2_10G[nxgep->function_num]; |
| break; |
| case NEPTUNE_2_10GF_2_1GC: |
| nrdcs = rx_2_10G_2_1G[nxgep->function_num]; |
| break; |
| case NEPTUNE_1_10GF_3_1GC: |
| nrdcs = rx_1_10G_3_1G[nxgep->function_num]; |
| break; |
| case NEPTUNE_1_1GC_1_10GF_2_1GC: |
| nrdcs = rx_1_1G_1_10G_2_1G[nxgep->function_num]; |
| break; |
| default: |
| switch (nxgep->platform_type) { |
| case P_NEPTUNE_ALONSO: |
| nrdcs = |
| rx_2_10G_2_1G[nxgep->function_num]; |
| break; |
| default: |
| nrdcs = rx_4_1G[nxgep->function_num]; |
| break; |
| } |
| break; |
| } |
| |
| if (p_cfgp->max_rdcs < nrdcs) |
| nrdcs = p_cfgp->max_rdcs; |
| } else { |
| nrdcs = 0; |
| } |
| |
| rdc_grp_p = &p_dma_cfgp->rdc_grps[ |
| p_cfgp->def_mac_rxdma_grpid + i]; |
| rdc_grp_p->start_rdc = st_rdc; |
| rdc_grp_p->max_rdcs = nrdcs; |
| rdc_grp_p->def_rdc = rdc_grp_p->start_rdc; |
| |
| /* default to: 0, 1, 2, 3, ...., 0, 1, 2, 3.... */ |
| if (nrdcs != 0) { |
| for (j = 0; j < nrdcs; j++) { |
| map |= (1 << j); |
| } |
| map <<= rdc_grp_p->start_rdc; |
| } else |
| map = 0; |
| rdc_grp_p->map = map; |
| |
| nxgep->rx_set.owned.map |= map; |