nxge_virtual.c revision 4ba491f53199ecfd5a928fdce7dc8f8aa9de4b9e
/*
* 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
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* 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_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);
uint8_t, int *);
static void nxge_set_rdc_intr_property(p_nxge_t);
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;
typedef enum {
DEFAULT = 0,
FAIR,
static char *token_names[] = {
"default",
"equal",
"fair",
"custom",
"classify",
"l2_classify",
"l3_distribute",
"l3_classify",
"l3_tcam",
"none",
};
void
{
(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_fflp_dump_regs(handle);
}
/*
* 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.
*/
{
int instance;
#ifndef NXGE_SHARED_REG_SW_SIM
#endif
"nxge_cntlops: nxge_list null"));
return (NXGE_ERROR);
}
"nxge_cntlops: nxgep null"));
return (NXGE_ERROR);
}
#ifndef NXGE_SHARED_REG_SW_SIM
#endif
switch (ctlop) {
case NXGE_CTLOPS_NIUTYPE:
return (status);
#ifdef NXGE_SHARED_REG_SW_SIM
return (0);
#else
"nxge_cntlops: NXGE_CTLOPS_GET_SHARED_REG"));
return (0);
#endif
#ifdef NXGE_SHARED_REG_SW_SIM
return (0);
#else
while (status != NPI_SUCCESS)
"nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG"));
return (0);
#endif
#ifdef NXGE_SHARED_REG_SW_SIM
return (0);
#else
while (status != NPI_SUCCESS)
"nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG"));
return (0);
#endif
#ifdef NXGE_SHARED_REG_SW_SIM
return (0);
#else
"nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG"));
return (0);
#endif
#ifdef NXGE_SHARED_REG_SW_SIM
return (0);
#else
while (status != NPI_SUCCESS)
"nxge_cntlops: NXGE_CTLOPS_SET_SHARED_REG"));
return (0);
#endif
#ifdef NXGE_SHARED_REG_SW_SIM
return (0);
#else
while (status != NPI_SUCCESS)
"nxge_cntlops: NXGE_CTLOPS_GET_LOCK_BLOCK"));
return (0);
#endif
case NXGE_CTLOPS_GET_LOCK_TRY:
#ifdef NXGE_SHARED_REG_SW_SIM
return (0);
#else
"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
return (0);
#else
"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
{
#if defined(NXGE_SHARE_REG_SW_SIM)
return;
#endif
while (status != NPI_SUCCESS)
}
void
{
#if defined(NXGE_SHARE_REG_SW_SIM)
return;
#endif
(void) npi_dev_func_sr_lock_free(handle);
}
static void
{
&prop_len) == DDI_PROP_SUCCESS) {
}
}
}
static config_token_t
nxge_get_config_token(char *prop)
{
while (token < CONFIG_TOKEN_NONE) {
break;
token++;
}
return (token);
}
/* per port */
static nxge_status_t
dev_info_t *s_dip[])
{
int ddi_status;
int custom_start_grp[MAX_SIBLINGS];
int custom_num_grp[MAX_SIBLINGS];
start_grp = 0;
switch (token) {
case FAIR:
cfg_prop = "fair";
(num_ports == 4) ?
}
break;
case EQUAL:
cfg_prop = "equal";
(num_ports == 4) ?
}
break;
case CLASSIFY:
cfg_prop = "classify";
}
break;
case CUSTOM:
cfg_prop = "custom";
/* See if it is good config */
num_grps = 0;
(custom_start_grp[port] >=
bad_config = B_TRUE;
break;
}
num_prop, -1);
(custom_num_grp[port] >
((custom_num_grp[port] +
custom_start_grp[port]) >=
bad_config = B_TRUE;
break;
}
if (num_grps > NXGE_MAX_RDC_GRPS) {
bad_config = B_TRUE;
break;
}
grp_bitmap[port] = 0;
for (bits = 0;
bits++) {
grp_bitmap[port] |=
}
}
if (bad_config == B_FALSE) {
/* check for overlap */
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 */
(num_ports == 4) ?
}
}
break;
default:
/* use default config */
cfg_prop = "fair";
}
break;
}
/* Now Update the rx properties */
"rxdma-grp-cfg", cfg_prop);
if (ddi_status != DDI_PROP_SUCCESS) {
" property %s not updating",
cfg_prop));
}
if (ddi_status != DDI_PROP_SUCCESS) {
" property %s not updating",
num_prop));
}
if (ddi_status != DDI_PROP_SUCCESS) {
" property %s not updating",
start_prop));
}
}
if (status & NXGE_DDI_FAILED)
status |= NXGE_ERROR;
return (status);
}
static nxge_status_t
dev_info_t *s_dip[])
{
int ddi_status;
int custom_start_rdc[MAX_SIBLINGS];
int custom_num_rdc[MAX_SIBLINGS];
int *prop_val;
start_rdc = 0;
switch (token) {
case FAIR:
cfg_prop = "fair";
}
break;
case EQUAL:
cfg_prop = "equal";
p4_rx_equal[port] :
}
break;
case CUSTOM:
cfg_prop = "custom";
/* See if it is good config */
num_rdc = 0;
&prop_val,
&prop_len);
if (ddi_status == DDI_SUCCESS)
else {
" %s custom start port %d"
" read failed ",
" rxdma-cfg", port));
bad_config = B_TRUE;
}
(custom_start_rdc[port] >=
NXGE_MAX_RDCS)) {
" %s custom start %d"
" out of range %x ",
" rxdma-cfg",
port,
custom_start_rdc[port]));
bad_config = B_TRUE;
break;
}
0,
&prop_val,
&prop_len);
if (ddi_status == DDI_SUCCESS)
else {
" %s custom num port %d"
" read failed ",
"rxdma-cfg", port));
bad_config = B_TRUE;
}
(custom_num_rdc[port] >
NXGE_MAX_RDCS) ||
((custom_num_rdc[port] +
custom_start_rdc[port]) >
NXGE_MAX_RDCS)) {
" %s custom num %d"
" out of range %x ",
" rxdma-cfg",
bad_config = B_TRUE;
break;
}
if (num_rdc > NXGE_MAX_RDCS) {
bad_config = B_TRUE;
break;
}
rdc_bitmap[port] = 0;
for (bits = 0;
rdc_bitmap[port] |=
}
}
if (bad_config == B_FALSE) {
/* check for overlap */
if (rdc_bitmap[port] &
rdc_bitmap[j]) {
" 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 */
" rxdma-cfg property:"
" bad custom config:"
" use default"));
(num_ports == 4) ?
p4_rx_fair[port] :
}
}
break;
default:
/* use default config */
cfg_prop = "fair";
}
break;
}
/* Now Update the rx properties */
" update property rxdma-cfg with %s ", cfg_prop));
"rxdma-cfg", cfg_prop);
if (ddi_status != DDI_PROP_SUCCESS) {
" property rxdma-cfg is not updating to %s",
cfg_prop));
}
if (ddi_status != DDI_PROP_SUCCESS) {
" property %s not updating with %d",
}
if (ddi_status != DDI_PROP_SUCCESS) {
" property %s not updating with %d ",
}
}
if (status & NXGE_DDI_FAILED)
status |= NXGE_ERROR;
return (status);
}
static nxge_status_t
dev_info_t *s_dip[])
{
int ddi_status = DDI_SUCCESS;
int custom_start_tdc[MAX_SIBLINGS];
int custom_num_tdc[MAX_SIBLINGS];
int *prop_val;
start_tdc = 0;
switch (token) {
case FAIR:
cfg_prop = "fair";
}
break;
case EQUAL:
cfg_prop = "equal";
}
break;
case CUSTOM:
cfg_prop = "custom";
/* See if it is good config */
num_tdc = 0;
if (ddi_status == DDI_SUCCESS)
else {
" %s custom start port %d"
bad_config = B_TRUE;
}
(custom_start_tdc[port] >=
NXGE_MAX_RDCS)) {
" %s custom start %d"
" out of range %x ", " txdma-cfg",
bad_config = B_TRUE;
break;
}
if (ddi_status == DDI_SUCCESS)
else {
" %s custom num port %d"
bad_config = B_TRUE;
}
(custom_num_tdc[port] >
NXGE_MAX_TDCS) ||
((custom_num_tdc[port] +
custom_start_tdc[port]) >
NXGE_MAX_TDCS)) {
" %s custom num %d"
" out of range %x ", " rxdma-cfg",
bad_config = B_TRUE;
break;
}
if (num_tdc > NXGE_MAX_TDCS) {
bad_config = B_TRUE;
break;
}
tdc_bitmap[port] = 0;
for (bits = 0;
tdc_bitmap[port] |=
(1 <<
}
}
if (bad_config == B_FALSE) {
/* check for overlap */
if (tdc_bitmap[port] &
tdc_bitmap[j]) {
" 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 */
" txdma-cfg property:"
" bad custom config:" " use default"));
}
}
break;
default:
/* use default config */
cfg_prop = "fair";
}
break;
}
/* Now Update the tx properties */
" update property txdma-cfg with %s ", cfg_prop));
"txdma-cfg", cfg_prop);
if (ddi_status != DDI_PROP_SUCCESS) {
" property txdma-cfg is not updating to %s",
cfg_prop));
}
if (ddi_status != DDI_PROP_SUCCESS) {
" property %s not updating with %d",
custom_num_tdc[port]));
}
if (ddi_status != DDI_PROP_SUCCESS) {
" property %s not updating with %d ",
}
}
if (status & NXGE_DDI_FAILED)
status |= NXGE_ERROR;
return (status);
}
static nxge_status_t
{
switch (flags) {
case COMMON_TXDMA_CFG:
if (nxge_dma_obp_props_only == 0)
break;
case COMMON_RXDMA_CFG:
if (nxge_dma_obp_props_only == 0)
break;
case COMMON_RXDMA_GRP_CFG:
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.
*/
{
int ddi_status = DDI_SUCCESS;
int *cfg_val;
#ifdef NXGE_DEBUG_ERROR
if (ddi_status != DDI_PROP_SUCCESS)
" property %s failed update ", prop));
#endif
}
if (ddi_status != DDI_PROP_SUCCESS)
return (NXGE_ERROR | NXGE_DDI_FAILED);
}
cfg_value[i] = known_cfg_value;
&prop_len) == DDI_PROP_SUCCESS) {
found++;
}
}
if (found != i) {
" property %s not specified on all ports", prop));
if (found == 0) {
/* not specified: Use default */
" property %s not specified on any port:"
" Using default", prop));
} else {
/* specified on some */
" property %s not specified"
" on some ports: Using default", prop));
/* ? use p0 value instead ? */
}
} else {
/* check type and consistence */
/* found on all devices */
for (i = 1; i < found; i++) {
" property %s inconsistent:"
" Using default", prop));
break;
}
/*
* Found on all the ports and consistent. Nothing to
* do.
*/
}
}
if (update_prop == B_TRUE) {
#ifdef NXGE_DEBUG_ERROR
if (ddi_status != DDI_SUCCESS)
" property %s not updating with %d"
" Using default",
#endif
if (ddi_status != DDI_PROP_SUCCESS)
}
}
if (status & NXGE_DDI_FAILED)
status |= NXGE_ERROR;
return (status);
}
static uint64_t
{
int start_prop;
/* update the properties per quick config */
switch (rx_quick_cfg) {
case CFG_L3_WEB:
case CFG_L3_DISTRIBUTE:
break;
default:
break;
}
return (cfg_value);
}
static nxge_status_t
{
char *prop_name;
/* update the properties per quick config */
if (rx_quick_cfg == CFG_NOT_SPECIFIED)
/*
* 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)
*
*/
}
/*
* these properties do not affect the actual classification outcome.
*
* fcram_access_ratio, tcam_access_ratio, tcam_enable, llc_snap_enable
*
*/
for (class_prop = param_fcram_access_ratio;
}
return (status);
}
{
int i = 0, found = 0;
int num_siblings;
char *prop_val[MAX_SIBLINGS];
char *prop;
return (NXGE_OK);
num_siblings = 0;
while (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:
return (status);
default:
return (NXGE_ERROR);
}
i = 0;
while (i < num_siblings) {
(char **)&prop_val[i]) == DDI_PROP_SUCCESS) {
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 */
" property %s not specified on any port:"
" Using default", prop));
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 */
" property %s not specified on some ports:"
" Using default", prop));
return (status);
}
}
/* check type and consistence */
/* found on all devices */
for (i = 1; i < found; i++) {
" property %s inconsistent:"
" Using default", prop));
return (status);
}
}
/*
* Found on all the ports check if it is custom configuration. if
* custom, then verify consistence
*
* finally create soft properties
*/
return (status);
}
{
int ddi_status = DDI_SUCCESS;
char *prop_val;
char *rx_prop;
char *prop;
prop = "rx-quick-cfg";
/*
* good value are
*
* "web-server" "generic-server" "l3-classify" "flow-classify"
*/
" property %s not specified: using default ", prop));
} else {
" %s: web server ", prop));
}
" %s: distribute ", prop));
}
/* more */
}
if (ddi_status != DDI_PROP_SUCCESS)
/* now handle specified cases: */
if (status & NXGE_DDI_FAILED)
status |= NXGE_ERROR;
return (status);
}
/*
* Device properties adv-autoneg-cap etc are defined by FWARC
*/
static void
{
int *prop_val;
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;
/*
* first find out the card type and the supported link speeds and
* features
*/
/* add code for card type */
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
speed = 10000;
speed = 1000;
speed = 100;
speed = 10;
speed = 0;
} else {
"speed property is invalid reverting to auto"));
speed = 0;
}
} else
speed = 0;
duplex = 2;
duplex = 1;
duplex = 0;
} else {
"duplex property is invalid"
" reverting to auto"));
duplex = 0;
}
} else
duplex = 0;
/* speed == 0 or duplex == 0 means auto negotiation. */
if (adv_autoneg_cap == 0) {
} else if (speed == 0) {
}
if (duplex == 0) {
adv_10gfdx_cap = (speed == 0);
}
if (status)
return;
if (status)
if (status)
if (status)
if (status)
if (status)
if (status)
if (status)
if (status)
return;
}
{
" nxge_get_config_properties:"
return (NXGE_ERROR);
}
/*
* Get info on how many ports Neptune card has.
*/
"<==nxge_get_config_properties: Invalid Neptune type 0x%x",
return (NXGE_ERROR);
}
if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
}
return (NXGE_ERROR);
}
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.
*
*/
case N2_NIU:
" ==> nxge_get_config_properties: N2"));
}
break;
default:
if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
" nxge_get_config_properties:"
return (NXGE_ERROR);
}
" ==> nxge_get_config_properties: Neptune"));
}
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.
*/
"nxge_get_config_properties: software lso %d\n",
nxgep->soft_lso_enable));
return (status);
}
static nxge_status_t
{
" ==> 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);
return (status);
}
static void
{
(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);
}
/*
* FWARC 2006/556 for N2 NIU. Get the properties
* from the prom.
*/
static nxge_status_t
{
int ndmas;
int *prop_val;
int i;
"tx-dma-channels", (int **)&prop_val,
&prop_len) == DDI_PROP_SUCCESS) {
if (prop_len != NXGE_NIU_TDMA_PROP_LEN) {
"==> nxge_use_default_dma_config_n2: "
"get tx-dma-channels failed"));
return (NXGE_DDI_FAILED);
} else {
"==> nxge_use_default_dma_config_n2: tdc starts %d "
"==> nxge_use_default_dma_config_n2: #tdc %d (#%d)",
}
} else {
"==> nxge_use_default_dma_config_n2: "
"get tx-dma-channels failed"));
return (NXGE_DDI_FAILED);
}
"p_cfgp 0x%llx max_tdcs %d start %d",
/* Receive DMA */
"rx-dma-channels", (int **)&prop_val,
&prop_len) == DDI_PROP_SUCCESS) {
if (prop_len != NXGE_NIU_TDMA_PROP_LEN) {
"==> nxge_use_default_dma_config_n2: "
"get rx-dma-channels failed"));
return (NXGE_DDI_FAILED);
} else {
"==> nxge_use_default_dma_config_n2(obp):"
" rdc start %d (#%d)",
"==> nxge_use_default_dma_config_n2(obp): "
}
} else {
"==> nxge_use_default_dma_config_n2: "
"get rx-dma-channel failed"));
return (NXGE_DDI_FAILED);
}
/* Hypervisor: rdc # and group # use the same # !! */
"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)) {
"==> 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_use_default_dma_config_n2(obp): "
"# interrupts %d", prop_len));
switch (func) {
case 0:
break;
case 1:
break;
default:
break;
}
return (status);
for (i = 0; i < prop_len; i++) {
"==> nxge_use_default_dma_config_n2(obp): "
"F%d: interrupt #%d, ldg %d",
}
"==> nxge_use_default_dma_config_n2(obp): %d "
"(#%d) maxgrpids %d channel starts %d",
p_cfgp->ldg_chn_start));
} else {
"==> nxge_use_default_dma_config_n2: "
"get interrupts failed"));
return (NXGE_DDI_FAILED);
}
"==> 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%p start_ldg %d nxgep->max_ldgs %d",
/*
* RDC groups and the beginning RDC group assigned to this function.
*/
"nxge_use_default_dma_config_n2(): "
"nxge_fzc_rdc_tbl_bind failed"));
return (NXGE_DDI_FAILED);
}
if (status) {
return (NXGE_DDI_FAILED);
}
if (status) {
"rx-rdc-grps");
return (NXGE_DDI_FAILED);
}
"p_cfgp $%p # rdc groups %d start rdc group id %d",
}
}
}
}
return (status);
}
static void
{
char *prop;
int *prop_val;
int i;
} else {
case NEPTUNE_4_1GC:
break;
case NEPTUNE_2_10GF:
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;
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;
}
} else {
case NEPTUNE_4_1GC:
break;
case NEPTUNE_2_10GF:
break;
case NEPTUNE_2_10GF_2_1GC:
case NEPTUNE_2_10GF_2_1GRF:
break;
case NEPTUNE_1_10GF_3_1GC:
break;
break;
default:
switch (nxgep->platform_type) {
case P_NEPTUNE_ALONSO:
break;
default:
break;
}
break;
}
}
} else {
case NEPTUNE_4_1GC:
break;
case NEPTUNE_2_10GF:
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;
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;
}
} else {
case NEPTUNE_4_1GC:
break;
case NEPTUNE_2_10GF:
break;
case NEPTUNE_2_10GF_2_1GC:
case NEPTUNE_2_10GF_2_1GRF:
break;
case NEPTUNE_1_10GF_3_1GC:
break;
break;
default:
switch (nxgep->platform_type) {
case P_NEPTUNE_ALONSO:
break;
default:
break;
}
break;
}
}
/*
* RDC groups and the beginning RDC group assigned to this function.
* XXX: this may be wrong if prop value is used.
*/
"nxge_use_default_dma_config2(): "
"nxge_fzc_rdc_tbl_bind failed"));
}
} else {
"==> nxge_use_default_dma_config: "
"num_rdc_grpid not found: use def:# of "
"rdc groups %d\n", nrxgp));
}
/*
* 2/4 ports have the same hard-wired logical groups assigned.
*/
"p_cfgp 0x%llx max_rdcs %d max_grpids %d default_grpid %d",
"p_cfgp 0x%016llx start_ldg %d nxgep->max_ldgs %d "
"def_mac_rxdma_grpid %d",
}
}
}
}
"sTDC[%d] nTDC[%d] sRDC[%d] nRDC[%d]",
}
void
{
/*
* alloc_buf_size:
* dead variables.
*/
/* ----------------------------------------------------- */
/*
* 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.
*/
/* HIO futures: this is still an open question. */
}
static void
{
int *vlan_cfg_val;
int status;
char *prop;
&vlan_cfg_val, &vlan_cnt);
if (status == DDI_PROP_SUCCESS) {
}
}
static void
{
int *mac_cfg_val;
int status;
char *prop;
p_cfgp->start_mac_entry = 0;
switch (nxgep->function_num) {
case 0:
case 1:
/* 10G ports */
break;
case 2:
case 3:
/* 1G ports */
default:
break;
}
"== nxge_use_cfg_mac_class_config: "
" mac_pref bit set def_mac_rxdma_grpid %d",
&mac_cfg_val, &mac_cnt);
if (status == DDI_PROP_SUCCESS) {
}
}
static void
{
}
static void
{
int i;
for (i = 0; i < NXGE_MAX_RDCS; i++) {
}
}
static void
{
case NEPTUNE_4_1GC:
case NEPTUNE_2_10GF_2_1GC:
case NEPTUNE_1_10GF_3_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;
bitmap |= (1 << i);
}
for (i = 0; i < ngrps; i++) {
p_cfgp->def_mac_txdma_grpid + i];
if (i == 0)
else
/* no ring is associated with a group initially */
}
for (i = 0; i < NXGE_MAX_RDCS; i++) {
}
/*
* Setup RDC groups
*/
for (i = 0; i < ngrps; i++) {
/*
* All rings are associated with the default group initially
*/
if (i == 0) {
/* default group */
case NEPTUNE_4_1GC:
break;
case N2_NIU:
case NEPTUNE_2_10GF:
break;
case NEPTUNE_2_10GF_2_1GC:
break;
case NEPTUNE_1_10GF_3_1GC:
break;
break;
default:
switch (nxgep->platform_type) {
case P_NEPTUNE_ALONSO:
nrdcs =
break;
default:
break;
}
break;
}
} else {
nrdcs = 0;
}
p_cfgp->def_mac_rxdma_grpid + i];
/* default to: 0, 1, 2, 3, ...., 0, 1, 2, 3.... */
if (nrdcs != 0) {
for (j = 0; j < nrdcs; j++) {
map |= (1 << j);
}
} else
map = 0;
map = 0;
}
/* default RDC */
/* full 18 byte header ? */
}
{
/* Receive DMA Channels */
return (status);
}
{
return (status);
}
{
" ==> nxge_check_rxdma_rdcgrp_member"));
}
" <== nxge_check_rxdma_rdcgrp_member"));
return (status);
}
{
return (status);
}
static void
{
int i;
int *vlan_cfg_val;
char *prop;
int good_count = 0;
/*
* By default, VLAN to RDC group mapping is disabled Need to read HW or
* .conf properties to find out if mapping is required
*
* Format
*
* uint32_t array, each array entry specifying the VLAN id and the
* mapping
*
* bit[30] = add bit[29] = remove bit[28] = preference bits[23-16] =
* rdcgrp bits[15-0] = VLAN ID ( )
*/
for (i = 0; i < NXGE_MAX_VLANS; i++) {
}
for (i = 0; i < vlan_cnt; i++) {
p_cfgp->max_rdc_grpids) &&
" nxge_vlan_config mapping"
" id %d grp %d",
good_count++;
}
}
if (good_count != vlan_cnt) {
}
}
}
static void
{
int i;
int *mac_cfg_val;
char *prop;
int good_count = 0;
int good_cfg[NXGE_MAX_MACS];
for (i = 0; i < NXGE_MAX_MACS; i++) {
}
for (i = 0; i < mac_cnt; i++) {
p_cfgp->max_rdc_grpids) &&
" nxge_mac_config mapping"
" id %d grp %d",
good_count++;
}
}
if (good_count != mac_cnt) {
}
}
}
static void
{
int i;
int *int_prop_val;
char *prop;
int start_prop, end_prop;
int start_class, j = 0;
for (i = start_prop, j = 0; i <= end_prop; i++, j++) {
0, prop, &int_prop_val,
&prop_cnt) == DDI_PROP_SUCCESS) {
} else {
}
}
} else {
}
} else {
}
}
{
if (!*navail_p) {
*nrequired_p = 0;
"<== nxge_ldgv_init:no avail"));
return (NXGE_ERROR);
}
/*
*/
if (!maxldgs) {
/* No devices configured. */
"no logical groups configured."));
return (NXGE_ERROR);
} else {
}
/*
* If function zero instance, it needs to handle the system and MIF
*/
if (func == 0) {
"nxge_ldgv_init_n2: func 0, ERR ID not set!"));
}
/* MIF interrupt */
"nxge_ldgv_init_n2: func 0, MIF ID not set!"));
}
}
/*
* Assume single partition, each function owns mac.
*/
if (!nxge_use_partition)
} else {
}
"==> nxge_ldgv_init_n2: maxldvs %d maxldgs %d",
/* logical start_ldg is ldv */
for (i = 0; i < maxldgs; i++) {
"==> nxge_ldgv_init_n2: maxldvs %d maxldgs %d "
"ldg %d ldgptr $%p",
ptr++;
}
nldvs = 0;
*nrequired_p = 0;
/*
* logical device group table is organized in the following order (same
* as what interrupt property has). function 0: owns MAC, MIF, error,
* rx, tx. function 1: owns MAC, rx, tx.
*/
/* Each function should own MAC interrupt */
ldvp->ldv_ldf_masks = 0;
"==> nxge_ldgv_init_n2(mac): maxldvs %d ldv %d "
"ldg %d ldgptr $%p ldvptr $%p",
nldvs++;
}
ldvp->ldv_ldf_masks = 0;
"==> nxge_ldgv_init_n2(mif): maxldvs %d ldv %d "
"ldg %d ldgptr $%p ldvptr $%p",
nldvs++;
}
/*
* HW based syserr interrupt for port0, and SW based syserr interrupt
* for port1
*/
/*
* Unmask the system interrupt states.
*/
ldvp->ldv_ldf_masks = 0;
"==> nxge_ldgv_init_n2(syserr): maxldvs %d ldv %d "
"ldg %d ldgptr $%p ldvptr p%p",
nldvs++;
} else {
/*
* SW based: allocate the ldv for the syserr since the vector
* should not be consumed for port1
*/
sysldvp->ldv_ldf_masks = 0;
}
"(before rx) func %d nldvs %d navail %d nrequired %d",
/*
* Start with RDC to configure logical devices for each group.
*/
ldvp->ldv_ldf_masks = 0;
"==> nxge_ldgv_init_n2(rx%d): maxldvs %d ldv %d "
"ldg %d ldgptr 0x%016llx ldvptr 0x%016llx",
nldvs++;
chn_start++;
}
}
"func %d nldvs %d navail %d nrequired %d",
"func %d nldvs %d navail %d nrequired %d ldgp 0x%llx "
"ldvp 0x%llx",
/*
* Transmit DMA channels.
*/
ldvp->ldv_ldf_masks = 0;
"==> nxge_ldgv_init_n2(tx%d): maxldvs %d ldv %d "
"ldg %d ldgptr %p ldvptr %p",
nldvs++;
chn_start++;
}
}
"func %d nldvs %d maxgrps %d navail %d nrequired %d",
return (status);
}
/*
* Interrupts related interface functions.
*/
{
if (!*navail_p) {
*nrequired_p = 0;
"<== nxge_ldgv_init:no avail"));
return (NXGE_ERROR);
}
/*
* If function zero instance, it needs to handle the system error
* interrupts.
*/
if (func == 0) {
nldvs++;
} else {
/* use timer */
nldvs++;
}
/*
* Assume single partition, each function owns mac.
*/
if (!nxge_use_partition) {
/* mac */
nldvs++;
/* MIF */
nldvs++;
}
/* No devices configured. */
"no logical devices or groups configured."));
return (NXGE_ERROR);
}
KM_SLEEP);
KM_SLEEP);
}
"==> nxge_ldgv_init: maxldvs %d maxldgs %d nldvs %d",
for (i = 0; i < maxldgs; i++) {
"==> nxge_ldgv_init: maxldvs %d maxldgs %d ldg %d",
ptr++;
}
} else {
}
/*
* Receive DMA channels.
*/
nldvs = 0;
*nrequired_p = 0;
/*
* Start with RDC to configure logical devices for each group.
*/
/* For now, <channel & <vdma_index> are the same. */
ldvp->ldv_ldf_masks = 0;
nldvs++;
}
}
/*
* Transmit DMA channels.
*/
/* For now, <channel & <vdma_index> are the same. */
ldvp->ldv_ldf_masks = 0;
nldvs++;
}
}
if (own_fzc) {
ldv = NXGE_MIF_LD;
ldvp->ldv_ldf_masks = 0;
nldvs++;
}
/*
* MAC port (function zero control)
*/
if (own_fzc) {
ldvp->ldv_ldf_masks = 0;
nldvs++;
}
"func %d nldvs %d navail %d nrequired %d",
/*
* Function 0 owns system error interrupts.
*/
if (own_sys_err) {
ldvp->ldv_ldf_masks = 0;
/*
* Unmask the system interrupt states.
*/
nldvs++;
} else {
ldvp->ldv_ldf_masks = 0;
}
"func %d nldvs %d navail %d nrequired %d",
return (status);
}
{
"no logical group configured."));
return (NXGE_OK);
}
}
}
}
return (NXGE_OK);
}
{
/*
* Configure the logical device group numbers, state vectors and
* interrupt masks for each logical device.
*/
/*
* Configure logical device masks and timers.
*/
return (status);
}
{
int i, j;
"<== nxge_intr_mask_mgmt: Null ldgvp"));
return (NXGE_ERROR);
}
"<== nxge_intr_mask_mgmt: Null ldgp or ldvp"));
return (NXGE_ERROR);
}
/* Initialize masks. */
"==> nxge_intr_mask_mgmt(Neptune): # intrs %d ",
"==> nxge_intr_mask_mgmt(Neptune): # ldv %d "
"==> nxge_intr_mask_mgmt: set ldv # %d "
if (rs != NPI_SUCCESS) {
"<== nxge_intr_mask_mgmt: "
"set mask failed "
" rs 0x%x ldv %d mask 0x%x",
ldvp->ldv_ldf_masks));
return (NXGE_ERROR | rs);
}
"==> nxge_intr_mask_mgmt: "
"set mask OK "
" rs 0x%x ldv %d mask 0x%x",
ldvp->ldv_ldf_masks));
}
}
}
/* Configure timer and arm bit */
if (rs != NPI_SUCCESS) {
"<== nxge_intr_mask_mgmt: "
"set timer failed "
" rs 0x%x dg %d timer 0x%x",
return (NXGE_ERROR | rs);
}
"==> nxge_intr_mask_mgmt: "
"set timer OK "
" rs 0x%x ldg %d timer 0x%x",
}
return (NXGE_OK);
}
{
int i, j;
"==> nxge_intr_mask_mgmt_set (%d)", on));
on));
return (NXGE_ERROR);
}
"==> nxge_intr_mask_mgmt_set: Null ldgvp"));
return (NXGE_ERROR);
}
"<== nxge_intr_mask_mgmt_set: Null ldgp or ldvp"));
return (NXGE_ERROR);
}
/* set masks. */
"==> nxge_intr_mask_mgmt_set: flag %d ldg %d"
"==> nxge_intr_mask_mgmt_set: "
"for %d %d flag %d", i, j, on));
if (on) {
ldvp->ldv_ldf_masks = 0;
"==> nxge_intr_mask_mgmt_set: "
"ON mask off"));
} else if (!on) {
"==> nxge_intr_mask_mgmt_set:mask on"));
}
if (rs != NPI_SUCCESS) {
"==> nxge_intr_mask_mgmt_set: "
"set mask failed "
" rs 0x%x ldv %d mask 0x%x",
return (NXGE_ERROR | rs);
}
"==> nxge_intr_mask_mgmt_set: flag %d"
"set mask OK "
" ldv %d mask 0x%x",
}
}
/* set the arm bit */
}
if (rs != NPI_SUCCESS) {
"<== nxge_intr_mask_mgmt_set: "
"set timer failed "
" rs 0x%x ldg %d timer 0x%x",
return (NXGE_ERROR | rs);
}
"==> nxge_intr_mask_mgmt_set: OK (flag %d) "
"set timer "
" ldg %d timer 0x%x",
}
return (NXGE_OK);
}
static nxge_status_t
{
#if defined(_BIG_ENDIAN)
uint_t j;
#endif
uint_t i;
#if defined(_BIG_ENDIAN)
/*
* Get the ethernet address.
*/
/*
* Check if it is an adapter with its own local mac address If it is
* present, override the system mac address.
*/
"local-mac-address", &prop_val,
&prop_len) == DDI_PROP_SUCCESS) {
if (prop_len == ETHERADDRL) {
"%02x:%02x:%02x:%02x:%02x:%02x",
}
}
"local-mac-address?", &prop_val,
&prop_len) == DDI_PROP_SUCCESS) {
"Using local MAC address"));
}
} else {
}
goto got_mac_addr;
"MAC address from properties is not valid...reading from PROM"));
#endif
(void) nxge_espc_mac_addrs_get(nxgep);
"MAC address"));
"[%s] invalid...please update",
return (NXGE_ERROR);
}
goto got_mac_addr;
}
/*
* First get the MAC address from the info in the VPD data read
* from the EEPROM.
*/
"nxge_get_mac_addr_properties: "
"MAC address in EEPROM VPD data not valid"
"...reading from NCR registers"));
(void) nxge_espc_mac_addrs_get(nxgep);
"MAC address"));
"[%s] invalid...please update",
return (NXGE_ERROR);
}
}
/*
* Note: mac-addresses property is the list of mac addresses for a
* port. NXGE_MAX_MMAC_ADDRS is the total number of MAC addresses
* allocated for a board.
*/
#if defined(_BIG_ENDIAN)
/*
* XAUI may have up to 18 MACs, more than the XMAC can
* use (1 unique MAC plus 16 alternate MACs)
*/
}
for (j = 0; j < ETHERADDRL; j++) {
*(prop_val + (i * ETHERADDRL) + j);
}
"nxge_get_mac_addr_properties: Alt mac[%d] from "
"mac-addresses property[%2x:%2x:%2x:%2x:%2x:%2x]",
}
goto got_mmac_info;
}
#endif
/*
* total_factory_macs = 32
* num_factory_mmac = (32 >> (nports/2)) - 1
* So if nports = 4, then num_factory_mmac = 7
* if nports = 2, then num_factory_mmac = 15
*/
}
NXGE_GET_PORT_NUM(func_num), i);
}
return (NXGE_OK);
}
void
{
/*
* Read the type of physical layer interface being used.
*/
} else {
}
"phy-interface", &prop_val,
&prop_len) == DDI_PROP_SUCCESS) {
} else {
}
}
}
/*
* Static functions start here.
*/
static void
{
/* Assign the group number for each device. */
"ldv %d endldg %d ldg %d, ldvp $%p",
*ngrps += 1;
"==> nxge_ldgv_setup: ngrps %d", *ngrps));
}
"==> nxge_ldgv_setup: ldvp $%p ngrps %d",
++*ldvp;
} else {
*ngrps += 1;
"ldv %d endldg %d ldg %d, ldvp $%p",
"==> nxge_ldgv_setup: new ngrps %d", *ngrps));
}
"ldv %d ldvp $%p endldg %d ngrps %d",
}
/*
* Note: This function assumes the following distribution of mac
* addresses among 4 ports in neptune:
*
* -------------
* 0| |0 - local-mac-address for fn 0
* -------------
* 1| |1 - local-mac-address for fn 1
* -------------
* 2| |2 - local-mac-address for fn 2
* -------------
* 3| |3 - local-mac-address for fn 3
* -------------
* | |4 - Start of alt. mac addr. for fn 0
* | |
* | |
* | |10
* --------------
* | |11 - Start of alt. mac addr. for fn 1
* | |
* | |
* | |17
* --------------
* | |18 - Start of alt. mac addr. for fn 2
* | |
* | |
* | |24
* --------------
* | |25 - Start of alt. mac addr. for fn 3
* | |
* | |
* | |31
* --------------
*
*
* When 'compute_addrs' is true, the alternate mac addresses are computed
* using the unique mac address as base. Otherwise the alternate addresses
* are assigned from the list read off the 'mac-addresses' property.
*/
static void
{
int slot;
if (compute_addrs) {
base_mmac_addr[2];
/* ls4b of 1st altmac */
} else { /* Neptune */
}
}
/* Set flags for unique MAC */
/* Clear flags of all alternate MAC slots */
else
}
/* Generate and store factory alternate MACs */
if (compute_addrs) {
mmac_addr[0] = base_mmac_addr[0];
alt_mac_ls4b++;
} else {
}
"mac_pool_addr[%2x:%2x:%2x:%2x:%2x:%2x] npi_addr[%x%x%x]",
/*
* slot minus 1 because npi_mac_altaddr_entry expects 0
* for the first alternate mac address.
*/
}
/* Initialize the first two parameters for mmac kstat */
}
/*
* Convert an RDC group index into a port ring index. That is, map
* <groupid> to an index into nxgep->rx_ring_handles.
* (group ring index -> port ring index)
*/
int
{
int i;
int index = 0;
for (i = 0; i < groupid; i++) {
}
}