nxge_virtual.c revision 14ea4bb737263733ad80a36b4f73f681c30a6b45
/*
* 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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
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_setup_hw_pciconfig(p_nxge_t);
static void nxge_setup_hw_vpd_rom_mac(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_init_mmac(p_nxge_t);
extern uint32_t nxge_use_partition;
extern uint32_t nxge_dma_obp_props_only;
extern uint16_t nxge_rcr_timeout;
extern uint16_t nxge_rcr_threshold;
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.
*/
/*ARGSUSED*/
{
int instance;
#ifndef NXGE_SHARED_REG_SW_SIM
#endif
"Instance %d ",
instance));
"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
{
}
}
}
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",
port,
custom_num_rdc[port]));
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] |=
(1 <<
}
}
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",
custom_num_rdc[port]));
}
if (ddi_status != DDI_PROP_SUCCESS) {
" property %s"
" not updating with %d ",
custom_start_rdc[port]));
}
}
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";
p4_tx_equal[port] :
}
break;
case CUSTOM:
cfg_prop = "custom";
/* See if it is good config */
num_tdc = 0;
&prop_val,
&prop_len);
if (ddi_status == DDI_SUCCESS)
else {
" %s custom start port %d"
" read failed ",
" txdma-cfg", port));
bad_config = B_TRUE;
}
(custom_start_tdc[port] >=
NXGE_MAX_RDCS)) {
" %s custom start %d"
" out of range %x ",
" txdma-cfg",
port,
custom_start_tdc[port]));
bad_config = B_TRUE;
break;
}
0,
&prop_val,
&prop_len);
if (ddi_status == DDI_SUCCESS)
else {
" %s custom num port %d"
" read failed ",
" txdma-cfg", port));
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",
port,
custom_num_tdc[port]));
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"));
(num_ports == 4) ?
p4_tx_fair[port] :
}
}
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 ",
custom_start_tdc[port]));
}
}
if (status & NXGE_DDI_FAILED)
status |= NXGE_ERROR;
return (status);
}
static nxge_status_t
dev_info_t *s_dip[])
{
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.
*/
dev_info_t *c_dip[])
{
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) ==
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) {
c_dip[i],
#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 class_prop, int rx_quick_cfg)
{
int start_prop;
/* update the properties per quick config */
switch (rx_quick_cfg) {
case CFG_L3_WEB:
case CFG_L3_DISTRIBUTE:
class_prop - start_prop);
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.
* Includee 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;
}
/*
* 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;
class_prop++) {
}
return (status);
}
{
int i = 0, found = 0;
int num_siblings;
char *prop_val[MAX_SIBLINGS];
char *prop;
if (nxge_dma_obp_props_only) {
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) {
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)
#ifdef lint
#endif
/* now handle specified cases: */
if (status & NXGE_DDI_FAILED)
status |= NXGE_ERROR;
return (status);
}
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 */
}
}
}
}
}
}
}
}
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;
if (adv_autoneg_cap == 0) {
} else if (speed == 0) {
}
if (duplex == 0) {
adv_10gfdx_cap = (speed == 0);
}
if (status)
if (status)
if (status)
if (status)
if (status)
if (status)
if (status)
if (status)
if (status)
return;
}
{
" nxge_get_config_properties:"
" common hardware not set",
return (NXGE_ERROR);
}
/*
* Get info on how many ports Neptune card has.
*/
case N2_NIU:
return (NXGE_ERROR);
}
break;
case NEPTUNE_2:
return (NXGE_ERROR);
}
/* Set Board Version Number */
0, "board-model", &prop_val8,
&prop_len) == DDI_PROP_SUCCESS) {
if (prop_len > 9) {
}
}
return (NXGE_ERROR);
}
break;
case NEPTUNE:
default:
return (NXGE_ERROR);
}
break;
}
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
* proprtional
* to te 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;
case NEPTUNE:
" ==> nxge_get_config_properties: Neptune"));
}
break;
case NEPTUNE_2:
" ==> nxge_get_config_properties: Neptune-2"));
return (NXGE_ERROR);
}
break;
default:
" nxge_get_config_properties:"
" unknown NIU type %x",
return (NXGE_ERROR);
}
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);
/* Setup the VPD, expansion ROM, or MAC addresses configuration */
/*
* 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
{
" ==> 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);
/* Setup the PCI related configuration */
/* Setup the VPD, expansion ROM, or MAC addresses configuration */
/*
* Read in the hardware (fcode) properties. Use the ndd array
* to read each property.
*/
(void) nxge_get_param_soft_properties(nxgep);
" <== nxge_use_cfg_neptune_properties"));
}
/* FWARC 2006/556 */
static nxge_status_t
{
int ndmas;
int nrxgp;
int *prop_val;
int i;
"tx-dma-channels",
(int **)&prop_val,
&prop_len) == DDI_PROP_SUCCESS) {
"==> 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 nxgep->max_tdcs %d start %d",
/* Receive DMA */
"rx-dma-channels",
(int **)&prop_val,
&prop_len) == DDI_PROP_SUCCESS) {
"==> nxge_use_default_dma_config_n2(obp): rdc start %d"
"==> nxge_use_default_dma_config_n2(obp):#rdc %d (#%d)",
} else {
"==> nxge_use_default_dma_config_n2: "
"get rx-dma-channel failed"));
return (NXGE_DDI_FAILED);
}
/* Hypervisor: rdc # and group # use the same # !! */
p_cfgp->start_grpid = 0;
"interrupts",
(int **)&prop_val,
&prop_len) == DDI_PROP_SUCCESS) {
/*
* 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): "
"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 nxgep->max_rdcs %d max_grpids %d"
"start_grpid %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.
*/
nrxgp = 2;
"rx-rdc-grps", nrxgp);
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 status;
} else {
} else {
}
}
} else {
tx_ndmas = p2_tx_equal[0];
} else {
tx_ndmas = p4_tx_equal[0];
}
}
"p_cfgp 0x%llx max_tdcs %d nxgep->max_tdcs %d",
} else {
} else {
}
}
} else {
rx_ndmas = p2_rx_equal[0];
} else {
rx_ndmas = p4_rx_equal[0];
}
}
"==> nxge_use_default_dma_config: "
"use property "
"start_grpid %d ",
p_cfgp->start_grpid));
} else {
"==> nxge_use_default_dma_config: "
"use default "
"start_grpid %d (same as function #)",
p_cfgp->start_grpid));
}
} else {
nrxgp = 1;
"==> 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 nxgep->max_rdcs %d max_grpids %d"
"start_grpid %d",
p_cfgp->start_grpid));
"p_cfgp 0x%016llx start_ldg %d nxgep->max_ldgs %d "
"start_rdc_grpid %d",
/* add code for individual rdc properties */
}
}
}
}
#ifdef lint
#endif
}
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) {
mac_cnt);
}
}
static void
{
}
/*ARGSUSED*/
static void
{
/*
* Initialize PCI configuration registers if
* required.
*/
}
/*ARGSUSED*/
static void
{
}
static void
{
int i;
#ifdef NXGE_CFG_V2
int *rdc_cfg_val;
char *prop;
#endif
for (i = 0; i < NXGE_MAX_RDCS; i++) {
}
#ifdef NXGE_CFG_V2
/*
*
* Format
*
* uint32_t array, each array entry specifying the
* rdc id and the rcr interrupt blanking parameter
*
* bit[30] = enable
* bit[29] = remove
* bits[23-16] = rdc
* bits[15-0] = blanking parameter
*/
&rdc_cfg_val, &rdc_prop_cnt) ==
for (i = 0; i < rdc_prop_cnt; i++) {
" nxge_rcr param mapping"
" rdc %d timeout %d",
}
tout++;
}
}
&rdc_cfg_val, &rdc_prop_cnt) ==
for (i = 0; i < rdc_prop_cnt; i++) {
" nxge_rcr param rdc %d"
" threshold %x",
}
threshold++;
}
}
#endif
}
/*ARGSUSED*/
static void
{
#ifdef NXGE_CFG_V2
#endif
/* Transmit DMA Channels */
bitmap = 0;
p_dma_cfgp->tx_dma_map = 0;
bitmap |= (1 << i);
}
/* Assume RDCs are evenly distributed */
switch (rx_quick_cfg) {
case CFG_NOT_SPECIFIED:
prop = "rxdma-grp-cfg";
prop,
(char **)&prop_val);
if (status != DDI_PROP_SUCCESS) {
" property %s not found", prop));
} else {
switch (token) {
case L2_CLASSIFY:
break;
case CLASSIFY:
case L3_CLASSIFY:
case L3_DISTRIBUTE:
case L3_TCAM:
break;
default:
break;
}
}
break;
case CFG_L3_WEB:
case CFG_L3_DISTRIBUTE:
case CFG_L2_CLASSIFY:
case CFG_L3_TCAM:
break;
default:
break;
}
/* Receive DMA Channels */
}
switch (rdcgrp_cfg) {
case CFG_L3_DISTRIBUTE:
case CFG_L3_WEB:
case CFG_L3_TCAM:
ngrps = 1;
break;
case CFG_L2_CLASSIFY:
ndmas = 1;
ngrps = 1;
break;
default:
break;
}
for (i = 0; i < ngrps; i++) {
/* default to: 0, 1, 2, 3, ...., 0, 1, 2, 3.... */
for (j = 0; j < NXGE_MAX_RDCS; j++) {
}
}
}
/* default RDC */
#ifdef NXGE_CFG_V2
&int_prop_val, &prop_len) ==
} else {
}
#ifdef NXGE_DEBUG_ERROR
if (status != DDI_PROP_SUCCESS)
" property %s failed update ", prop));
#endif
#else
#endif
/* full 18 byte header ? */
#ifdef NXGE_CFG_V2
&int_prop_val, &prop_len) ==
} else {
/* enabled by default */
}
#else
#endif
#ifdef NXGE_CFG_V2
&int_prop_val, &prop_len) ==
} else {
}
prop,
(int)p_dma_cfgp->rx_drr_weight);
#else
#endif
#ifdef NXGE_CFG_V2
&int_prop_val, &prop_len) ==
if ((p_dma_cfgp->rbr_size <
(p_dma_cfgp->rbr_size >
} else {
}
#else
#endif
#ifdef NXGE_CFG_V2
&int_prop_val, &prop_len) ==
if ((p_dma_cfgp->rcr_size <
(p_dma_cfgp->rcr_size >
} else {
}
#else
#endif
}
{
/* Receive DMA Channels */
return (status);
}
{
/* Receive DMA Channels */
return (status);
}
/*ARGSUSED*/
{
" ==> nxge_check_rxdma_rdcgrp_member"));
" rdc %d group %d",
}
" <== nxge_check_rxdma_rdcgrp_member"));
return (status);
}
{
return (status);
}
static void
{
int status, 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++) {
}
&vlan_cfg_val, &vlan_cnt) ==
for (i = 0; i < vlan_cnt; i++) {
" nxge_vlan_config mapping"
" id %d grp %d",
good_count++;
}
}
if (good_count != vlan_cnt) {
(int *)good_cfg, good_count);
}
}
#ifdef lint
#endif
}
static void
{
int status, 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++) {
}
&mac_cfg_val, &mac_cnt) ==
for (i = 0; i < mac_cnt; i++) {
" nxge_mac_config mapping"
" id %d grp %d",
good_count++;
}
}
if (good_count != mac_cnt) {
}
}
#ifdef lint
#endif
}
static void
{
int i;
int *int_prop_val;
char *prop;
int start_prop, end_prop;
for (i = start_prop; i <= end_prop; i++) {
0, prop,
&int_prop_val, &prop_cnt) ==
} else {
}
}
&int_prop_val, &prop_cnt) ==
} else {
}
&int_prop_val, &prop_cnt) ==
} else {
}
}
/*ARGSUSED*/
{
if (!*navail_p) {
*nrequired_p = 0;
"<== nxge_ldgv_init:no avail"));
return (NXGE_ERROR);
}
/*
* one vector by Hypervisor.
*/
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 error interrupts.
*/
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) {
}
KM_SLEEP);
KM_SLEEP);
} 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++;
}
/*
* 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",
} else {
ldvp++;
}
nldvs++;
"(before rx) func %d nldvs %d navail %d nrequired %d",
/*
* Receive DMA channels.
*/
/*
* 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++;
}
"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 0x%016llx ldvptr 0x%016llx",
nldvs++;
}
"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.
*/
/* If non-seq needs to change the following code */
ldvp->ldv_ldf_masks = 0;
nldvs++;
}
/*
* Transmit DMA channels.
*/
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
{
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 {
}
#else
(void) nxge_espc_mac_addrs_get(nxgep);
#endif
/* NIU does not need max_num_mmac */
} else {
"nxge_get_mac_addr_properties, espc access failed"));
return (NXGE_ERROR);
}
}
/*
* Note: mac-addresses of n2-niu is the list of mac addresses
* for a port. #mac-addresses stored in Neptune's SEEPROM is
* the total number of MAC addresses allocated for a board.
*/
/*
* XAUI may have up to 18 MACs, more than the XMAC can
* use (1 unique MAC plus 16 alternate MACs)
*/
XMAC_MAX_ALT_ADDR_ENTRY + 1) {
}
}
} else {
}
/* Initialze all mac addr. to "AVAILABLE" state */
/*
* XMAC: Disable alter MAC address comparison only
* (XMAC's unique MAC comparison is always
* enabled.
* BMAC: (Neptune only) Disable both unique and
* alter MAC address comparison
*/
NXGE_GET_PORT_NUM(func_num), i);
}
/*
* Initialize alt. mac addr. in the mac pool
*/
(void) nxge_init_mmac(nxgep);
return (NXGE_OK);
}
void
{
/*
* Read the type of physical layer interface being used.
*/
} else {
}
} 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 assume 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
* --------------
*
*/
static void
{
int i;
else /* Neptune */
/*
* Populate shadow mac pool w/ available mac. so we dont
* have to read the h/w to search for a mac addr.
*/
mmac_addr[0] = base_mmac_addr[0];
/*
* Program the h/w alt. mac address, starting
* from reg1(reg0 corr. to unique mac addr)
*/
}
}