bge_kstats.c revision 8eb6c4f9472d7b6f007c889f8e14385510452918
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include "sys/bge_impl.h"
/*
* Type of transceiver currently in use. The IEEE 802.3 std aPhyType
* enumerates the following set
*/
enum xcvr_type {
XCVR_TYPE_UNDEFINED = 0, /* 0 = undefined, or not yet known */
XCVR_TYPE_NONE, /* 1= MII present & nothing connected */
XCVR_TYPE_10BASE_T, /* 2 = 10 Mbps copper */
XCVR_TYPE_100BASE_T4, /* 3 = 10 Mbps copper */
XCVR_TYPE_100BASE_X, /* 4 = 100 Mbps copper */
XCVR_TYPE_100BASE_T2, /* 5 = 100 Mbps copper */
XCVR_TYPE_1000BASE_X, /* 6 = 1000 Mbps SerDes */
XCVR_TYPE_1000BASE_T /* 7 = 1000 Mbps copper */
};
/*
* Local datatype for defining tables of (Offset, Name) pairs
*/
typedef struct {
char *name;
/*
* Table of Hardware-defined Statistics Block Offsets and Names
*/
static const bge_ksindex_t bge_statistics[] = {
{ KS_STATS_SIZE, NULL }
};
static const bge_ksindex_t bge_stat_val[] = {
{ KS_STAT_REG_SIZE, NULL }
};
static int
{
const bge_ksindex_t *ksip;
if (flag != KSTAT_READ)
return (EACCES);
/*
* Transfer the statistics values from the copy that the
* chip updates via DMA to the named-kstat structure.
*
* As above, we don't bother to sync or stop updates to the
* statistics, 'cos it doesn't really matter if they're a few
* microsends out of date or less than 100% consistent ...
*/
else {
}
return (0);
}
static int
{
int i;
if (flag != KSTAT_READ)
return (EACCES);
return (0);
}
static const bge_ksindex_t bge_chipid[] = {
{ 0, "asic_rev" },
{ 1, "businfo" },
{ 2, "command" },
{ 3, "vendor_id" },
{ 4, "device_id" },
{ 5, "subsystem_vendor_id" },
{ 6, "subsystem_device_id" },
{ 7, "revision_id" },
{ 8, "cache_line_size" },
{ 9, "latency_timer" },
{ 10, "flags" },
{ 11, "chip_type" },
{ 12, "mbuf_base" },
{ 13, "mbuf_count" },
{ 14, "hw_mac_addr" },
{ 15, "&bus_type" },
{ 16, "&bus_speed" },
{ 17, "&bus_size" },
{ 18, "&supported" },
{ 19, "&interface" },
{ -1, NULL }
};
static void
{
}
static int
{
if (flag != KSTAT_READ)
return (EACCES);
/*
* Now we interpret some of the above into readable strings
*/
return (0);
}
static const bge_ksindex_t bge_driverinfo[] = {
{ 0, "rx_buff_addr" },
{ 1, "tx_buff_addr" },
{ 2, "rx_desc_addr" },
{ 3, "tx_desc_addr" },
{ 4, "tx_desc_free" },
{ 5, "resched_needed" },
{ 6, "watchdog" },
{ 7, "chip_resets" },
{ 8, "dma_misses" },
{ 9, "misc_host_config" },
{ 10, "dma_rw_control" },
{ 11, "pci_bus_info" },
{ 12, "buff_mgr_status" },
{ 13, "rcv_init_status" },
{ -1, NULL }
};
static int
{
if (flag != KSTAT_READ)
return (EACCES);
/*
* Hold the mutex while accessing the chip registers
* just in case the factotum is trying to reset it!
*/
return (0);
}
static const bge_ksindex_t bge_mii_kstats[] = {
{ 0, "%xcvr_addr" },
{ 1, "%xcvr_id" },
{ 2, "%xcvr_inuse" },
{ 3, "%cap_1000fdx" },
{ 4, "%cap_1000hdx" },
{ 5, "%cap_100fdx" },
{ 6, "%cap_100hdx" },
{ 7, "%cap_10fdx" },
{ 8, "%cap_10hdx" },
{ 9, "%cap_asmpause" },
{ 10, "%cap_pause" },
{ 11, "%cap_rem_fault" },
{ 12, "%cap_autoneg" },
{ 13, "%adv_cap_1000fdx" },
{ 14, "%adv_cap_1000hdx" },
{ 15, "%adv_cap_100fdx" },
{ 16, "%adv_cap_100hdx" },
{ 17, "%adv_cap_10fdx" },
{ 18, "%adv_cap_10hdx" },
{ 19, "%adv_cap_asmpause" },
{ 20, "%adv_cap_pause" },
{ 21, "%adv_rem_fault" },
{ 22, "%adv_cap_autoneg" },
{ 23, "%lp_cap_1000fdx" },
{ 24, "%lp_cap_1000hdx" },
{ 25, "%lp_cap_100fdx" },
{ 26, "%lp_cap_100hdx" },
{ 27, "%lp_cap_10fdx" },
{ 28, "%lp_cap_10hdx" },
{ 29, "%lp_cap_asmpause" },
{ 30, "%lp_cap_pause" },
{ 31, "%lp_rem_fault" },
{ 32, "%lp_cap_autoneg" },
{ 33, "%link_asmpause" },
{ 34, "%link_pause" },
{ 35, "%link_duplex" },
{ 36, "%link_up" },
{ -1, NULL }
};
/*
* Derive and publish the standard "mii" kstats.
*
* The information required is somewhat scattered: some is already held
* in driver softstate, some is available in the MII registers, and some
* has to be computed from combinations of both ...
*/
static int
{
if (flag != KSTAT_READ)
return (EACCES);
/*
* Read all the relevant PHY registers
*/
/*
* Derive PHY characterisation parameters
*/
xcvr_id <<= 16;
switch (bgep->param_link_speed) {
case 1000:
else
break;
case 100:
break;
case 10:
break;
default:
break;
}
/*
* Other miscellaneous transformations ...
*/
/*
* All required values are now available; assign them to the
* actual kstats, in the sequence defined by the table above.
*/
/*
* Our capabilities
*/
/*
* Our *advertised* capabilities
*/
/*
* Link Partner's advertised capabilities
*/
/*
* Current operating modes
*/
return (0);
}
static const bge_ksindex_t bge_serdes[] = {
{ 0, "serdes_status" },
{ 1, "serdes_advert" },
{ 2, "serdes_lpadv" },
{ -1, NULL }
};
static int
{
if (flag != KSTAT_READ)
return (EACCES);
return (0);
}
static const bge_ksindex_t bge_phydata[] = {
{ MII_CONTROL, "mii_control" },
{ MII_STATUS, "mii_status" },
{ MII_PHYIDH, "phy_identifier" },
{ MII_AN_ADVERT, "an_advert" },
{ MII_AN_LPABLE, "an_lp_ability" },
{ MII_AN_EXPANSION, "an_expansion" },
{ MII_AN_LPNXTPG, "an_lp_nextpage" },
{ MII_1000BASE_T_CONTROL, "gbit_control" },
{ MII_1000BASE_T_STATUS, "gbit_status" },
{ MII_IEEE_EXT_STATUS, "ieee_ext_status" },
{ MII_EXT_CONTROL, "phy_ext_control" },
{ MII_EXT_STATUS, "phy_ext_status" },
{ MII_RCV_ERR_COUNT, "receive_error_count" },
{ MII_FALSE_CARR_COUNT, "false_carrier_count" },
{ MII_RCV_NOT_OK_COUNT, "receiver_not_ok_count" },
{ MII_AUX_CONTROL, "aux_control" },
{ MII_AUX_STATUS, "aux_status" },
{ MII_INTR_STATUS, "intr_status" },
{ MII_INTR_MASK, "intr_mask" },
{ MII_HCD_STATUS, "hcd_status" },
{ -1, NULL }
};
static int
{
const bge_ksindex_t *ksip;
if (flag != KSTAT_READ)
return (EACCES);
/*
* Read the PHY registers & update the kstats ...
*
* We need to hold the mutex while performing MII reads, but
* we don't want to hold it across the entire sequence of reads.
* So we grab and release it on each iteration, 'cos it doesn't
* really matter if the kstats are less than 100% consistent ...
*/
case MII_STATUS:
break;
case MII_PHYIDH:
break;
default:
break;
}
}
return (0);
}
static kstat_t *
{
char *np;
int type;
size /= sizeof (bge_ksindex_t);
return (NULL);
switch (*np) {
default:
break;
case '%':
np += 1;
break;
case '$':
np += 1;
break;
case '&':
np += 1;
break;
}
}
return (ksp);
}
/*
* Create kstats corresponding to NDD parameters
*/
static kstat_t *
{
int i;
}
return (ksp);
}
void
{
sizeof (bge_statistics_t), KSTAT_FLAG_VIRTUAL);
}
sizeof (bge_statistics), bge_statistics_update);
} else {
sizeof (bge_stat_val), bge_statistics_update);
}
sizeof (bge_chipid), bge_chipid_update);
sizeof (bge_driverinfo), bge_driverinfo_update);
sizeof (bge_mii_kstats), bge_mii_update);
sizeof (bge_serdes), bge_serdes_update);
else
sizeof (bge_phydata), bge_phydata_update);
}
void
{
int i;
for (i = BGE_KSTAT_COUNT; --i >= 0; )
}
{
else {
}
switch (stat) {
case MAC_STAT_IFSPEED:
break;
case MAC_STAT_MULTIRCV:
else
break;
case MAC_STAT_BRDCSTRCV:
else
break;
case MAC_STAT_MULTIXMT:
else
break;
case MAC_STAT_BRDCSTXMT:
else
break;
case MAC_STAT_NORCVBUF:
else
val = 0;
break;
case MAC_STAT_IERRORS:
else
val = 0;
break;
case MAC_STAT_NOXMTBUF:
else
val = 0;
break;
case MAC_STAT_OERRORS:
else
val = 0;
break;
case MAC_STAT_COLLISIONS:
else
break;
case MAC_STAT_RBYTES:
else
break;
case MAC_STAT_IPACKETS:
bstp->s.ifHCInMulticastPkts +
else
break;
case MAC_STAT_OBYTES:
else
break;
case MAC_STAT_OPACKETS:
bstp->s.ifHCOutMulticastPkts +
else
break;
case MAC_STAT_ALIGN_ERRORS:
else
break;
case MAC_STAT_FCS_ERRORS:
else
break;
else
break;
else
break;
case MAC_STAT_DEFER_XMTS:
else
break;
else
break;
case MAC_STAT_EX_COLLISIONS:
else
break;
case MAC_STAT_MACXMT_ERRORS:
else
break;
case MAC_STAT_CARRIER_ERRORS:
else
val = 0;
break;
case MAC_STAT_TOOLONG_ERRORS:
else
break;
case MAC_STAT_XCVR_ADDR:
break;
case MAC_STAT_XCVR_ID:
val <<= 16;
break;
case MAC_STAT_XCVR_INUSE:
val = XCVR_1000T;
break;
case MAC_STAT_CAP_1000FDX:
val = 1;
break;
case MAC_STAT_CAP_1000HDX:
val = 1;
break;
case MAC_STAT_CAP_100FDX:
val = 1;
break;
case MAC_STAT_CAP_100HDX:
val = 1;
break;
case MAC_STAT_CAP_10FDX:
val = 1;
break;
case MAC_STAT_CAP_10HDX:
val = 1;
break;
case MAC_STAT_CAP_ASMPAUSE:
val = 1;
break;
case MAC_STAT_CAP_PAUSE:
val = 1;
break;
case MAC_STAT_CAP_AUTONEG:
val = 1;
break;
case MAC_STAT_ADV_CAP_1000FDX:
break;
case MAC_STAT_ADV_CAP_1000HDX:
break;
case MAC_STAT_ADV_CAP_100FDX:
break;
case MAC_STAT_ADV_CAP_100HDX:
break;
case MAC_STAT_ADV_CAP_10FDX:
break;
case MAC_STAT_ADV_CAP_10HDX:
break;
break;
case MAC_STAT_ADV_CAP_PAUSE:
break;
case MAC_STAT_ADV_CAP_AUTONEG:
break;
case MAC_STAT_LP_CAP_1000FDX:
break;
case MAC_STAT_LP_CAP_1000HDX:
break;
case MAC_STAT_LP_CAP_100FDX:
break;
case MAC_STAT_LP_CAP_100HDX:
break;
case MAC_STAT_LP_CAP_10FDX:
break;
case MAC_STAT_LP_CAP_10HDX:
break;
case MAC_STAT_LP_CAP_ASMPAUSE:
break;
case MAC_STAT_LP_CAP_PAUSE:
break;
case MAC_STAT_LP_CAP_AUTONEG:
break;
case MAC_STAT_LINK_ASMPAUSE:
break;
case MAC_STAT_LINK_PAUSE:
break;
case MAC_STAT_LINK_AUTONEG:
break;
case MAC_STAT_LINK_DUPLEX:
break;
#ifdef DEBUG
default:
/*
* Shouldn't reach here...
*/
"bge_m_stat: unrecognized parameter value = %d",
stat);
#endif
}
return (val);
}