xref: /titanic_51/usr/src/uts/common/io/e1000g/e1000g_stat.c (revision 29fd2c1627adafbe0a83726c224e60b5514c7736)
108057504Sxy150489 /*
208057504Sxy150489  * This file is provided under a CDDLv1 license.  When using or
308057504Sxy150489  * redistributing this file, you may do so under this license.
408057504Sxy150489  * In redistributing this file this license must be included
508057504Sxy150489  * and no other modification of this header file is permitted.
608057504Sxy150489  *
708057504Sxy150489  * CDDL LICENSE SUMMARY
808057504Sxy150489  *
9d5c3073dSchenlu chen - Sun Microsystems - Beijing China  * Copyright(c) 1999 - 2009 Intel Corporation. All rights reserved.
1008057504Sxy150489  *
1108057504Sxy150489  * The contents of this file are subject to the terms of Version
1208057504Sxy150489  * 1.0 of the Common Development and Distribution License (the "License").
1308057504Sxy150489  *
1408057504Sxy150489  * You should have received a copy of the License with this software.
1508057504Sxy150489  * You can obtain a copy of the License at
1608057504Sxy150489  *	http://www.opensolaris.org/os/licensing.
1708057504Sxy150489  * See the License for the specific language governing permissions
1808057504Sxy150489  * and limitations under the License.
1908057504Sxy150489  */
2008057504Sxy150489 
2108057504Sxy150489 /*
220dc2366fSVenugopal Iyer  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23*29fd2c16SDavid Höppner  * Copyright 2012 David Höppner. All rights reserved.
24da14cebeSEric Cheng  * Use is subject to license terms.
2508057504Sxy150489  */
2608057504Sxy150489 
2708057504Sxy150489 /*
2808057504Sxy150489  * **********************************************************************
2908057504Sxy150489  *									*
3008057504Sxy150489  * Module Name:  e1000g_stat.c						*
3108057504Sxy150489  *									*
3225f2d433Sxy150489  * Abstract: Functions for processing statistics			*
3308057504Sxy150489  *									*
3408057504Sxy150489  * **********************************************************************
3508057504Sxy150489  */
3608057504Sxy150489 #include "e1000g_sw.h"
3708057504Sxy150489 #include "e1000g_debug.h"
3808057504Sxy150489 
3925f2d433Sxy150489 static int e1000g_update_stats(kstat_t *ksp, int rw);
40caf05df5SMiles Xu, Sun Microsystems static uint32_t e1000g_read_phy_stat(struct e1000_hw *hw, int reg);
4108057504Sxy150489 
4208057504Sxy150489 /*
4325f2d433Sxy150489  * e1000_tbi_adjust_stats
4425f2d433Sxy150489  *
4525f2d433Sxy150489  * Adjusts statistic counters when a frame is accepted
4625f2d433Sxy150489  * under the TBI workaround. This function has been
4725f2d433Sxy150489  * adapted for Solaris from shared code.
4808057504Sxy150489  */
4908057504Sxy150489 void
5025f2d433Sxy150489 e1000_tbi_adjust_stats(struct e1000g *Adapter,
5125f2d433Sxy150489     uint32_t frame_len, uint8_t *mac_addr)
5208057504Sxy150489 {
5325f2d433Sxy150489 	uint32_t carry_bit;
5425f2d433Sxy150489 	p_e1000g_stat_t e1000g_ksp;
5508057504Sxy150489 
5625f2d433Sxy150489 	e1000g_ksp = (p_e1000g_stat_t)Adapter->e1000g_ksp->ks_data;
5708057504Sxy150489 
5825f2d433Sxy150489 	/* First adjust the frame length */
5925f2d433Sxy150489 	frame_len--;
6025f2d433Sxy150489 
6108057504Sxy150489 	/*
6208057504Sxy150489 	 * We need to adjust the statistics counters, since the hardware
6308057504Sxy150489 	 * counters overcount this packet as a CRC error and undercount
6408057504Sxy150489 	 * the packet as a good packet
6508057504Sxy150489 	 */
6625f2d433Sxy150489 	/* This packet should not be counted as a CRC error */
67*29fd2c16SDavid Höppner 	Adapter->fcs_errors--;
6825f2d433Sxy150489 	/* This packet does count as a Good Packet Received */
6908057504Sxy150489 	e1000g_ksp->Gprc.value.ul++;
7008057504Sxy150489 
7108057504Sxy150489 	/*
7208057504Sxy150489 	 * Adjust the Good Octets received counters
7308057504Sxy150489 	 */
7425f2d433Sxy150489 	carry_bit = 0x80000000 & e1000g_ksp->Gorl.value.ul;
7525f2d433Sxy150489 	e1000g_ksp->Gorl.value.ul += frame_len;
7608057504Sxy150489 	/*
7708057504Sxy150489 	 * If the high bit of Gorcl (the low 32 bits of the Good Octets
7808057504Sxy150489 	 * Received Count) was one before the addition,
7908057504Sxy150489 	 * AND it is zero after, then we lost the carry out,
8008057504Sxy150489 	 * need to add one to Gorch (Good Octets Received Count High).
8108057504Sxy150489 	 * This could be simplified if all environments supported
8208057504Sxy150489 	 * 64-bit integers.
8308057504Sxy150489 	 */
8425f2d433Sxy150489 	if (carry_bit && ((e1000g_ksp->Gorl.value.ul & 0x80000000) == 0)) {
8508057504Sxy150489 		e1000g_ksp->Gorh.value.ul++;
8608057504Sxy150489 	}
8708057504Sxy150489 	/*
8808057504Sxy150489 	 * Is this a broadcast or multicast?  Check broadcast first,
8908057504Sxy150489 	 * since the test for a multicast frame will test positive on
9008057504Sxy150489 	 * a broadcast frame.
9108057504Sxy150489 	 */
9225f2d433Sxy150489 	if ((mac_addr[0] == (uint8_t)0xff) &&
9325f2d433Sxy150489 	    (mac_addr[1] == (uint8_t)0xff)) {
9408057504Sxy150489 		/*
9508057504Sxy150489 		 * Broadcast packet
9608057504Sxy150489 		 */
97*29fd2c16SDavid Höppner 		Adapter->brdcstrcv++;
9825f2d433Sxy150489 	} else if (*mac_addr & 0x01) {
9908057504Sxy150489 		/*
10008057504Sxy150489 		 * Multicast packet
10108057504Sxy150489 		 */
102*29fd2c16SDavid Höppner 		Adapter->multircv++;
10308057504Sxy150489 	}
10425f2d433Sxy150489 
105592a4d85Scc210113 	if (frame_len == Adapter->max_frame_size) {
10608057504Sxy150489 		/*
10708057504Sxy150489 		 * In this case, the hardware has overcounted the number of
10808057504Sxy150489 		 * oversize frames.
10908057504Sxy150489 		 */
110*29fd2c16SDavid Höppner 		if (Adapter->toolong_errors > 0)
111*29fd2c16SDavid Höppner 			Adapter->toolong_errors--;
11208057504Sxy150489 	}
11308057504Sxy150489 
11447b7744cSyy150190 #ifdef E1000G_DEBUG
11508057504Sxy150489 	/*
11608057504Sxy150489 	 * Adjust the bin counters when the extra byte put the frame in the
11725f2d433Sxy150489 	 * wrong bin. Remember that the frame_len was adjusted above.
11808057504Sxy150489 	 */
11925f2d433Sxy150489 	if (frame_len == 64) {
12008057504Sxy150489 		e1000g_ksp->Prc64.value.ul++;
12108057504Sxy150489 		e1000g_ksp->Prc127.value.ul--;
12225f2d433Sxy150489 	} else if (frame_len == 127) {
12308057504Sxy150489 		e1000g_ksp->Prc127.value.ul++;
12408057504Sxy150489 		e1000g_ksp->Prc255.value.ul--;
12525f2d433Sxy150489 	} else if (frame_len == 255) {
12608057504Sxy150489 		e1000g_ksp->Prc255.value.ul++;
12708057504Sxy150489 		e1000g_ksp->Prc511.value.ul--;
12825f2d433Sxy150489 	} else if (frame_len == 511) {
12908057504Sxy150489 		e1000g_ksp->Prc511.value.ul++;
13008057504Sxy150489 		e1000g_ksp->Prc1023.value.ul--;
13125f2d433Sxy150489 	} else if (frame_len == 1023) {
13208057504Sxy150489 		e1000g_ksp->Prc1023.value.ul++;
13308057504Sxy150489 		e1000g_ksp->Prc1522.value.ul--;
13425f2d433Sxy150489 	} else if (frame_len == 1522) {
13508057504Sxy150489 		e1000g_ksp->Prc1522.value.ul++;
13608057504Sxy150489 	}
13747b7744cSyy150190 #endif
13808057504Sxy150489 }
13908057504Sxy150489 
14008057504Sxy150489 
14108057504Sxy150489 /*
14225f2d433Sxy150489  * e1000g_update_stats - update driver private kstat counters
14325f2d433Sxy150489  *
14425f2d433Sxy150489  * This routine will dump and reset the e1000's internal
14525f2d433Sxy150489  * statistics counters. The current stats dump values will
14625f2d433Sxy150489  * be sent to the kernel status area.
14708057504Sxy150489  */
14808057504Sxy150489 static int
14925f2d433Sxy150489 e1000g_update_stats(kstat_t *ksp, int rw)
15008057504Sxy150489 {
15108057504Sxy150489 	struct e1000g *Adapter;
15225f2d433Sxy150489 	struct e1000_hw *hw;
15325f2d433Sxy150489 	p_e1000g_stat_t e1000g_ksp;
15425f2d433Sxy150489 	e1000g_tx_ring_t *tx_ring;
15525f2d433Sxy150489 	e1000g_rx_ring_t *rx_ring;
15657ef6f69Sguoqing zhu - Sun Microsystems - Beijing China #ifdef E1000G_DEBUG
15754e0d7a5SMiles Xu, Sun Microsystems 	e1000g_rx_data_t *rx_data;
15857ef6f69Sguoqing zhu - Sun Microsystems - Beijing China #endif
15908057504Sxy150489 	uint64_t val;
16008057504Sxy150489 	uint32_t low_val, high_val;
16108057504Sxy150489 
16208057504Sxy150489 	if (rw == KSTAT_WRITE)
16308057504Sxy150489 		return (EACCES);
16408057504Sxy150489 
16508057504Sxy150489 	Adapter = (struct e1000g *)ksp->ks_private;
16608057504Sxy150489 	ASSERT(Adapter != NULL);
16725f2d433Sxy150489 	e1000g_ksp = (p_e1000g_stat_t)ksp->ks_data;
16808057504Sxy150489 	ASSERT(e1000g_ksp != NULL);
16925f2d433Sxy150489 	hw = &Adapter->shared;
17025f2d433Sxy150489 
17125f2d433Sxy150489 	tx_ring = Adapter->tx_ring;
17225f2d433Sxy150489 	rx_ring = Adapter->rx_ring;
17357ef6f69Sguoqing zhu - Sun Microsystems - Beijing China #ifdef E1000G_DEBUG
17454e0d7a5SMiles Xu, Sun Microsystems 	rx_data = rx_ring->rx_data;
17557ef6f69Sguoqing zhu - Sun Microsystems - Beijing China #endif
17625f2d433Sxy150489 
17725f2d433Sxy150489 	rw_enter(&Adapter->chip_lock, RW_WRITER);
17808057504Sxy150489 
17908057504Sxy150489 	e1000g_ksp->reset_count.value.ul = Adapter->reset_count;
18008057504Sxy150489 
18125f2d433Sxy150489 	e1000g_ksp->rx_error.value.ul = rx_ring->stat_error;
18225f2d433Sxy150489 	e1000g_ksp->rx_allocb_fail.value.ul = rx_ring->stat_allocb_fail;
18346ebaa55SMiles Xu, Sun Microsystems 	e1000g_ksp->rx_size_error.value.ul = rx_ring->stat_size_error;
18425f2d433Sxy150489 
18525f2d433Sxy150489 	e1000g_ksp->tx_no_swpkt.value.ul = tx_ring->stat_no_swpkt;
18625f2d433Sxy150489 	e1000g_ksp->tx_no_desc.value.ul = tx_ring->stat_no_desc;
18725f2d433Sxy150489 	e1000g_ksp->tx_send_fail.value.ul = tx_ring->stat_send_fail;
18825f2d433Sxy150489 	e1000g_ksp->tx_reschedule.value.ul = tx_ring->stat_reschedule;
18925f2d433Sxy150489 	e1000g_ksp->tx_over_size.value.ul = tx_ring->stat_over_size;
19025f2d433Sxy150489 
19125f2d433Sxy150489 #ifdef E1000G_DEBUG
19225f2d433Sxy150489 	e1000g_ksp->rx_none.value.ul = rx_ring->stat_none;
19325f2d433Sxy150489 	e1000g_ksp->rx_multi_desc.value.ul = rx_ring->stat_multi_desc;
19425f2d433Sxy150489 	e1000g_ksp->rx_no_freepkt.value.ul = rx_ring->stat_no_freepkt;
19554e0d7a5SMiles Xu, Sun Microsystems 	if (rx_data != NULL)
19654e0d7a5SMiles Xu, Sun Microsystems 		e1000g_ksp->rx_avail_freepkt.value.ul = rx_data->avail_freepkt;
19725f2d433Sxy150489 
19825f2d433Sxy150489 	e1000g_ksp->tx_under_size.value.ul = tx_ring->stat_under_size;
19925f2d433Sxy150489 	e1000g_ksp->tx_exceed_frags.value.ul = tx_ring->stat_exceed_frags;
20025f2d433Sxy150489 	e1000g_ksp->tx_empty_frags.value.ul = tx_ring->stat_empty_frags;
20125f2d433Sxy150489 	e1000g_ksp->tx_recycle.value.ul = tx_ring->stat_recycle;
20225f2d433Sxy150489 	e1000g_ksp->tx_recycle_intr.value.ul = tx_ring->stat_recycle_intr;
20325f2d433Sxy150489 	e1000g_ksp->tx_recycle_retry.value.ul = tx_ring->stat_recycle_retry;
20425f2d433Sxy150489 	e1000g_ksp->tx_recycle_none.value.ul = tx_ring->stat_recycle_none;
20525f2d433Sxy150489 	e1000g_ksp->tx_copy.value.ul = tx_ring->stat_copy;
20625f2d433Sxy150489 	e1000g_ksp->tx_bind.value.ul = tx_ring->stat_bind;
20725f2d433Sxy150489 	e1000g_ksp->tx_multi_copy.value.ul = tx_ring->stat_multi_copy;
20825f2d433Sxy150489 	e1000g_ksp->tx_multi_cookie.value.ul = tx_ring->stat_multi_cookie;
20925f2d433Sxy150489 	e1000g_ksp->tx_lack_desc.value.ul = tx_ring->stat_lack_desc;
21025f2d433Sxy150489 #endif
21108057504Sxy150489 
21208057504Sxy150489 	/*
21308057504Sxy150489 	 * Standard Stats
21408057504Sxy150489 	 */
21525f2d433Sxy150489 	e1000g_ksp->Mpc.value.ul += E1000_READ_REG(hw, E1000_MPC);
21625f2d433Sxy150489 	e1000g_ksp->Rlec.value.ul += E1000_READ_REG(hw, E1000_RLEC);
21725f2d433Sxy150489 	e1000g_ksp->Xonrxc.value.ul += E1000_READ_REG(hw, E1000_XONRXC);
21825f2d433Sxy150489 	e1000g_ksp->Xontxc.value.ul += E1000_READ_REG(hw, E1000_XONTXC);
21925f2d433Sxy150489 	e1000g_ksp->Xoffrxc.value.ul += E1000_READ_REG(hw, E1000_XOFFRXC);
22025f2d433Sxy150489 	e1000g_ksp->Xofftxc.value.ul += E1000_READ_REG(hw, E1000_XOFFTXC);
22125f2d433Sxy150489 	e1000g_ksp->Fcruc.value.ul += E1000_READ_REG(hw, E1000_FCRUC);
22208057504Sxy150489 
22325f2d433Sxy150489 	if ((hw->mac.type != e1000_ich8lan) &&
2244d737963Sxiangtao you - Sun Microsystems - Beijing China 	    (hw->mac.type != e1000_ich9lan) &&
225caf05df5SMiles Xu, Sun Microsystems 	    (hw->mac.type != e1000_ich10lan) &&
226caf05df5SMiles Xu, Sun Microsystems 	    (hw->mac.type != e1000_pchlan)) {
22708057504Sxy150489 		e1000g_ksp->Symerrs.value.ul +=
22825f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_SYMERRS);
22947b7744cSyy150190 #ifdef E1000G_DEBUG
23008057504Sxy150489 		e1000g_ksp->Prc64.value.ul +=
23125f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_PRC64);
23208057504Sxy150489 		e1000g_ksp->Prc127.value.ul +=
23325f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_PRC127);
23408057504Sxy150489 		e1000g_ksp->Prc255.value.ul +=
23525f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_PRC255);
23608057504Sxy150489 		e1000g_ksp->Prc511.value.ul +=
23725f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_PRC511);
23808057504Sxy150489 		e1000g_ksp->Prc1023.value.ul +=
23925f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_PRC1023);
24008057504Sxy150489 		e1000g_ksp->Prc1522.value.ul +=
24125f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_PRC1522);
24208057504Sxy150489 
24325f2d433Sxy150489 		e1000g_ksp->Ptc64.value.ul +=
24425f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_PTC64);
24525f2d433Sxy150489 		e1000g_ksp->Ptc127.value.ul +=
24625f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_PTC127);
24725f2d433Sxy150489 		e1000g_ksp->Ptc255.value.ul +=
24825f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_PTC255);
24925f2d433Sxy150489 		e1000g_ksp->Ptc511.value.ul +=
25025f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_PTC511);
25125f2d433Sxy150489 		e1000g_ksp->Ptc1023.value.ul +=
25225f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_PTC1023);
25325f2d433Sxy150489 		e1000g_ksp->Ptc1522.value.ul +=
25425f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_PTC1522);
25547b7744cSyy150190 #endif
25625f2d433Sxy150489 	}
25708057504Sxy150489 
25825f2d433Sxy150489 	e1000g_ksp->Gprc.value.ul += E1000_READ_REG(hw, E1000_GPRC);
25925f2d433Sxy150489 	e1000g_ksp->Gptc.value.ul += E1000_READ_REG(hw, E1000_GPTC);
26025f2d433Sxy150489 	e1000g_ksp->Rfc.value.ul += E1000_READ_REG(hw, E1000_RFC);
261caf05df5SMiles Xu, Sun Microsystems 	e1000g_ksp->Tncrs.value.ul += e1000g_read_phy_stat(hw, E1000_TNCRS);
26225f2d433Sxy150489 	e1000g_ksp->Tsctc.value.ul += E1000_READ_REG(hw, E1000_TSCTC);
26325f2d433Sxy150489 	e1000g_ksp->Tsctfc.value.ul += E1000_READ_REG(hw, E1000_TSCTFC);
26425f2d433Sxy150489 
26525f2d433Sxy150489 	/*
26625f2d433Sxy150489 	 * Adaptive Calculations
26725f2d433Sxy150489 	 */
26825f2d433Sxy150489 	hw->mac.tx_packet_delta = E1000_READ_REG(hw, E1000_TPT);
269*29fd2c16SDavid Höppner 	Adapter->opackets += hw->mac.tx_packet_delta;
27008057504Sxy150489 
27108057504Sxy150489 	/*
27208057504Sxy150489 	 * The 64-bit register will reset whenever the upper
27308057504Sxy150489 	 * 32 bits are read. So we need to read the lower
27408057504Sxy150489 	 * 32 bits first, then read the upper 32 bits.
27508057504Sxy150489 	 */
27625f2d433Sxy150489 	low_val = E1000_READ_REG(hw, E1000_GORCL);
27725f2d433Sxy150489 	high_val = E1000_READ_REG(hw, E1000_GORCH);
27808057504Sxy150489 	val = (uint64_t)e1000g_ksp->Gorh.value.ul << 32 |
27908057504Sxy150489 	    (uint64_t)e1000g_ksp->Gorl.value.ul;
28008057504Sxy150489 	val += (uint64_t)high_val << 32 | (uint64_t)low_val;
28108057504Sxy150489 	e1000g_ksp->Gorl.value.ul = (uint32_t)val;
28208057504Sxy150489 	e1000g_ksp->Gorh.value.ul = (uint32_t)(val >> 32);
28308057504Sxy150489 
28425f2d433Sxy150489 	low_val = E1000_READ_REG(hw, E1000_GOTCL);
28525f2d433Sxy150489 	high_val = E1000_READ_REG(hw, E1000_GOTCH);
28608057504Sxy150489 	val = (uint64_t)e1000g_ksp->Goth.value.ul << 32 |
28708057504Sxy150489 	    (uint64_t)e1000g_ksp->Gotl.value.ul;
28808057504Sxy150489 	val += (uint64_t)high_val << 32 | (uint64_t)low_val;
28908057504Sxy150489 	e1000g_ksp->Gotl.value.ul = (uint32_t)val;
29008057504Sxy150489 	e1000g_ksp->Goth.value.ul = (uint32_t)(val >> 32);
29108057504Sxy150489 
29225f2d433Sxy150489 	low_val = E1000_READ_REG(hw, E1000_TORL);
29325f2d433Sxy150489 	high_val = E1000_READ_REG(hw, E1000_TORH);
294*29fd2c16SDavid Höppner 	Adapter->rbytes +=
295*29fd2c16SDavid Höppner 	    (uint64_t)high_val << 32 | (uint64_t)low_val;
29608057504Sxy150489 
29725f2d433Sxy150489 	low_val = E1000_READ_REG(hw, E1000_TOTL);
29825f2d433Sxy150489 	high_val = E1000_READ_REG(hw, E1000_TOTH);
299*29fd2c16SDavid Höppner 	Adapter->obytes +=
300*29fd2c16SDavid Höppner 	    (uint64_t)high_val << 32 | (uint64_t)low_val;
30108057504Sxy150489 
30225f2d433Sxy150489 	rw_exit(&Adapter->chip_lock);
30308057504Sxy150489 
304ec39b9cfSchangqing li - Sun Microsystems - Beijing China 	if (e1000g_check_acc_handle(Adapter->osdep.reg_handle) != DDI_FM_OK) {
3059b6541b3Sgl147354 		ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_UNAFFECTED);
306ec39b9cfSchangqing li - Sun Microsystems - Beijing China 		return (EIO);
307ec39b9cfSchangqing li - Sun Microsystems - Beijing China 	}
3089b6541b3Sgl147354 
30908057504Sxy150489 	return (0);
31008057504Sxy150489 }
31108057504Sxy150489 
31208057504Sxy150489 int
31308057504Sxy150489 e1000g_m_stat(void *arg, uint_t stat, uint64_t *val)
31408057504Sxy150489 {
31508057504Sxy150489 	struct e1000g *Adapter = (struct e1000g *)arg;
31625f2d433Sxy150489 	struct e1000_hw *hw = &Adapter->shared;
31725f2d433Sxy150489 	p_e1000g_stat_t e1000g_ksp;
31808057504Sxy150489 	uint32_t low_val, high_val;
31908057504Sxy150489 
32025f2d433Sxy150489 	e1000g_ksp = (p_e1000g_stat_t)Adapter->e1000g_ksp->ks_data;
32125f2d433Sxy150489 
3224914a7d0Syy150190 	rw_enter(&Adapter->chip_lock, RW_READER);
32308057504Sxy150489 
324d5c3073dSchenlu chen - Sun Microsystems - Beijing China 	if (Adapter->e1000g_state & E1000G_SUSPENDED) {
325d5c3073dSchenlu chen - Sun Microsystems - Beijing China 		rw_exit(&Adapter->chip_lock);
326d5c3073dSchenlu chen - Sun Microsystems - Beijing China 		return (ECANCELED);
327d5c3073dSchenlu chen - Sun Microsystems - Beijing China 	}
328d5c3073dSchenlu chen - Sun Microsystems - Beijing China 
32908057504Sxy150489 	switch (stat) {
33008057504Sxy150489 	case MAC_STAT_IFSPEED:
33108057504Sxy150489 		*val = Adapter->link_speed * 1000000ull;
33208057504Sxy150489 		break;
33308057504Sxy150489 
33408057504Sxy150489 	case MAC_STAT_MULTIRCV:
335*29fd2c16SDavid Höppner 		Adapter->multircv +=
33625f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_MPRC);
337*29fd2c16SDavid Höppner 		*val = Adapter->multircv;
33808057504Sxy150489 		break;
33908057504Sxy150489 
34008057504Sxy150489 	case MAC_STAT_BRDCSTRCV:
341*29fd2c16SDavid Höppner 		Adapter->brdcstrcv +=
34225f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_BPRC);
343*29fd2c16SDavid Höppner 		*val = Adapter->brdcstrcv;
34408057504Sxy150489 		break;
34508057504Sxy150489 
34608057504Sxy150489 	case MAC_STAT_MULTIXMT:
347*29fd2c16SDavid Höppner 		Adapter->multixmt +=
34825f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_MPTC);
349*29fd2c16SDavid Höppner 		*val = Adapter->multixmt;
35008057504Sxy150489 		break;
35108057504Sxy150489 
35208057504Sxy150489 	case MAC_STAT_BRDCSTXMT:
353*29fd2c16SDavid Höppner 		Adapter->brdcstxmt +=
35425f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_BPTC);
355*29fd2c16SDavid Höppner 		*val = Adapter->brdcstxmt;
35608057504Sxy150489 		break;
35708057504Sxy150489 
35808057504Sxy150489 	case MAC_STAT_NORCVBUF:
359*29fd2c16SDavid Höppner 		Adapter->norcvbuf +=
36025f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_RNBC);
361*29fd2c16SDavid Höppner 		*val = Adapter->norcvbuf;
36208057504Sxy150489 		break;
36308057504Sxy150489 
36408057504Sxy150489 	case MAC_STAT_IERRORS:
365*29fd2c16SDavid Höppner 		Adapter->macrcv_errors +=
36625f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_RXERRC);
367*29fd2c16SDavid Höppner 		Adapter->align_errors +=
36825f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_ALGNERRC);
36908057504Sxy150489 		e1000g_ksp->Rlec.value.ul +=
37025f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_RLEC);
371*29fd2c16SDavid Höppner 		Adapter->fcs_errors +=
37225f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_CRCERRS);
373*29fd2c16SDavid Höppner 		Adapter->carrier_errors +=
37425f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_CEXTERR);
375*29fd2c16SDavid Höppner 		*val = Adapter->macrcv_errors +
376*29fd2c16SDavid Höppner 		    Adapter->align_errors +
37708057504Sxy150489 		    e1000g_ksp->Rlec.value.ul +
378*29fd2c16SDavid Höppner 		    Adapter->fcs_errors +
379*29fd2c16SDavid Höppner 		    Adapter->carrier_errors;
38008057504Sxy150489 		break;
38108057504Sxy150489 
38208057504Sxy150489 	case MAC_STAT_NOXMTBUF:
38325f2d433Sxy150489 		*val = Adapter->tx_ring->stat_no_desc;
38408057504Sxy150489 		break;
38508057504Sxy150489 
38608057504Sxy150489 	case MAC_STAT_OERRORS:
387*29fd2c16SDavid Höppner 		Adapter->oerrors +=
388caf05df5SMiles Xu, Sun Microsystems 		    e1000g_read_phy_stat(hw, E1000_ECOL);
389*29fd2c16SDavid Höppner 		*val = Adapter->oerrors;
39008057504Sxy150489 		break;
39108057504Sxy150489 
39208057504Sxy150489 	case MAC_STAT_COLLISIONS:
393*29fd2c16SDavid Höppner 		Adapter->collisions +=
394caf05df5SMiles Xu, Sun Microsystems 		    e1000g_read_phy_stat(hw, E1000_COLC);
395*29fd2c16SDavid Höppner 		*val = Adapter->collisions;
39608057504Sxy150489 		break;
39708057504Sxy150489 
39808057504Sxy150489 	case MAC_STAT_RBYTES:
39908057504Sxy150489 		/*
40008057504Sxy150489 		 * The 64-bit register will reset whenever the upper
40108057504Sxy150489 		 * 32 bits are read. So we need to read the lower
40208057504Sxy150489 		 * 32 bits first, then read the upper 32 bits.
40308057504Sxy150489 		 */
40425f2d433Sxy150489 		low_val = E1000_READ_REG(hw, E1000_TORL);
40525f2d433Sxy150489 		high_val = E1000_READ_REG(hw, E1000_TORH);
406*29fd2c16SDavid Höppner 		Adapter->rbytes +=
407*29fd2c16SDavid Höppner 		    (uint64_t)high_val << 32 | (uint64_t)low_val;
408*29fd2c16SDavid Höppner 		*val = Adapter->rbytes;
40908057504Sxy150489 		break;
41008057504Sxy150489 
41108057504Sxy150489 	case MAC_STAT_IPACKETS:
412*29fd2c16SDavid Höppner 		Adapter->ipackets +=
41325f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_TPR);
414*29fd2c16SDavid Höppner 		*val = Adapter->ipackets;
41508057504Sxy150489 		break;
41608057504Sxy150489 
41708057504Sxy150489 	case MAC_STAT_OBYTES:
41808057504Sxy150489 		/*
41908057504Sxy150489 		 * The 64-bit register will reset whenever the upper
42008057504Sxy150489 		 * 32 bits are read. So we need to read the lower
42108057504Sxy150489 		 * 32 bits first, then read the upper 32 bits.
42208057504Sxy150489 		 */
42325f2d433Sxy150489 		low_val = E1000_READ_REG(hw, E1000_TOTL);
42425f2d433Sxy150489 		high_val = E1000_READ_REG(hw, E1000_TOTH);
425*29fd2c16SDavid Höppner 		Adapter->obytes +=
426*29fd2c16SDavid Höppner 		    (uint64_t)high_val << 32 | (uint64_t)low_val;
427*29fd2c16SDavid Höppner 		*val = Adapter->obytes;
42808057504Sxy150489 		break;
42908057504Sxy150489 
43008057504Sxy150489 	case MAC_STAT_OPACKETS:
431*29fd2c16SDavid Höppner 		Adapter->opackets +=
43225f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_TPT);
433*29fd2c16SDavid Höppner 		*val = Adapter->opackets;
43408057504Sxy150489 		break;
43508057504Sxy150489 
43608057504Sxy150489 	case ETHER_STAT_ALIGN_ERRORS:
437*29fd2c16SDavid Höppner 		Adapter->align_errors +=
43825f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_ALGNERRC);
439*29fd2c16SDavid Höppner 		*val = Adapter->align_errors;
44008057504Sxy150489 		break;
44108057504Sxy150489 
44208057504Sxy150489 	case ETHER_STAT_FCS_ERRORS:
443*29fd2c16SDavid Höppner 		Adapter->fcs_errors +=
44425f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_CRCERRS);
445*29fd2c16SDavid Höppner 		*val = Adapter->fcs_errors;
44608057504Sxy150489 		break;
44708057504Sxy150489 
44808057504Sxy150489 	case ETHER_STAT_SQE_ERRORS:
449*29fd2c16SDavid Höppner 		Adapter->sqe_errors +=
45025f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_SEC);
451*29fd2c16SDavid Höppner 		*val = Adapter->sqe_errors;
45208057504Sxy150489 		break;
45308057504Sxy150489 
45408057504Sxy150489 	case ETHER_STAT_CARRIER_ERRORS:
455*29fd2c16SDavid Höppner 		Adapter->carrier_errors +=
45625f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_CEXTERR);
457*29fd2c16SDavid Höppner 		*val = Adapter->carrier_errors;
45808057504Sxy150489 		break;
45908057504Sxy150489 
46008057504Sxy150489 	case ETHER_STAT_EX_COLLISIONS:
461*29fd2c16SDavid Höppner 		Adapter->ex_collisions +=
462caf05df5SMiles Xu, Sun Microsystems 		    e1000g_read_phy_stat(hw, E1000_ECOL);
463*29fd2c16SDavid Höppner 		*val = Adapter->ex_collisions;
46408057504Sxy150489 		break;
46508057504Sxy150489 
46608057504Sxy150489 	case ETHER_STAT_TX_LATE_COLLISIONS:
467*29fd2c16SDavid Höppner 		Adapter->tx_late_collisions +=
468caf05df5SMiles Xu, Sun Microsystems 		    e1000g_read_phy_stat(hw, E1000_LATECOL);
469*29fd2c16SDavid Höppner 		*val = Adapter->tx_late_collisions;
47008057504Sxy150489 		break;
47108057504Sxy150489 
47208057504Sxy150489 	case ETHER_STAT_DEFER_XMTS:
473*29fd2c16SDavid Höppner 		Adapter->defer_xmts +=
474caf05df5SMiles Xu, Sun Microsystems 		    e1000g_read_phy_stat(hw, E1000_DC);
475*29fd2c16SDavid Höppner 		*val = Adapter->defer_xmts;
47608057504Sxy150489 		break;
47708057504Sxy150489 
47808057504Sxy150489 	case ETHER_STAT_FIRST_COLLISIONS:
479*29fd2c16SDavid Höppner 		Adapter->first_collisions +=
480caf05df5SMiles Xu, Sun Microsystems 		    e1000g_read_phy_stat(hw, E1000_SCC);
481*29fd2c16SDavid Höppner 		*val = Adapter->first_collisions;
48208057504Sxy150489 		break;
48308057504Sxy150489 
48408057504Sxy150489 	case ETHER_STAT_MULTI_COLLISIONS:
485*29fd2c16SDavid Höppner 		Adapter->multi_collisions +=
486caf05df5SMiles Xu, Sun Microsystems 		    e1000g_read_phy_stat(hw, E1000_MCC);
487*29fd2c16SDavid Höppner 		*val = Adapter->multi_collisions;
48808057504Sxy150489 		break;
48908057504Sxy150489 
49008057504Sxy150489 	case ETHER_STAT_MACRCV_ERRORS:
491*29fd2c16SDavid Höppner 		Adapter->macrcv_errors +=
49225f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_RXERRC);
493*29fd2c16SDavid Höppner 		*val = Adapter->macrcv_errors;
49408057504Sxy150489 		break;
49508057504Sxy150489 
49608057504Sxy150489 	case ETHER_STAT_MACXMT_ERRORS:
497*29fd2c16SDavid Höppner 		Adapter->macxmt_errors +=
498caf05df5SMiles Xu, Sun Microsystems 		    e1000g_read_phy_stat(hw, E1000_ECOL);
499*29fd2c16SDavid Höppner 		*val = Adapter->macxmt_errors;
50008057504Sxy150489 		break;
50108057504Sxy150489 
50208057504Sxy150489 	case ETHER_STAT_TOOLONG_ERRORS:
503*29fd2c16SDavid Höppner 		Adapter->toolong_errors +=
50425f2d433Sxy150489 		    E1000_READ_REG(hw, E1000_ROC);
505*29fd2c16SDavid Höppner 		*val = Adapter->toolong_errors;
506*29fd2c16SDavid Höppner 		break;
507*29fd2c16SDavid Höppner 
508*29fd2c16SDavid Höppner 	case ETHER_STAT_TOOSHORT_ERRORS:
509*29fd2c16SDavid Höppner 		Adapter->tooshort_errors +=
510*29fd2c16SDavid Höppner 		    E1000_READ_REG(hw, E1000_RUC);
511*29fd2c16SDavid Höppner 		*val = Adapter->tooshort_errors;
512*29fd2c16SDavid Höppner 		break;
513*29fd2c16SDavid Höppner 
514*29fd2c16SDavid Höppner 	case ETHER_STAT_JABBER_ERRORS:
515*29fd2c16SDavid Höppner 		Adapter->jabber_errors +=
516*29fd2c16SDavid Höppner 		    E1000_READ_REG(hw, E1000_RJC);
517*29fd2c16SDavid Höppner 		*val = Adapter->jabber_errors;
51808057504Sxy150489 		break;
51908057504Sxy150489 
52008057504Sxy150489 	case ETHER_STAT_XCVR_ADDR:
52108057504Sxy150489 		/* The Internal PHY's MDI address for each MAC is 1 */
52208057504Sxy150489 		*val = 1;
52308057504Sxy150489 		break;
52408057504Sxy150489 
52508057504Sxy150489 	case ETHER_STAT_XCVR_ID:
5264914a7d0Syy150190 		*val = hw->phy.id | hw->phy.revision;
52708057504Sxy150489 		break;
52808057504Sxy150489 
52908057504Sxy150489 	case ETHER_STAT_XCVR_INUSE:
53008057504Sxy150489 		switch (Adapter->link_speed) {
53108057504Sxy150489 		case SPEED_1000:
53208057504Sxy150489 			*val =
533592a4d85Scc210113 			    (hw->phy.media_type == e1000_media_type_copper) ?
53425f2d433Sxy150489 			    XCVR_1000T : XCVR_1000X;
53508057504Sxy150489 			break;
53608057504Sxy150489 		case SPEED_100:
53708057504Sxy150489 			*val =
538592a4d85Scc210113 			    (hw->phy.media_type == e1000_media_type_copper) ?
5394914a7d0Syy150190 			    (Adapter->phy_status & MII_SR_100T4_CAPS) ?
54025f2d433Sxy150489 			    XCVR_100T4 : XCVR_100T2 : XCVR_100X;
54108057504Sxy150489 			break;
54208057504Sxy150489 		case SPEED_10:
54308057504Sxy150489 			*val = XCVR_10;
54408057504Sxy150489 			break;
54508057504Sxy150489 		default:
54608057504Sxy150489 			*val = XCVR_NONE;
54708057504Sxy150489 			break;
54808057504Sxy150489 		}
54908057504Sxy150489 		break;
55008057504Sxy150489 
55108057504Sxy150489 	case ETHER_STAT_CAP_1000FDX:
5529ce7e93cScc210113 		*val = Adapter->param_1000fdx_cap;
55308057504Sxy150489 		break;
55408057504Sxy150489 
55508057504Sxy150489 	case ETHER_STAT_CAP_1000HDX:
5569ce7e93cScc210113 		*val = Adapter->param_1000hdx_cap;
55708057504Sxy150489 		break;
55808057504Sxy150489 
55908057504Sxy150489 	case ETHER_STAT_CAP_100FDX:
5609ce7e93cScc210113 		*val = Adapter->param_100fdx_cap;
56108057504Sxy150489 		break;
56208057504Sxy150489 
56308057504Sxy150489 	case ETHER_STAT_CAP_100HDX:
5649ce7e93cScc210113 		*val = Adapter->param_100hdx_cap;
56508057504Sxy150489 		break;
56608057504Sxy150489 
56708057504Sxy150489 	case ETHER_STAT_CAP_10FDX:
5689ce7e93cScc210113 		*val = Adapter->param_10fdx_cap;
56908057504Sxy150489 		break;
57008057504Sxy150489 
57108057504Sxy150489 	case ETHER_STAT_CAP_10HDX:
5729ce7e93cScc210113 		*val = Adapter->param_10hdx_cap;
57308057504Sxy150489 		break;
57408057504Sxy150489 
57508057504Sxy150489 	case ETHER_STAT_CAP_ASMPAUSE:
5769ce7e93cScc210113 		*val = Adapter->param_asym_pause_cap;
57708057504Sxy150489 		break;
57808057504Sxy150489 
57908057504Sxy150489 	case ETHER_STAT_CAP_PAUSE:
5809ce7e93cScc210113 		*val = Adapter->param_pause_cap;
58108057504Sxy150489 		break;
58208057504Sxy150489 
58308057504Sxy150489 	case ETHER_STAT_CAP_AUTONEG:
5849ce7e93cScc210113 		*val = Adapter->param_autoneg_cap;
58508057504Sxy150489 		break;
58608057504Sxy150489 
58708057504Sxy150489 	case ETHER_STAT_ADV_CAP_1000FDX:
5889ce7e93cScc210113 		*val = Adapter->param_adv_1000fdx;
58908057504Sxy150489 		break;
59008057504Sxy150489 
59108057504Sxy150489 	case ETHER_STAT_ADV_CAP_1000HDX:
5929ce7e93cScc210113 		*val = Adapter->param_adv_1000hdx;
59308057504Sxy150489 		break;
59408057504Sxy150489 
59508057504Sxy150489 	case ETHER_STAT_ADV_CAP_100FDX:
5969ce7e93cScc210113 		*val = Adapter->param_adv_100fdx;
59708057504Sxy150489 		break;
59808057504Sxy150489 
59908057504Sxy150489 	case ETHER_STAT_ADV_CAP_100HDX:
6009ce7e93cScc210113 		*val = Adapter->param_adv_100hdx;
60108057504Sxy150489 		break;
60208057504Sxy150489 
60308057504Sxy150489 	case ETHER_STAT_ADV_CAP_10FDX:
6049ce7e93cScc210113 		*val = Adapter->param_adv_10fdx;
60508057504Sxy150489 		break;
60608057504Sxy150489 
60708057504Sxy150489 	case ETHER_STAT_ADV_CAP_10HDX:
6089ce7e93cScc210113 		*val = Adapter->param_adv_10hdx;
60908057504Sxy150489 		break;
61008057504Sxy150489 
61108057504Sxy150489 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
6129ce7e93cScc210113 		*val = Adapter->param_adv_asym_pause;
61308057504Sxy150489 		break;
61408057504Sxy150489 
61508057504Sxy150489 	case ETHER_STAT_ADV_CAP_PAUSE:
6169ce7e93cScc210113 		*val = Adapter->param_adv_pause;
61708057504Sxy150489 		break;
61808057504Sxy150489 
61908057504Sxy150489 	case ETHER_STAT_ADV_CAP_AUTONEG:
62025f2d433Sxy150489 		*val = hw->mac.autoneg;
62108057504Sxy150489 		break;
62208057504Sxy150489 
62308057504Sxy150489 	case ETHER_STAT_LP_CAP_1000FDX:
6249ce7e93cScc210113 		*val = Adapter->param_lp_1000fdx;
62508057504Sxy150489 		break;
62608057504Sxy150489 
62708057504Sxy150489 	case ETHER_STAT_LP_CAP_1000HDX:
6289ce7e93cScc210113 		*val = Adapter->param_lp_1000hdx;
62908057504Sxy150489 		break;
63008057504Sxy150489 
63108057504Sxy150489 	case ETHER_STAT_LP_CAP_100FDX:
6329ce7e93cScc210113 		*val = Adapter->param_lp_100fdx;
63308057504Sxy150489 		break;
63408057504Sxy150489 
63508057504Sxy150489 	case ETHER_STAT_LP_CAP_100HDX:
6369ce7e93cScc210113 		*val = Adapter->param_lp_100hdx;
63708057504Sxy150489 		break;
63808057504Sxy150489 
63908057504Sxy150489 	case ETHER_STAT_LP_CAP_10FDX:
6409ce7e93cScc210113 		*val = Adapter->param_lp_10fdx;
64108057504Sxy150489 		break;
64208057504Sxy150489 
64308057504Sxy150489 	case ETHER_STAT_LP_CAP_10HDX:
6449ce7e93cScc210113 		*val = Adapter->param_lp_10hdx;
64508057504Sxy150489 		break;
64608057504Sxy150489 
64708057504Sxy150489 	case ETHER_STAT_LP_CAP_ASMPAUSE:
6489ce7e93cScc210113 		*val = Adapter->param_lp_asym_pause;
64908057504Sxy150489 		break;
65008057504Sxy150489 
65108057504Sxy150489 	case ETHER_STAT_LP_CAP_PAUSE:
6529ce7e93cScc210113 		*val = Adapter->param_lp_pause;
65308057504Sxy150489 		break;
65408057504Sxy150489 
65508057504Sxy150489 	case ETHER_STAT_LP_CAP_AUTONEG:
6569ce7e93cScc210113 		*val = Adapter->param_lp_autoneg;
65708057504Sxy150489 		break;
65808057504Sxy150489 
65908057504Sxy150489 	case ETHER_STAT_LINK_ASMPAUSE:
6609ce7e93cScc210113 		*val = Adapter->param_asym_pause_cap;
66108057504Sxy150489 		break;
66208057504Sxy150489 
66308057504Sxy150489 	case ETHER_STAT_LINK_PAUSE:
6649ce7e93cScc210113 		*val = Adapter->param_pause_cap;
66508057504Sxy150489 		break;
66608057504Sxy150489 
66708057504Sxy150489 	case ETHER_STAT_LINK_AUTONEG:
6689ce7e93cScc210113 		*val = hw->mac.autoneg;
66908057504Sxy150489 		break;
67008057504Sxy150489 
67108057504Sxy150489 	case ETHER_STAT_LINK_DUPLEX:
67208057504Sxy150489 		*val = (Adapter->link_duplex == FULL_DUPLEX) ?
67308057504Sxy150489 		    LINK_DUPLEX_FULL : LINK_DUPLEX_HALF;
67408057504Sxy150489 		break;
67508057504Sxy150489 
6769ce7e93cScc210113 	case ETHER_STAT_CAP_100T4:
6779ce7e93cScc210113 		*val = Adapter->param_100t4_cap;
6789ce7e93cScc210113 		break;
6799ce7e93cScc210113 
6809ce7e93cScc210113 	case ETHER_STAT_ADV_CAP_100T4:
6819ce7e93cScc210113 		*val = Adapter->param_adv_100t4;
6829ce7e93cScc210113 		break;
6839ce7e93cScc210113 
6849ce7e93cScc210113 	case ETHER_STAT_LP_CAP_100T4:
6859ce7e93cScc210113 		*val = Adapter->param_lp_100t4;
6869ce7e93cScc210113 		break;
6879ce7e93cScc210113 
68808057504Sxy150489 	default:
68925f2d433Sxy150489 		rw_exit(&Adapter->chip_lock);
69008057504Sxy150489 		return (ENOTSUP);
69108057504Sxy150489 	}
69208057504Sxy150489 
69325f2d433Sxy150489 	rw_exit(&Adapter->chip_lock);
69425f2d433Sxy150489 
695ec39b9cfSchangqing li - Sun Microsystems - Beijing China 	if (e1000g_check_acc_handle(Adapter->osdep.reg_handle) != DDI_FM_OK) {
6969b6541b3Sgl147354 		ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_UNAFFECTED);
697ec39b9cfSchangqing li - Sun Microsystems - Beijing China 		return (EIO);
698ec39b9cfSchangqing li - Sun Microsystems - Beijing China 	}
6999b6541b3Sgl147354 
70008057504Sxy150489 	return (0);
70108057504Sxy150489 }
70208057504Sxy150489 
70308057504Sxy150489 /*
70425f2d433Sxy150489  * e1000g_init_stats - initialize kstat data structures
70525f2d433Sxy150489  *
70625f2d433Sxy150489  * This routine will create and initialize the driver private
70725f2d433Sxy150489  * statistics counters.
70808057504Sxy150489  */
70908057504Sxy150489 int
71025f2d433Sxy150489 e1000g_init_stats(struct e1000g *Adapter)
71108057504Sxy150489 {
71208057504Sxy150489 	kstat_t *ksp;
71325f2d433Sxy150489 	p_e1000g_stat_t e1000g_ksp;
71408057504Sxy150489 
71508057504Sxy150489 	/*
71608057504Sxy150489 	 * Create and init kstat
71708057504Sxy150489 	 */
71808057504Sxy150489 	ksp = kstat_create(WSNAME, ddi_get_instance(Adapter->dip),
71908057504Sxy150489 	    "statistics", "net", KSTAT_TYPE_NAMED,
72025f2d433Sxy150489 	    sizeof (e1000g_stat_t) / sizeof (kstat_named_t), 0);
72108057504Sxy150489 
72208057504Sxy150489 	if (ksp == NULL) {
72308057504Sxy150489 		e1000g_log(Adapter, CE_WARN,
72408057504Sxy150489 		    "Could not create kernel statistics\n");
72508057504Sxy150489 		return (DDI_FAILURE);
72608057504Sxy150489 	}
72708057504Sxy150489 
72808057504Sxy150489 	Adapter->e1000g_ksp = ksp;	/* Fill in the Adapters ksp */
72908057504Sxy150489 
73025f2d433Sxy150489 	e1000g_ksp = (p_e1000g_stat_t)ksp->ks_data;
73108057504Sxy150489 
73208057504Sxy150489 	/*
73308057504Sxy150489 	 * Initialize all the statistics
73408057504Sxy150489 	 */
73525f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->reset_count, "Reset Count",
73608057504Sxy150489 	    KSTAT_DATA_ULONG);
73708057504Sxy150489 
73808057504Sxy150489 	kstat_named_init(&e1000g_ksp->rx_error, "Rx Error",
73908057504Sxy150489 	    KSTAT_DATA_ULONG);
74008057504Sxy150489 	kstat_named_init(&e1000g_ksp->rx_allocb_fail, "Rx Allocb Failure",
74108057504Sxy150489 	    KSTAT_DATA_ULONG);
74246ebaa55SMiles Xu, Sun Microsystems 	kstat_named_init(&e1000g_ksp->rx_size_error, "Rx Size Error",
74346ebaa55SMiles Xu, Sun Microsystems 	    KSTAT_DATA_ULONG);
74408057504Sxy150489 
74508057504Sxy150489 	kstat_named_init(&e1000g_ksp->tx_no_desc, "Tx No Desc",
74608057504Sxy150489 	    KSTAT_DATA_ULONG);
74708057504Sxy150489 	kstat_named_init(&e1000g_ksp->tx_no_swpkt, "Tx No Buffer",
74808057504Sxy150489 	    KSTAT_DATA_ULONG);
74925f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->tx_send_fail, "Tx Send Failure",
75025f2d433Sxy150489 	    KSTAT_DATA_ULONG);
75125f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->tx_over_size, "Tx Pkt Over Size",
75225f2d433Sxy150489 	    KSTAT_DATA_ULONG);
75325f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->tx_reschedule, "Tx Reschedule",
75408057504Sxy150489 	    KSTAT_DATA_ULONG);
75508057504Sxy150489 
75625f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Mpc, "Recv_Missed_Packets",
75725f2d433Sxy150489 	    KSTAT_DATA_ULONG);
75825f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Symerrs, "Recv_Symbol_Errors",
75925f2d433Sxy150489 	    KSTAT_DATA_ULONG);
76025f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Rlec, "Recv_Length_Errors",
76125f2d433Sxy150489 	    KSTAT_DATA_ULONG);
76225f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Xonrxc, "XONs_Recvd",
76325f2d433Sxy150489 	    KSTAT_DATA_ULONG);
76425f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Xontxc, "XONs_Xmitd",
76525f2d433Sxy150489 	    KSTAT_DATA_ULONG);
76625f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Xoffrxc, "XOFFs_Recvd",
76725f2d433Sxy150489 	    KSTAT_DATA_ULONG);
76825f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Xofftxc, "XOFFs_Xmitd",
76925f2d433Sxy150489 	    KSTAT_DATA_ULONG);
77025f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Fcruc, "Recv_Unsupport_FC_Pkts",
77125f2d433Sxy150489 	    KSTAT_DATA_ULONG);
77247b7744cSyy150190 #ifdef E1000G_DEBUG
77325f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Prc64, "Pkts_Recvd_(  64b)",
77425f2d433Sxy150489 	    KSTAT_DATA_ULONG);
77525f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Prc127, "Pkts_Recvd_(  65- 127b)",
77625f2d433Sxy150489 	    KSTAT_DATA_ULONG);
77725f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Prc255, "Pkts_Recvd_( 127- 255b)",
77825f2d433Sxy150489 	    KSTAT_DATA_ULONG);
77925f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Prc511, "Pkts_Recvd_( 256- 511b)",
78025f2d433Sxy150489 	    KSTAT_DATA_ULONG);
78125f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Prc1023, "Pkts_Recvd_( 511-1023b)",
78225f2d433Sxy150489 	    KSTAT_DATA_ULONG);
78325f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Prc1522, "Pkts_Recvd_(1024-1522b)",
78425f2d433Sxy150489 	    KSTAT_DATA_ULONG);
78547b7744cSyy150190 #endif
78625f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Gprc, "Good_Pkts_Recvd",
78725f2d433Sxy150489 	    KSTAT_DATA_ULONG);
78825f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Gptc, "Good_Pkts_Xmitd",
78925f2d433Sxy150489 	    KSTAT_DATA_ULONG);
79025f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Gorl, "Good_Octets_Recvd_Lo",
79125f2d433Sxy150489 	    KSTAT_DATA_ULONG);
79225f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Gorh, "Good_Octets_Recvd_Hi",
79325f2d433Sxy150489 	    KSTAT_DATA_ULONG);
79425f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Gotl, "Good_Octets_Xmitd_Lo",
79525f2d433Sxy150489 	    KSTAT_DATA_ULONG);
79625f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Goth, "Good_Octets_Xmitd_Hi",
79725f2d433Sxy150489 	    KSTAT_DATA_ULONG);
79825f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Rfc, "Recv_Frag",
79925f2d433Sxy150489 	    KSTAT_DATA_ULONG);
80047b7744cSyy150190 #ifdef E1000G_DEBUG
80125f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Ptc64, "Pkts_Xmitd_(  64b)",
80225f2d433Sxy150489 	    KSTAT_DATA_ULONG);
80325f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Ptc127, "Pkts_Xmitd_(  65- 127b)",
80425f2d433Sxy150489 	    KSTAT_DATA_ULONG);
80525f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Ptc255, "Pkts_Xmitd_( 128- 255b)",
80625f2d433Sxy150489 	    KSTAT_DATA_ULONG);
80725f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Ptc511, "Pkts_Xmitd_( 255- 511b)",
80825f2d433Sxy150489 	    KSTAT_DATA_ULONG);
80925f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Ptc1023, "Pkts_Xmitd_( 512-1023b)",
81025f2d433Sxy150489 	    KSTAT_DATA_ULONG);
81125f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Ptc1522, "Pkts_Xmitd_(1024-1522b)",
81225f2d433Sxy150489 	    KSTAT_DATA_ULONG);
81347b7744cSyy150190 #endif
81425f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Tncrs, "Xmit_with_No_CRS",
81525f2d433Sxy150489 	    KSTAT_DATA_ULONG);
81625f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Tsctc, "Xmit_TCP_Seg_Contexts",
81725f2d433Sxy150489 	    KSTAT_DATA_ULONG);
81825f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->Tsctfc, "Xmit_TCP_Seg_Contexts_Fail",
81925f2d433Sxy150489 	    KSTAT_DATA_ULONG);
82008057504Sxy150489 
82125f2d433Sxy150489 #ifdef E1000G_DEBUG
82225f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->rx_none, "Rx No Data",
82325f2d433Sxy150489 	    KSTAT_DATA_ULONG);
82425f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->rx_multi_desc, "Rx Span Multi Desc",
82525f2d433Sxy150489 	    KSTAT_DATA_ULONG);
82625f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->rx_no_freepkt, "Rx Freelist Empty",
82725f2d433Sxy150489 	    KSTAT_DATA_ULONG);
82825f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->rx_avail_freepkt, "Rx Freelist Avail",
82908057504Sxy150489 	    KSTAT_DATA_ULONG);
83008057504Sxy150489 
83108057504Sxy150489 	kstat_named_init(&e1000g_ksp->tx_under_size, "Tx Pkt Under Size",
83208057504Sxy150489 	    KSTAT_DATA_ULONG);
83308057504Sxy150489 	kstat_named_init(&e1000g_ksp->tx_exceed_frags, "Tx Exceed Max Frags",
83408057504Sxy150489 	    KSTAT_DATA_ULONG);
83525f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->tx_empty_frags, "Tx Empty Frags",
83608057504Sxy150489 	    KSTAT_DATA_ULONG);
83725f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->tx_recycle, "Tx Recycle",
83808057504Sxy150489 	    KSTAT_DATA_ULONG);
83925f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->tx_recycle_intr, "Tx Recycle Intr",
84008057504Sxy150489 	    KSTAT_DATA_ULONG);
84125f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->tx_recycle_retry, "Tx Recycle Retry",
84208057504Sxy150489 	    KSTAT_DATA_ULONG);
84325f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->tx_recycle_none, "Tx Recycled None",
84408057504Sxy150489 	    KSTAT_DATA_ULONG);
84525f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->tx_copy, "Tx Send Copy",
84608057504Sxy150489 	    KSTAT_DATA_ULONG);
84725f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->tx_bind, "Tx Send Bind",
84808057504Sxy150489 	    KSTAT_DATA_ULONG);
84925f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->tx_multi_copy, "Tx Copy Multi Frags",
85008057504Sxy150489 	    KSTAT_DATA_ULONG);
85125f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->tx_multi_cookie, "Tx Bind Multi Cookies",
85208057504Sxy150489 	    KSTAT_DATA_ULONG);
85325f2d433Sxy150489 	kstat_named_init(&e1000g_ksp->tx_lack_desc, "Tx Desc Insufficient",
85408057504Sxy150489 	    KSTAT_DATA_ULONG);
85525f2d433Sxy150489 #endif
85608057504Sxy150489 
85708057504Sxy150489 	/*
85808057504Sxy150489 	 * Function to provide kernel stat update on demand
85908057504Sxy150489 	 */
86025f2d433Sxy150489 	ksp->ks_update = e1000g_update_stats;
86108057504Sxy150489 
86208057504Sxy150489 	/*
86308057504Sxy150489 	 * Pointer into provider's raw statistics
86408057504Sxy150489 	 */
86508057504Sxy150489 	ksp->ks_private = (void *)Adapter;
86608057504Sxy150489 
86708057504Sxy150489 	/*
86808057504Sxy150489 	 * Add kstat to systems kstat chain
86908057504Sxy150489 	 */
87008057504Sxy150489 	kstat_install(ksp);
87108057504Sxy150489 
87208057504Sxy150489 	return (DDI_SUCCESS);
87308057504Sxy150489 }
874caf05df5SMiles Xu, Sun Microsystems 
875caf05df5SMiles Xu, Sun Microsystems /*
876caf05df5SMiles Xu, Sun Microsystems  * e1000g_read_phy_stat - read certain PHY statistics
877caf05df5SMiles Xu, Sun Microsystems  *
878caf05df5SMiles Xu, Sun Microsystems  * Certain statistics are read from MAC registers on some silicon types
879caf05df5SMiles Xu, Sun Microsystems  * but are read from the PHY on other silicon types.  This routine
880caf05df5SMiles Xu, Sun Microsystems  * handles that difference as needed.
881caf05df5SMiles Xu, Sun Microsystems  */
882caf05df5SMiles Xu, Sun Microsystems static uint32_t
883caf05df5SMiles Xu, Sun Microsystems e1000g_read_phy_stat(struct e1000_hw *hw, int reg)
884caf05df5SMiles Xu, Sun Microsystems {
885caf05df5SMiles Xu, Sun Microsystems 	uint16_t phy_low, phy_high;
886caf05df5SMiles Xu, Sun Microsystems 	uint32_t val;
887caf05df5SMiles Xu, Sun Microsystems 
888caf05df5SMiles Xu, Sun Microsystems 	/* get statistic from PHY in these cases */
889caf05df5SMiles Xu, Sun Microsystems 	if ((hw->phy.type == e1000_phy_82578) ||
890caf05df5SMiles Xu, Sun Microsystems 	    (hw->phy.type == e1000_phy_82577)) {
891caf05df5SMiles Xu, Sun Microsystems 
892caf05df5SMiles Xu, Sun Microsystems 		switch (reg) {
893caf05df5SMiles Xu, Sun Microsystems 		case E1000_SCC:
894caf05df5SMiles Xu, Sun Microsystems 			(void) e1000_read_phy_reg(hw, HV_SCC_UPPER, &phy_high);
895caf05df5SMiles Xu, Sun Microsystems 			(void) e1000_read_phy_reg(hw, HV_SCC_LOWER, &phy_low);
896caf05df5SMiles Xu, Sun Microsystems 			val = ((uint32_t)phy_high << 16) | (uint32_t)phy_low;
897caf05df5SMiles Xu, Sun Microsystems 			break;
898caf05df5SMiles Xu, Sun Microsystems 
899caf05df5SMiles Xu, Sun Microsystems 		case E1000_MCC:
900caf05df5SMiles Xu, Sun Microsystems 			(void) e1000_read_phy_reg(hw, HV_MCC_UPPER, &phy_high);
901caf05df5SMiles Xu, Sun Microsystems 			(void) e1000_read_phy_reg(hw, HV_MCC_LOWER, &phy_low);
902caf05df5SMiles Xu, Sun Microsystems 			val = ((uint32_t)phy_high << 16) | (uint32_t)phy_low;
903caf05df5SMiles Xu, Sun Microsystems 			break;
904caf05df5SMiles Xu, Sun Microsystems 
905caf05df5SMiles Xu, Sun Microsystems 		case E1000_ECOL:
906caf05df5SMiles Xu, Sun Microsystems 			(void) e1000_read_phy_reg(hw, HV_ECOL_UPPER, &phy_high);
907caf05df5SMiles Xu, Sun Microsystems 			(void) e1000_read_phy_reg(hw, HV_ECOL_LOWER, &phy_low);
908caf05df5SMiles Xu, Sun Microsystems 			val = ((uint32_t)phy_high << 16) | (uint32_t)phy_low;
909caf05df5SMiles Xu, Sun Microsystems 			break;
910caf05df5SMiles Xu, Sun Microsystems 
911caf05df5SMiles Xu, Sun Microsystems 		case E1000_COLC:
912caf05df5SMiles Xu, Sun Microsystems 			(void) e1000_read_phy_reg(hw, HV_COLC_UPPER, &phy_high);
913caf05df5SMiles Xu, Sun Microsystems 			(void) e1000_read_phy_reg(hw, HV_COLC_LOWER, &phy_low);
914caf05df5SMiles Xu, Sun Microsystems 			val = ((uint32_t)phy_high << 16) | (uint32_t)phy_low;
915caf05df5SMiles Xu, Sun Microsystems 			break;
916caf05df5SMiles Xu, Sun Microsystems 
917caf05df5SMiles Xu, Sun Microsystems 		case E1000_LATECOL:
918caf05df5SMiles Xu, Sun Microsystems 			(void) e1000_read_phy_reg(hw, HV_LATECOL_UPPER,
919caf05df5SMiles Xu, Sun Microsystems 			    &phy_high);
920caf05df5SMiles Xu, Sun Microsystems 			(void) e1000_read_phy_reg(hw, HV_LATECOL_LOWER,
921caf05df5SMiles Xu, Sun Microsystems 			    &phy_low);
922caf05df5SMiles Xu, Sun Microsystems 			val = ((uint32_t)phy_high << 16) | (uint32_t)phy_low;
923caf05df5SMiles Xu, Sun Microsystems 			break;
924caf05df5SMiles Xu, Sun Microsystems 
925caf05df5SMiles Xu, Sun Microsystems 		case E1000_DC:
926caf05df5SMiles Xu, Sun Microsystems 			(void) e1000_read_phy_reg(hw, HV_DC_UPPER, &phy_high);
927caf05df5SMiles Xu, Sun Microsystems 			(void) e1000_read_phy_reg(hw, HV_DC_LOWER, &phy_low);
928caf05df5SMiles Xu, Sun Microsystems 			val = ((uint32_t)phy_high << 16) | (uint32_t)phy_low;
929caf05df5SMiles Xu, Sun Microsystems 			break;
930caf05df5SMiles Xu, Sun Microsystems 
931caf05df5SMiles Xu, Sun Microsystems 		case E1000_TNCRS:
932caf05df5SMiles Xu, Sun Microsystems 			(void) e1000_read_phy_reg(hw, HV_TNCRS_UPPER,
933caf05df5SMiles Xu, Sun Microsystems 			    &phy_high);
934caf05df5SMiles Xu, Sun Microsystems 			(void) e1000_read_phy_reg(hw, HV_TNCRS_LOWER,
935caf05df5SMiles Xu, Sun Microsystems 			    &phy_low);
936caf05df5SMiles Xu, Sun Microsystems 			val = ((uint32_t)phy_high << 16) | (uint32_t)phy_low;
937caf05df5SMiles Xu, Sun Microsystems 			break;
938caf05df5SMiles Xu, Sun Microsystems 
939caf05df5SMiles Xu, Sun Microsystems 		default:
940caf05df5SMiles Xu, Sun Microsystems 			break;
941caf05df5SMiles Xu, Sun Microsystems 		}
942caf05df5SMiles Xu, Sun Microsystems 
943caf05df5SMiles Xu, Sun Microsystems 	/* get statistic from MAC otherwise */
944caf05df5SMiles Xu, Sun Microsystems 	} else {
945caf05df5SMiles Xu, Sun Microsystems 		val = E1000_READ_REG(hw, reg);
946caf05df5SMiles Xu, Sun Microsystems 	}
947caf05df5SMiles Xu, Sun Microsystems 
948caf05df5SMiles Xu, Sun Microsystems 	return (val);
949caf05df5SMiles Xu, Sun Microsystems }
9500dc2366fSVenugopal Iyer 
9510dc2366fSVenugopal Iyer /*
9520dc2366fSVenugopal Iyer  * Retrieve a value for one of the statistics for a particular rx ring
9530dc2366fSVenugopal Iyer  */
9540dc2366fSVenugopal Iyer int
9550dc2366fSVenugopal Iyer e1000g_rx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
9560dc2366fSVenugopal Iyer {
9570dc2366fSVenugopal Iyer 	e1000g_rx_ring_t *rx_ring = (e1000g_rx_ring_t *)rh;
9580dc2366fSVenugopal Iyer 	struct e1000g *Adapter = rx_ring->adapter;
9590dc2366fSVenugopal Iyer 	struct e1000_hw *hw = &Adapter->shared;
9600dc2366fSVenugopal Iyer 	uint32_t low_val, high_val;
9610dc2366fSVenugopal Iyer 
9620dc2366fSVenugopal Iyer 	rw_enter(&Adapter->chip_lock, RW_READER);
9630dc2366fSVenugopal Iyer 
9640dc2366fSVenugopal Iyer 	if (Adapter->e1000g_state & E1000G_SUSPENDED) {
9650dc2366fSVenugopal Iyer 		rw_exit(&Adapter->chip_lock);
9660dc2366fSVenugopal Iyer 		return (ECANCELED);
9670dc2366fSVenugopal Iyer 	}
9680dc2366fSVenugopal Iyer 
9690dc2366fSVenugopal Iyer 	switch (stat) {
9700dc2366fSVenugopal Iyer 	case MAC_STAT_RBYTES:
9710dc2366fSVenugopal Iyer 		/*
9720dc2366fSVenugopal Iyer 		 * The 64-bit register will reset whenever the upper
9730dc2366fSVenugopal Iyer 		 * 32 bits are read. So we need to read the lower
9740dc2366fSVenugopal Iyer 		 * 32 bits first, then read the upper 32 bits.
9750dc2366fSVenugopal Iyer 		 */
9760dc2366fSVenugopal Iyer 		low_val = E1000_READ_REG(hw, E1000_TORL);
9770dc2366fSVenugopal Iyer 		high_val = E1000_READ_REG(hw, E1000_TORH);
978*29fd2c16SDavid Höppner 		Adapter->rbytes +=
979*29fd2c16SDavid Höppner 		    (uint64_t)high_val << 32 | (uint64_t)low_val;
980*29fd2c16SDavid Höppner 		*val = Adapter->rbytes;
9810dc2366fSVenugopal Iyer 		break;
9820dc2366fSVenugopal Iyer 
9830dc2366fSVenugopal Iyer 	case MAC_STAT_IPACKETS:
984*29fd2c16SDavid Höppner 		Adapter->ipackets +=
9850dc2366fSVenugopal Iyer 		    E1000_READ_REG(hw, E1000_TPR);
986*29fd2c16SDavid Höppner 		*val = Adapter->ipackets;
9870dc2366fSVenugopal Iyer 		break;
9880dc2366fSVenugopal Iyer 
9890dc2366fSVenugopal Iyer 	default:
9900dc2366fSVenugopal Iyer 		*val = 0;
9910dc2366fSVenugopal Iyer 		rw_exit(&Adapter->chip_lock);
9920dc2366fSVenugopal Iyer 		return (ENOTSUP);
9930dc2366fSVenugopal Iyer 	}
9940dc2366fSVenugopal Iyer 
9950dc2366fSVenugopal Iyer 	rw_exit(&Adapter->chip_lock);
9960dc2366fSVenugopal Iyer 
9970dc2366fSVenugopal Iyer 	if (e1000g_check_acc_handle(Adapter->osdep.reg_handle) != DDI_FM_OK)
9980dc2366fSVenugopal Iyer 		ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_UNAFFECTED);
9990dc2366fSVenugopal Iyer 
10000dc2366fSVenugopal Iyer 	return (0);
10010dc2366fSVenugopal Iyer }
1002