13526Sxy150489 /*
23526Sxy150489 * This file is provided under a CDDLv1 license. When using or
33526Sxy150489 * redistributing this file, you may do so under this license.
43526Sxy150489 * In redistributing this file this license must be included
53526Sxy150489 * and no other modification of this header file is permitted.
63526Sxy150489 *
73526Sxy150489 * CDDL LICENSE SUMMARY
83526Sxy150489 *
98479SChenlu.Chen@Sun.COM * Copyright(c) 1999 - 2009 Intel Corporation. All rights reserved.
103526Sxy150489 *
113526Sxy150489 * The contents of this file are subject to the terms of Version
123526Sxy150489 * 1.0 of the Common Development and Distribution License (the "License").
133526Sxy150489 *
143526Sxy150489 * You should have received a copy of the License with this software.
153526Sxy150489 * You can obtain a copy of the License at
163526Sxy150489 * http://www.opensolaris.org/os/licensing.
173526Sxy150489 * See the License for the specific language governing permissions
183526Sxy150489 * and limitations under the License.
193526Sxy150489 */
203526Sxy150489
213526Sxy150489 /*
22*11878SVenu.Iyer@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
238275SEric Cheng * Use is subject to license terms.
243526Sxy150489 */
253526Sxy150489
263526Sxy150489 /*
273526Sxy150489 * **********************************************************************
283526Sxy150489 * *
293526Sxy150489 * Module Name: e1000g_stat.c *
303526Sxy150489 * *
314919Sxy150489 * Abstract: Functions for processing statistics *
323526Sxy150489 * *
333526Sxy150489 * **********************************************************************
343526Sxy150489 */
353526Sxy150489 #include "e1000g_sw.h"
363526Sxy150489 #include "e1000g_debug.h"
373526Sxy150489
384919Sxy150489 static int e1000g_update_stats(kstat_t *ksp, int rw);
3910680SMin.Xu@Sun.COM static uint32_t e1000g_read_phy_stat(struct e1000_hw *hw, int reg);
403526Sxy150489
413526Sxy150489 /*
424919Sxy150489 * e1000_tbi_adjust_stats
434919Sxy150489 *
444919Sxy150489 * Adjusts statistic counters when a frame is accepted
454919Sxy150489 * under the TBI workaround. This function has been
464919Sxy150489 * adapted for Solaris from shared code.
473526Sxy150489 */
483526Sxy150489 void
e1000_tbi_adjust_stats(struct e1000g * Adapter,uint32_t frame_len,uint8_t * mac_addr)494919Sxy150489 e1000_tbi_adjust_stats(struct e1000g *Adapter,
504919Sxy150489 uint32_t frame_len, uint8_t *mac_addr)
513526Sxy150489 {
524919Sxy150489 uint32_t carry_bit;
534919Sxy150489 p_e1000g_stat_t e1000g_ksp;
543526Sxy150489
554919Sxy150489 e1000g_ksp = (p_e1000g_stat_t)Adapter->e1000g_ksp->ks_data;
563526Sxy150489
574919Sxy150489 /* First adjust the frame length */
584919Sxy150489 frame_len--;
594919Sxy150489
603526Sxy150489 /*
613526Sxy150489 * We need to adjust the statistics counters, since the hardware
623526Sxy150489 * counters overcount this packet as a CRC error and undercount
633526Sxy150489 * the packet as a good packet
643526Sxy150489 */
654919Sxy150489 /* This packet should not be counted as a CRC error */
663526Sxy150489 e1000g_ksp->Crcerrs.value.ul--;
674919Sxy150489 /* This packet does count as a Good Packet Received */
683526Sxy150489 e1000g_ksp->Gprc.value.ul++;
693526Sxy150489
703526Sxy150489 /*
713526Sxy150489 * Adjust the Good Octets received counters
723526Sxy150489 */
734919Sxy150489 carry_bit = 0x80000000 & e1000g_ksp->Gorl.value.ul;
744919Sxy150489 e1000g_ksp->Gorl.value.ul += frame_len;
753526Sxy150489 /*
763526Sxy150489 * If the high bit of Gorcl (the low 32 bits of the Good Octets
773526Sxy150489 * Received Count) was one before the addition,
783526Sxy150489 * AND it is zero after, then we lost the carry out,
793526Sxy150489 * need to add one to Gorch (Good Octets Received Count High).
803526Sxy150489 * This could be simplified if all environments supported
813526Sxy150489 * 64-bit integers.
823526Sxy150489 */
834919Sxy150489 if (carry_bit && ((e1000g_ksp->Gorl.value.ul & 0x80000000) == 0)) {
843526Sxy150489 e1000g_ksp->Gorh.value.ul++;
853526Sxy150489 }
863526Sxy150489 /*
873526Sxy150489 * Is this a broadcast or multicast? Check broadcast first,
883526Sxy150489 * since the test for a multicast frame will test positive on
893526Sxy150489 * a broadcast frame.
903526Sxy150489 */
914919Sxy150489 if ((mac_addr[0] == (uint8_t)0xff) &&
924919Sxy150489 (mac_addr[1] == (uint8_t)0xff)) {
933526Sxy150489 /*
943526Sxy150489 * Broadcast packet
953526Sxy150489 */
963526Sxy150489 e1000g_ksp->Bprc.value.ul++;
974919Sxy150489 } else if (*mac_addr & 0x01) {
983526Sxy150489 /*
993526Sxy150489 * Multicast packet
1003526Sxy150489 */
1013526Sxy150489 e1000g_ksp->Mprc.value.ul++;
1023526Sxy150489 }
1034919Sxy150489
1046735Scc210113 if (frame_len == Adapter->max_frame_size) {
1053526Sxy150489 /*
1063526Sxy150489 * In this case, the hardware has overcounted the number of
1073526Sxy150489 * oversize frames.
1083526Sxy150489 */
1093526Sxy150489 if (e1000g_ksp->Roc.value.ul > 0)
1103526Sxy150489 e1000g_ksp->Roc.value.ul--;
1113526Sxy150489 }
1123526Sxy150489
1135882Syy150190 #ifdef E1000G_DEBUG
1143526Sxy150489 /*
1153526Sxy150489 * Adjust the bin counters when the extra byte put the frame in the
1164919Sxy150489 * wrong bin. Remember that the frame_len was adjusted above.
1173526Sxy150489 */
1184919Sxy150489 if (frame_len == 64) {
1193526Sxy150489 e1000g_ksp->Prc64.value.ul++;
1203526Sxy150489 e1000g_ksp->Prc127.value.ul--;
1214919Sxy150489 } else if (frame_len == 127) {
1223526Sxy150489 e1000g_ksp->Prc127.value.ul++;
1233526Sxy150489 e1000g_ksp->Prc255.value.ul--;
1244919Sxy150489 } else if (frame_len == 255) {
1253526Sxy150489 e1000g_ksp->Prc255.value.ul++;
1263526Sxy150489 e1000g_ksp->Prc511.value.ul--;
1274919Sxy150489 } else if (frame_len == 511) {
1283526Sxy150489 e1000g_ksp->Prc511.value.ul++;
1293526Sxy150489 e1000g_ksp->Prc1023.value.ul--;
1304919Sxy150489 } else if (frame_len == 1023) {
1313526Sxy150489 e1000g_ksp->Prc1023.value.ul++;
1323526Sxy150489 e1000g_ksp->Prc1522.value.ul--;
1334919Sxy150489 } else if (frame_len == 1522) {
1343526Sxy150489 e1000g_ksp->Prc1522.value.ul++;
1353526Sxy150489 }
1365882Syy150190 #endif
1373526Sxy150489 }
1383526Sxy150489
1393526Sxy150489
1403526Sxy150489 /*
1414919Sxy150489 * e1000g_update_stats - update driver private kstat counters
1424919Sxy150489 *
1434919Sxy150489 * This routine will dump and reset the e1000's internal
1444919Sxy150489 * statistics counters. The current stats dump values will
1454919Sxy150489 * be sent to the kernel status area.
1463526Sxy150489 */
1473526Sxy150489 static int
e1000g_update_stats(kstat_t * ksp,int rw)1484919Sxy150489 e1000g_update_stats(kstat_t *ksp, int rw)
1493526Sxy150489 {
1503526Sxy150489 struct e1000g *Adapter;
1514919Sxy150489 struct e1000_hw *hw;
1524919Sxy150489 p_e1000g_stat_t e1000g_ksp;
1534919Sxy150489 e1000g_tx_ring_t *tx_ring;
1544919Sxy150489 e1000g_rx_ring_t *rx_ring;
15511143SGuoqing.Zhu@Sun.COM #ifdef E1000G_DEBUG
1568850SMin.Xu@Sun.COM e1000g_rx_data_t *rx_data;
15711143SGuoqing.Zhu@Sun.COM #endif
1583526Sxy150489 uint64_t val;
1593526Sxy150489 uint32_t low_val, high_val;
1603526Sxy150489
1613526Sxy150489 if (rw == KSTAT_WRITE)
1623526Sxy150489 return (EACCES);
1633526Sxy150489
1643526Sxy150489 Adapter = (struct e1000g *)ksp->ks_private;
1653526Sxy150489 ASSERT(Adapter != NULL);
1664919Sxy150489 e1000g_ksp = (p_e1000g_stat_t)ksp->ks_data;
1673526Sxy150489 ASSERT(e1000g_ksp != NULL);
1684919Sxy150489 hw = &Adapter->shared;
1694919Sxy150489
1704919Sxy150489 tx_ring = Adapter->tx_ring;
1714919Sxy150489 rx_ring = Adapter->rx_ring;
17211143SGuoqing.Zhu@Sun.COM #ifdef E1000G_DEBUG
1738850SMin.Xu@Sun.COM rx_data = rx_ring->rx_data;
17411143SGuoqing.Zhu@Sun.COM #endif
1754919Sxy150489
1764919Sxy150489 rw_enter(&Adapter->chip_lock, RW_WRITER);
1773526Sxy150489
1783526Sxy150489 e1000g_ksp->link_speed.value.ul = Adapter->link_speed;
1793526Sxy150489 e1000g_ksp->reset_count.value.ul = Adapter->reset_count;
1804919Sxy150489
1814919Sxy150489 e1000g_ksp->rx_error.value.ul = rx_ring->stat_error;
1824919Sxy150489 e1000g_ksp->rx_allocb_fail.value.ul = rx_ring->stat_allocb_fail;
1838995SMin.Xu@Sun.COM e1000g_ksp->rx_size_error.value.ul = rx_ring->stat_size_error;
1844919Sxy150489
1854919Sxy150489 e1000g_ksp->tx_no_swpkt.value.ul = tx_ring->stat_no_swpkt;
1864919Sxy150489 e1000g_ksp->tx_no_desc.value.ul = tx_ring->stat_no_desc;
1874919Sxy150489 e1000g_ksp->tx_send_fail.value.ul = tx_ring->stat_send_fail;
1884919Sxy150489 e1000g_ksp->tx_reschedule.value.ul = tx_ring->stat_reschedule;
1894919Sxy150489 e1000g_ksp->tx_over_size.value.ul = tx_ring->stat_over_size;
1903526Sxy150489
1914919Sxy150489 #ifdef E1000G_DEBUG
1924919Sxy150489 e1000g_ksp->rx_none.value.ul = rx_ring->stat_none;
1934919Sxy150489 e1000g_ksp->rx_multi_desc.value.ul = rx_ring->stat_multi_desc;
1944919Sxy150489 e1000g_ksp->rx_no_freepkt.value.ul = rx_ring->stat_no_freepkt;
1958850SMin.Xu@Sun.COM if (rx_data != NULL)
1968850SMin.Xu@Sun.COM e1000g_ksp->rx_avail_freepkt.value.ul = rx_data->avail_freepkt;
1974919Sxy150489
1984919Sxy150489 e1000g_ksp->tx_under_size.value.ul = tx_ring->stat_under_size;
1994919Sxy150489 e1000g_ksp->tx_exceed_frags.value.ul = tx_ring->stat_exceed_frags;
2004919Sxy150489 e1000g_ksp->tx_empty_frags.value.ul = tx_ring->stat_empty_frags;
2014919Sxy150489 e1000g_ksp->tx_recycle.value.ul = tx_ring->stat_recycle;
2024919Sxy150489 e1000g_ksp->tx_recycle_intr.value.ul = tx_ring->stat_recycle_intr;
2034919Sxy150489 e1000g_ksp->tx_recycle_retry.value.ul = tx_ring->stat_recycle_retry;
2044919Sxy150489 e1000g_ksp->tx_recycle_none.value.ul = tx_ring->stat_recycle_none;
2054919Sxy150489 e1000g_ksp->tx_copy.value.ul = tx_ring->stat_copy;
2064919Sxy150489 e1000g_ksp->tx_bind.value.ul = tx_ring->stat_bind;
2074919Sxy150489 e1000g_ksp->tx_multi_copy.value.ul = tx_ring->stat_multi_copy;
2084919Sxy150489 e1000g_ksp->tx_multi_cookie.value.ul = tx_ring->stat_multi_cookie;
2094919Sxy150489 e1000g_ksp->tx_lack_desc.value.ul = tx_ring->stat_lack_desc;
2104919Sxy150489 #endif
2113526Sxy150489
2123526Sxy150489 /*
2133526Sxy150489 * Standard Stats
2143526Sxy150489 */
2154919Sxy150489 e1000g_ksp->Mpc.value.ul += E1000_READ_REG(hw, E1000_MPC);
2164919Sxy150489 e1000g_ksp->Rlec.value.ul += E1000_READ_REG(hw, E1000_RLEC);
2174919Sxy150489 e1000g_ksp->Xonrxc.value.ul += E1000_READ_REG(hw, E1000_XONRXC);
2184919Sxy150489 e1000g_ksp->Xontxc.value.ul += E1000_READ_REG(hw, E1000_XONTXC);
2194919Sxy150489 e1000g_ksp->Xoffrxc.value.ul += E1000_READ_REG(hw, E1000_XOFFRXC);
2204919Sxy150489 e1000g_ksp->Xofftxc.value.ul += E1000_READ_REG(hw, E1000_XOFFTXC);
2214919Sxy150489 e1000g_ksp->Fcruc.value.ul += E1000_READ_REG(hw, E1000_FCRUC);
2223526Sxy150489
2234919Sxy150489 if ((hw->mac.type != e1000_ich8lan) &&
2247607STed.You@Sun.COM (hw->mac.type != e1000_ich9lan) &&
22510680SMin.Xu@Sun.COM (hw->mac.type != e1000_ich10lan) &&
22610680SMin.Xu@Sun.COM (hw->mac.type != e1000_pchlan)) {
2274919Sxy150489 e1000g_ksp->Symerrs.value.ul +=
2284919Sxy150489 E1000_READ_REG(hw, E1000_SYMERRS);
2295882Syy150190 #ifdef E1000G_DEBUG
2304919Sxy150489 e1000g_ksp->Prc64.value.ul +=
2314919Sxy150489 E1000_READ_REG(hw, E1000_PRC64);
2324919Sxy150489 e1000g_ksp->Prc127.value.ul +=
2334919Sxy150489 E1000_READ_REG(hw, E1000_PRC127);
2344919Sxy150489 e1000g_ksp->Prc255.value.ul +=
2354919Sxy150489 E1000_READ_REG(hw, E1000_PRC255);
2364919Sxy150489 e1000g_ksp->Prc511.value.ul +=
2374919Sxy150489 E1000_READ_REG(hw, E1000_PRC511);
2384919Sxy150489 e1000g_ksp->Prc1023.value.ul +=
2394919Sxy150489 E1000_READ_REG(hw, E1000_PRC1023);
2404919Sxy150489 e1000g_ksp->Prc1522.value.ul +=
2414919Sxy150489 E1000_READ_REG(hw, E1000_PRC1522);
2423526Sxy150489
2434919Sxy150489 e1000g_ksp->Ptc64.value.ul +=
2444919Sxy150489 E1000_READ_REG(hw, E1000_PTC64);
2454919Sxy150489 e1000g_ksp->Ptc127.value.ul +=
2464919Sxy150489 E1000_READ_REG(hw, E1000_PTC127);
2474919Sxy150489 e1000g_ksp->Ptc255.value.ul +=
2484919Sxy150489 E1000_READ_REG(hw, E1000_PTC255);
2494919Sxy150489 e1000g_ksp->Ptc511.value.ul +=
2504919Sxy150489 E1000_READ_REG(hw, E1000_PTC511);
2514919Sxy150489 e1000g_ksp->Ptc1023.value.ul +=
2524919Sxy150489 E1000_READ_REG(hw, E1000_PTC1023);
2534919Sxy150489 e1000g_ksp->Ptc1522.value.ul +=
2544919Sxy150489 E1000_READ_REG(hw, E1000_PTC1522);
2555882Syy150190 #endif
2564919Sxy150489 }
2573526Sxy150489
2584919Sxy150489 e1000g_ksp->Gprc.value.ul += E1000_READ_REG(hw, E1000_GPRC);
2594919Sxy150489 e1000g_ksp->Gptc.value.ul += E1000_READ_REG(hw, E1000_GPTC);
2604919Sxy150489 e1000g_ksp->Ruc.value.ul += E1000_READ_REG(hw, E1000_RUC);
2614919Sxy150489 e1000g_ksp->Rfc.value.ul += E1000_READ_REG(hw, E1000_RFC);
2624919Sxy150489 e1000g_ksp->Roc.value.ul += E1000_READ_REG(hw, E1000_ROC);
2634919Sxy150489 e1000g_ksp->Rjc.value.ul += E1000_READ_REG(hw, E1000_RJC);
2644919Sxy150489 e1000g_ksp->Tpr.value.ul += E1000_READ_REG(hw, E1000_TPR);
26510680SMin.Xu@Sun.COM e1000g_ksp->Tncrs.value.ul += e1000g_read_phy_stat(hw, E1000_TNCRS);
2664919Sxy150489 e1000g_ksp->Tsctc.value.ul += E1000_READ_REG(hw, E1000_TSCTC);
2674919Sxy150489 e1000g_ksp->Tsctfc.value.ul += E1000_READ_REG(hw, E1000_TSCTFC);
2683526Sxy150489
2694919Sxy150489 /*
2704919Sxy150489 * Adaptive Calculations
2714919Sxy150489 */
2724919Sxy150489 hw->mac.tx_packet_delta = E1000_READ_REG(hw, E1000_TPT);
2734919Sxy150489 e1000g_ksp->Tpt.value.ul += hw->mac.tx_packet_delta;
2743526Sxy150489
2753526Sxy150489 /*
2763526Sxy150489 * The 64-bit register will reset whenever the upper
2773526Sxy150489 * 32 bits are read. So we need to read the lower
2783526Sxy150489 * 32 bits first, then read the upper 32 bits.
2793526Sxy150489 */
2804919Sxy150489 low_val = E1000_READ_REG(hw, E1000_GORCL);
2814919Sxy150489 high_val = E1000_READ_REG(hw, E1000_GORCH);
2823526Sxy150489 val = (uint64_t)e1000g_ksp->Gorh.value.ul << 32 |
2833526Sxy150489 (uint64_t)e1000g_ksp->Gorl.value.ul;
2843526Sxy150489 val += (uint64_t)high_val << 32 | (uint64_t)low_val;
2853526Sxy150489 e1000g_ksp->Gorl.value.ul = (uint32_t)val;
2863526Sxy150489 e1000g_ksp->Gorh.value.ul = (uint32_t)(val >> 32);
2873526Sxy150489
2884919Sxy150489 low_val = E1000_READ_REG(hw, E1000_GOTCL);
2894919Sxy150489 high_val = E1000_READ_REG(hw, E1000_GOTCH);
2903526Sxy150489 val = (uint64_t)e1000g_ksp->Goth.value.ul << 32 |
2913526Sxy150489 (uint64_t)e1000g_ksp->Gotl.value.ul;
2923526Sxy150489 val += (uint64_t)high_val << 32 | (uint64_t)low_val;
2933526Sxy150489 e1000g_ksp->Gotl.value.ul = (uint32_t)val;
2943526Sxy150489 e1000g_ksp->Goth.value.ul = (uint32_t)(val >> 32);
2953526Sxy150489
2964919Sxy150489 low_val = E1000_READ_REG(hw, E1000_TORL);
2974919Sxy150489 high_val = E1000_READ_REG(hw, E1000_TORH);
2983526Sxy150489 val = (uint64_t)e1000g_ksp->Torh.value.ul << 32 |
2993526Sxy150489 (uint64_t)e1000g_ksp->Torl.value.ul;
3003526Sxy150489 val += (uint64_t)high_val << 32 | (uint64_t)low_val;
3013526Sxy150489 e1000g_ksp->Torl.value.ul = (uint32_t)val;
3023526Sxy150489 e1000g_ksp->Torh.value.ul = (uint32_t)(val >> 32);
3033526Sxy150489
3044919Sxy150489 low_val = E1000_READ_REG(hw, E1000_TOTL);
3054919Sxy150489 high_val = E1000_READ_REG(hw, E1000_TOTH);
3063526Sxy150489 val = (uint64_t)e1000g_ksp->Toth.value.ul << 32 |
3073526Sxy150489 (uint64_t)e1000g_ksp->Totl.value.ul;
3083526Sxy150489 val += (uint64_t)high_val << 32 | (uint64_t)low_val;
3093526Sxy150489 e1000g_ksp->Totl.value.ul = (uint32_t)val;
3103526Sxy150489 e1000g_ksp->Toth.value.ul = (uint32_t)(val >> 32);
3113526Sxy150489
3124919Sxy150489 rw_exit(&Adapter->chip_lock);
3133526Sxy150489
31410805SChangqing.Li@Sun.COM if (e1000g_check_acc_handle(Adapter->osdep.reg_handle) != DDI_FM_OK) {
3155273Sgl147354 ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_UNAFFECTED);
31610805SChangqing.Li@Sun.COM return (EIO);
31710805SChangqing.Li@Sun.COM }
3185273Sgl147354
3193526Sxy150489 return (0);
3203526Sxy150489 }
3213526Sxy150489
3223526Sxy150489 int
e1000g_m_stat(void * arg,uint_t stat,uint64_t * val)3233526Sxy150489 e1000g_m_stat(void *arg, uint_t stat, uint64_t *val)
3243526Sxy150489 {
3253526Sxy150489 struct e1000g *Adapter = (struct e1000g *)arg;
3264919Sxy150489 struct e1000_hw *hw = &Adapter->shared;
3274919Sxy150489 p_e1000g_stat_t e1000g_ksp;
3283526Sxy150489 uint32_t low_val, high_val;
3293526Sxy150489
3304919Sxy150489 e1000g_ksp = (p_e1000g_stat_t)Adapter->e1000g_ksp->ks_data;
3314919Sxy150489
3325082Syy150190 rw_enter(&Adapter->chip_lock, RW_READER);
3333526Sxy150489
3348479SChenlu.Chen@Sun.COM if (Adapter->e1000g_state & E1000G_SUSPENDED) {
3358479SChenlu.Chen@Sun.COM rw_exit(&Adapter->chip_lock);
3368479SChenlu.Chen@Sun.COM return (ECANCELED);
3378479SChenlu.Chen@Sun.COM }
3388479SChenlu.Chen@Sun.COM
3393526Sxy150489 switch (stat) {
3403526Sxy150489 case MAC_STAT_IFSPEED:
3413526Sxy150489 *val = Adapter->link_speed * 1000000ull;
3423526Sxy150489 break;
3433526Sxy150489
3443526Sxy150489 case MAC_STAT_MULTIRCV:
3453526Sxy150489 e1000g_ksp->Mprc.value.ul +=
3464919Sxy150489 E1000_READ_REG(hw, E1000_MPRC);
3473526Sxy150489 *val = e1000g_ksp->Mprc.value.ul;
3483526Sxy150489 break;
3493526Sxy150489
3503526Sxy150489 case MAC_STAT_BRDCSTRCV:
3513526Sxy150489 e1000g_ksp->Bprc.value.ul +=
3524919Sxy150489 E1000_READ_REG(hw, E1000_BPRC);
3533526Sxy150489 *val = e1000g_ksp->Bprc.value.ul;
3543526Sxy150489 break;
3553526Sxy150489
3563526Sxy150489 case MAC_STAT_MULTIXMT:
3573526Sxy150489 e1000g_ksp->Mptc.value.ul +=
3584919Sxy150489 E1000_READ_REG(hw, E1000_MPTC);
3593526Sxy150489 *val = e1000g_ksp->Mptc.value.ul;
3603526Sxy150489 break;
3613526Sxy150489
3623526Sxy150489 case MAC_STAT_BRDCSTXMT:
3633526Sxy150489 e1000g_ksp->Bptc.value.ul +=
3644919Sxy150489 E1000_READ_REG(hw, E1000_BPTC);
3653526Sxy150489 *val = e1000g_ksp->Bptc.value.ul;
3663526Sxy150489 break;
3673526Sxy150489
3683526Sxy150489 case MAC_STAT_NORCVBUF:
3693526Sxy150489 e1000g_ksp->Rnbc.value.ul +=
3704919Sxy150489 E1000_READ_REG(hw, E1000_RNBC);
3713526Sxy150489 *val = e1000g_ksp->Rnbc.value.ul;
3723526Sxy150489 break;
3733526Sxy150489
3743526Sxy150489 case MAC_STAT_IERRORS:
3753526Sxy150489 e1000g_ksp->Rxerrc.value.ul +=
3764919Sxy150489 E1000_READ_REG(hw, E1000_RXERRC);
3773526Sxy150489 e1000g_ksp->Algnerrc.value.ul +=
3784919Sxy150489 E1000_READ_REG(hw, E1000_ALGNERRC);
3793526Sxy150489 e1000g_ksp->Rlec.value.ul +=
3804919Sxy150489 E1000_READ_REG(hw, E1000_RLEC);
3813526Sxy150489 e1000g_ksp->Crcerrs.value.ul +=
3824919Sxy150489 E1000_READ_REG(hw, E1000_CRCERRS);
3833526Sxy150489 e1000g_ksp->Cexterr.value.ul +=
3844919Sxy150489 E1000_READ_REG(hw, E1000_CEXTERR);
3853526Sxy150489 *val = e1000g_ksp->Rxerrc.value.ul +
3863526Sxy150489 e1000g_ksp->Algnerrc.value.ul +
3873526Sxy150489 e1000g_ksp->Rlec.value.ul +
3883526Sxy150489 e1000g_ksp->Crcerrs.value.ul +
3893526Sxy150489 e1000g_ksp->Cexterr.value.ul;
3903526Sxy150489 break;
3913526Sxy150489
3923526Sxy150489 case MAC_STAT_NOXMTBUF:
3934919Sxy150489 *val = Adapter->tx_ring->stat_no_desc;
3943526Sxy150489 break;
3953526Sxy150489
3963526Sxy150489 case MAC_STAT_OERRORS:
3973526Sxy150489 e1000g_ksp->Ecol.value.ul +=
39810680SMin.Xu@Sun.COM e1000g_read_phy_stat(hw, E1000_ECOL);
3993526Sxy150489 *val = e1000g_ksp->Ecol.value.ul;
4003526Sxy150489 break;
4013526Sxy150489
4023526Sxy150489 case MAC_STAT_COLLISIONS:
4033526Sxy150489 e1000g_ksp->Colc.value.ul +=
40410680SMin.Xu@Sun.COM e1000g_read_phy_stat(hw, E1000_COLC);
4053526Sxy150489 *val = e1000g_ksp->Colc.value.ul;
4063526Sxy150489 break;
4073526Sxy150489
4083526Sxy150489 case MAC_STAT_RBYTES:
4093526Sxy150489 /*
4103526Sxy150489 * The 64-bit register will reset whenever the upper
4113526Sxy150489 * 32 bits are read. So we need to read the lower
4123526Sxy150489 * 32 bits first, then read the upper 32 bits.
4133526Sxy150489 */
4144919Sxy150489 low_val = E1000_READ_REG(hw, E1000_TORL);
4154919Sxy150489 high_val = E1000_READ_REG(hw, E1000_TORH);
4163526Sxy150489 *val = (uint64_t)e1000g_ksp->Torh.value.ul << 32 |
4173526Sxy150489 (uint64_t)e1000g_ksp->Torl.value.ul;
4183526Sxy150489 *val += (uint64_t)high_val << 32 | (uint64_t)low_val;
4193526Sxy150489
4203526Sxy150489 e1000g_ksp->Torl.value.ul = (uint32_t)*val;
4213526Sxy150489 e1000g_ksp->Torh.value.ul = (uint32_t)(*val >> 32);
4223526Sxy150489 break;
4233526Sxy150489
4243526Sxy150489 case MAC_STAT_IPACKETS:
4253526Sxy150489 e1000g_ksp->Tpr.value.ul +=
4264919Sxy150489 E1000_READ_REG(hw, E1000_TPR);
4273526Sxy150489 *val = e1000g_ksp->Tpr.value.ul;
4283526Sxy150489 break;
4293526Sxy150489
4303526Sxy150489 case MAC_STAT_OBYTES:
4313526Sxy150489 /*
4323526Sxy150489 * The 64-bit register will reset whenever the upper
4333526Sxy150489 * 32 bits are read. So we need to read the lower
4343526Sxy150489 * 32 bits first, then read the upper 32 bits.
4353526Sxy150489 */
4364919Sxy150489 low_val = E1000_READ_REG(hw, E1000_TOTL);
4374919Sxy150489 high_val = E1000_READ_REG(hw, E1000_TOTH);
4383526Sxy150489 *val = (uint64_t)e1000g_ksp->Toth.value.ul << 32 |
4393526Sxy150489 (uint64_t)e1000g_ksp->Totl.value.ul;
4403526Sxy150489 *val += (uint64_t)high_val << 32 | (uint64_t)low_val;
4413526Sxy150489
4423526Sxy150489 e1000g_ksp->Totl.value.ul = (uint32_t)*val;
4433526Sxy150489 e1000g_ksp->Toth.value.ul = (uint32_t)(*val >> 32);
4443526Sxy150489 break;
4453526Sxy150489
4463526Sxy150489 case MAC_STAT_OPACKETS:
4473526Sxy150489 e1000g_ksp->Tpt.value.ul +=
4484919Sxy150489 E1000_READ_REG(hw, E1000_TPT);
4493526Sxy150489 *val = e1000g_ksp->Tpt.value.ul;
4503526Sxy150489 break;
4513526Sxy150489
4523526Sxy150489 case ETHER_STAT_ALIGN_ERRORS:
4533526Sxy150489 e1000g_ksp->Algnerrc.value.ul +=
4544919Sxy150489 E1000_READ_REG(hw, E1000_ALGNERRC);
4553526Sxy150489 *val = e1000g_ksp->Algnerrc.value.ul;
4563526Sxy150489 break;
4573526Sxy150489
4583526Sxy150489 case ETHER_STAT_FCS_ERRORS:
4593526Sxy150489 e1000g_ksp->Crcerrs.value.ul +=
4604919Sxy150489 E1000_READ_REG(hw, E1000_CRCERRS);
4613526Sxy150489 *val = e1000g_ksp->Crcerrs.value.ul;
4623526Sxy150489 break;
4633526Sxy150489
4643526Sxy150489 case ETHER_STAT_SQE_ERRORS:
4653526Sxy150489 e1000g_ksp->Sec.value.ul +=
4664919Sxy150489 E1000_READ_REG(hw, E1000_SEC);
4673526Sxy150489 *val = e1000g_ksp->Sec.value.ul;
4683526Sxy150489 break;
4693526Sxy150489
4703526Sxy150489 case ETHER_STAT_CARRIER_ERRORS:
4713526Sxy150489 e1000g_ksp->Cexterr.value.ul +=
4724919Sxy150489 E1000_READ_REG(hw, E1000_CEXTERR);
4733526Sxy150489 *val = e1000g_ksp->Cexterr.value.ul;
4743526Sxy150489 break;
4753526Sxy150489
4763526Sxy150489 case ETHER_STAT_EX_COLLISIONS:
4773526Sxy150489 e1000g_ksp->Ecol.value.ul +=
47810680SMin.Xu@Sun.COM e1000g_read_phy_stat(hw, E1000_ECOL);
4793526Sxy150489 *val = e1000g_ksp->Ecol.value.ul;
4803526Sxy150489 break;
4813526Sxy150489
4823526Sxy150489 case ETHER_STAT_TX_LATE_COLLISIONS:
4833526Sxy150489 e1000g_ksp->Latecol.value.ul +=
48410680SMin.Xu@Sun.COM e1000g_read_phy_stat(hw, E1000_LATECOL);
4853526Sxy150489 *val = e1000g_ksp->Latecol.value.ul;
4863526Sxy150489 break;
4873526Sxy150489
4883526Sxy150489 case ETHER_STAT_DEFER_XMTS:
4893526Sxy150489 e1000g_ksp->Dc.value.ul +=
49010680SMin.Xu@Sun.COM e1000g_read_phy_stat(hw, E1000_DC);
4913526Sxy150489 *val = e1000g_ksp->Dc.value.ul;
4923526Sxy150489 break;
4933526Sxy150489
4943526Sxy150489 case ETHER_STAT_FIRST_COLLISIONS:
4953526Sxy150489 e1000g_ksp->Scc.value.ul +=
49610680SMin.Xu@Sun.COM e1000g_read_phy_stat(hw, E1000_SCC);
4973526Sxy150489 *val = e1000g_ksp->Scc.value.ul;
4983526Sxy150489 break;
4993526Sxy150489
5003526Sxy150489 case ETHER_STAT_MULTI_COLLISIONS:
5013526Sxy150489 e1000g_ksp->Mcc.value.ul +=
50210680SMin.Xu@Sun.COM e1000g_read_phy_stat(hw, E1000_MCC);
5033526Sxy150489 *val = e1000g_ksp->Mcc.value.ul;
5043526Sxy150489 break;
5053526Sxy150489
5063526Sxy150489 case ETHER_STAT_MACRCV_ERRORS:
5073526Sxy150489 e1000g_ksp->Rxerrc.value.ul +=
5084919Sxy150489 E1000_READ_REG(hw, E1000_RXERRC);
5093526Sxy150489 *val = e1000g_ksp->Rxerrc.value.ul;
5103526Sxy150489 break;
5113526Sxy150489
5123526Sxy150489 case ETHER_STAT_MACXMT_ERRORS:
5133526Sxy150489 e1000g_ksp->Ecol.value.ul +=
51410680SMin.Xu@Sun.COM e1000g_read_phy_stat(hw, E1000_ECOL);
5153526Sxy150489 *val = e1000g_ksp->Ecol.value.ul;
5163526Sxy150489 break;
5173526Sxy150489
5183526Sxy150489 case ETHER_STAT_TOOLONG_ERRORS:
5193526Sxy150489 e1000g_ksp->Roc.value.ul +=
5204919Sxy150489 E1000_READ_REG(hw, E1000_ROC);
5213526Sxy150489 *val = e1000g_ksp->Roc.value.ul;
5223526Sxy150489 break;
5233526Sxy150489
5243526Sxy150489 case ETHER_STAT_XCVR_ADDR:
5253526Sxy150489 /* The Internal PHY's MDI address for each MAC is 1 */
5263526Sxy150489 *val = 1;
5273526Sxy150489 break;
5283526Sxy150489
5293526Sxy150489 case ETHER_STAT_XCVR_ID:
5305082Syy150190 *val = hw->phy.id | hw->phy.revision;
5313526Sxy150489 break;
5323526Sxy150489
5333526Sxy150489 case ETHER_STAT_XCVR_INUSE:
5343526Sxy150489 switch (Adapter->link_speed) {
5353526Sxy150489 case SPEED_1000:
5363526Sxy150489 *val =
5376735Scc210113 (hw->phy.media_type == e1000_media_type_copper) ?
5384919Sxy150489 XCVR_1000T : XCVR_1000X;
5393526Sxy150489 break;
5403526Sxy150489 case SPEED_100:
5413526Sxy150489 *val =
5426735Scc210113 (hw->phy.media_type == e1000_media_type_copper) ?
5435082Syy150190 (Adapter->phy_status & MII_SR_100T4_CAPS) ?
5444919Sxy150489 XCVR_100T4 : XCVR_100T2 : XCVR_100X;
5453526Sxy150489 break;
5463526Sxy150489 case SPEED_10:
5473526Sxy150489 *val = XCVR_10;
5483526Sxy150489 break;
5493526Sxy150489 default:
5503526Sxy150489 *val = XCVR_NONE;
5513526Sxy150489 break;
5523526Sxy150489 }
5533526Sxy150489 break;
5543526Sxy150489
5553526Sxy150489 case ETHER_STAT_CAP_1000FDX:
5566394Scc210113 *val = Adapter->param_1000fdx_cap;
5573526Sxy150489 break;
5583526Sxy150489
5593526Sxy150489 case ETHER_STAT_CAP_1000HDX:
5606394Scc210113 *val = Adapter->param_1000hdx_cap;
5613526Sxy150489 break;
5623526Sxy150489
5633526Sxy150489 case ETHER_STAT_CAP_100FDX:
5646394Scc210113 *val = Adapter->param_100fdx_cap;
5653526Sxy150489 break;
5663526Sxy150489
5673526Sxy150489 case ETHER_STAT_CAP_100HDX:
5686394Scc210113 *val = Adapter->param_100hdx_cap;
5693526Sxy150489 break;
5703526Sxy150489
5713526Sxy150489 case ETHER_STAT_CAP_10FDX:
5726394Scc210113 *val = Adapter->param_10fdx_cap;
5733526Sxy150489 break;
5743526Sxy150489
5753526Sxy150489 case ETHER_STAT_CAP_10HDX:
5766394Scc210113 *val = Adapter->param_10hdx_cap;
5773526Sxy150489 break;
5783526Sxy150489
5793526Sxy150489 case ETHER_STAT_CAP_ASMPAUSE:
5806394Scc210113 *val = Adapter->param_asym_pause_cap;
5813526Sxy150489 break;
5823526Sxy150489
5833526Sxy150489 case ETHER_STAT_CAP_PAUSE:
5846394Scc210113 *val = Adapter->param_pause_cap;
5853526Sxy150489 break;
5863526Sxy150489
5873526Sxy150489 case ETHER_STAT_CAP_AUTONEG:
5886394Scc210113 *val = Adapter->param_autoneg_cap;
5893526Sxy150489 break;
5903526Sxy150489
5913526Sxy150489 case ETHER_STAT_ADV_CAP_1000FDX:
5926394Scc210113 *val = Adapter->param_adv_1000fdx;
5933526Sxy150489 break;
5943526Sxy150489
5953526Sxy150489 case ETHER_STAT_ADV_CAP_1000HDX:
5966394Scc210113 *val = Adapter->param_adv_1000hdx;
5973526Sxy150489 break;
5983526Sxy150489
5993526Sxy150489 case ETHER_STAT_ADV_CAP_100FDX:
6006394Scc210113 *val = Adapter->param_adv_100fdx;
6013526Sxy150489 break;
6023526Sxy150489
6033526Sxy150489 case ETHER_STAT_ADV_CAP_100HDX:
6046394Scc210113 *val = Adapter->param_adv_100hdx;
6053526Sxy150489 break;
6063526Sxy150489
6073526Sxy150489 case ETHER_STAT_ADV_CAP_10FDX:
6086394Scc210113 *val = Adapter->param_adv_10fdx;
6093526Sxy150489 break;
6103526Sxy150489
6113526Sxy150489 case ETHER_STAT_ADV_CAP_10HDX:
6126394Scc210113 *val = Adapter->param_adv_10hdx;
6133526Sxy150489 break;
6143526Sxy150489
6153526Sxy150489 case ETHER_STAT_ADV_CAP_ASMPAUSE:
6166394Scc210113 *val = Adapter->param_adv_asym_pause;
6173526Sxy150489 break;
6183526Sxy150489
6193526Sxy150489 case ETHER_STAT_ADV_CAP_PAUSE:
6206394Scc210113 *val = Adapter->param_adv_pause;
6213526Sxy150489 break;
6223526Sxy150489
6233526Sxy150489 case ETHER_STAT_ADV_CAP_AUTONEG:
6244919Sxy150489 *val = hw->mac.autoneg;
6253526Sxy150489 break;
6263526Sxy150489
6273526Sxy150489 case ETHER_STAT_LP_CAP_1000FDX:
6286394Scc210113 *val = Adapter->param_lp_1000fdx;
6293526Sxy150489 break;
6303526Sxy150489
6313526Sxy150489 case ETHER_STAT_LP_CAP_1000HDX:
6326394Scc210113 *val = Adapter->param_lp_1000hdx;
6333526Sxy150489 break;
6343526Sxy150489
6353526Sxy150489 case ETHER_STAT_LP_CAP_100FDX:
6366394Scc210113 *val = Adapter->param_lp_100fdx;
6373526Sxy150489 break;
6383526Sxy150489
6393526Sxy150489 case ETHER_STAT_LP_CAP_100HDX:
6406394Scc210113 *val = Adapter->param_lp_100hdx;
6413526Sxy150489 break;
6423526Sxy150489
6433526Sxy150489 case ETHER_STAT_LP_CAP_10FDX:
6446394Scc210113 *val = Adapter->param_lp_10fdx;
6453526Sxy150489 break;
6463526Sxy150489
6473526Sxy150489 case ETHER_STAT_LP_CAP_10HDX:
6486394Scc210113 *val = Adapter->param_lp_10hdx;
6493526Sxy150489 break;
6503526Sxy150489
6513526Sxy150489 case ETHER_STAT_LP_CAP_ASMPAUSE:
6526394Scc210113 *val = Adapter->param_lp_asym_pause;
6533526Sxy150489 break;
6543526Sxy150489
6553526Sxy150489 case ETHER_STAT_LP_CAP_PAUSE:
6566394Scc210113 *val = Adapter->param_lp_pause;
6573526Sxy150489 break;
6583526Sxy150489
6593526Sxy150489 case ETHER_STAT_LP_CAP_AUTONEG:
6606394Scc210113 *val = Adapter->param_lp_autoneg;
6613526Sxy150489 break;
6623526Sxy150489
6633526Sxy150489 case ETHER_STAT_LINK_ASMPAUSE:
6646394Scc210113 *val = Adapter->param_asym_pause_cap;
6653526Sxy150489 break;
6663526Sxy150489
6673526Sxy150489 case ETHER_STAT_LINK_PAUSE:
6686394Scc210113 *val = Adapter->param_pause_cap;
6693526Sxy150489 break;
6703526Sxy150489
6713526Sxy150489 case ETHER_STAT_LINK_AUTONEG:
6726394Scc210113 *val = hw->mac.autoneg;
6733526Sxy150489 break;
6743526Sxy150489
6753526Sxy150489 case ETHER_STAT_LINK_DUPLEX:
6763526Sxy150489 *val = (Adapter->link_duplex == FULL_DUPLEX) ?
6773526Sxy150489 LINK_DUPLEX_FULL : LINK_DUPLEX_HALF;
6783526Sxy150489 break;
6793526Sxy150489
6806394Scc210113 case ETHER_STAT_CAP_100T4:
6816394Scc210113 *val = Adapter->param_100t4_cap;
6826394Scc210113 break;
6836394Scc210113
6846394Scc210113 case ETHER_STAT_ADV_CAP_100T4:
6856394Scc210113 *val = Adapter->param_adv_100t4;
6866394Scc210113 break;
6876394Scc210113
6886394Scc210113 case ETHER_STAT_LP_CAP_100T4:
6896394Scc210113 *val = Adapter->param_lp_100t4;
6906394Scc210113 break;
6916394Scc210113
6923526Sxy150489 default:
6934919Sxy150489 rw_exit(&Adapter->chip_lock);
6943526Sxy150489 return (ENOTSUP);
6953526Sxy150489 }
6963526Sxy150489
6974919Sxy150489 rw_exit(&Adapter->chip_lock);
6984919Sxy150489
69910805SChangqing.Li@Sun.COM if (e1000g_check_acc_handle(Adapter->osdep.reg_handle) != DDI_FM_OK) {
7005273Sgl147354 ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_UNAFFECTED);
70110805SChangqing.Li@Sun.COM return (EIO);
70210805SChangqing.Li@Sun.COM }
7035273Sgl147354
7043526Sxy150489 return (0);
7053526Sxy150489 }
7063526Sxy150489
7073526Sxy150489 /*
7084919Sxy150489 * e1000g_init_stats - initialize kstat data structures
7094919Sxy150489 *
7104919Sxy150489 * This routine will create and initialize the driver private
7114919Sxy150489 * statistics counters.
7123526Sxy150489 */
7133526Sxy150489 int
e1000g_init_stats(struct e1000g * Adapter)7144919Sxy150489 e1000g_init_stats(struct e1000g *Adapter)
7153526Sxy150489 {
7163526Sxy150489 kstat_t *ksp;
7174919Sxy150489 p_e1000g_stat_t e1000g_ksp;
7183526Sxy150489
7193526Sxy150489 /*
7203526Sxy150489 * Create and init kstat
7213526Sxy150489 */
7223526Sxy150489 ksp = kstat_create(WSNAME, ddi_get_instance(Adapter->dip),
7233526Sxy150489 "statistics", "net", KSTAT_TYPE_NAMED,
7244919Sxy150489 sizeof (e1000g_stat_t) / sizeof (kstat_named_t), 0);
7253526Sxy150489
7263526Sxy150489 if (ksp == NULL) {
7273526Sxy150489 e1000g_log(Adapter, CE_WARN,
7283526Sxy150489 "Could not create kernel statistics\n");
7293526Sxy150489 return (DDI_FAILURE);
7303526Sxy150489 }
7313526Sxy150489
7323526Sxy150489 Adapter->e1000g_ksp = ksp; /* Fill in the Adapters ksp */
7333526Sxy150489
7344919Sxy150489 e1000g_ksp = (p_e1000g_stat_t)ksp->ks_data;
7353526Sxy150489
7363526Sxy150489 /*
7373526Sxy150489 * Initialize all the statistics
7383526Sxy150489 */
7393526Sxy150489 kstat_named_init(&e1000g_ksp->link_speed, "link_speed",
7403526Sxy150489 KSTAT_DATA_ULONG);
7414919Sxy150489 kstat_named_init(&e1000g_ksp->reset_count, "Reset Count",
7423526Sxy150489 KSTAT_DATA_ULONG);
7433526Sxy150489
7443526Sxy150489 kstat_named_init(&e1000g_ksp->rx_error, "Rx Error",
7453526Sxy150489 KSTAT_DATA_ULONG);
7463526Sxy150489 kstat_named_init(&e1000g_ksp->rx_allocb_fail, "Rx Allocb Failure",
7473526Sxy150489 KSTAT_DATA_ULONG);
7488995SMin.Xu@Sun.COM kstat_named_init(&e1000g_ksp->rx_size_error, "Rx Size Error",
7498995SMin.Xu@Sun.COM KSTAT_DATA_ULONG);
7503526Sxy150489
7513526Sxy150489 kstat_named_init(&e1000g_ksp->tx_no_desc, "Tx No Desc",
7523526Sxy150489 KSTAT_DATA_ULONG);
7533526Sxy150489 kstat_named_init(&e1000g_ksp->tx_no_swpkt, "Tx No Buffer",
7543526Sxy150489 KSTAT_DATA_ULONG);
7554919Sxy150489 kstat_named_init(&e1000g_ksp->tx_send_fail, "Tx Send Failure",
7564919Sxy150489 KSTAT_DATA_ULONG);
7574919Sxy150489 kstat_named_init(&e1000g_ksp->tx_over_size, "Tx Pkt Over Size",
7584919Sxy150489 KSTAT_DATA_ULONG);
7594919Sxy150489 kstat_named_init(&e1000g_ksp->tx_reschedule, "Tx Reschedule",
7603526Sxy150489 KSTAT_DATA_ULONG);
7613526Sxy150489
7624919Sxy150489 kstat_named_init(&e1000g_ksp->Mpc, "Recv_Missed_Packets",
7634919Sxy150489 KSTAT_DATA_ULONG);
7644919Sxy150489 kstat_named_init(&e1000g_ksp->Symerrs, "Recv_Symbol_Errors",
7654919Sxy150489 KSTAT_DATA_ULONG);
7664919Sxy150489 kstat_named_init(&e1000g_ksp->Rlec, "Recv_Length_Errors",
7674919Sxy150489 KSTAT_DATA_ULONG);
7684919Sxy150489 kstat_named_init(&e1000g_ksp->Xonrxc, "XONs_Recvd",
7694919Sxy150489 KSTAT_DATA_ULONG);
7704919Sxy150489 kstat_named_init(&e1000g_ksp->Xontxc, "XONs_Xmitd",
7714919Sxy150489 KSTAT_DATA_ULONG);
7724919Sxy150489 kstat_named_init(&e1000g_ksp->Xoffrxc, "XOFFs_Recvd",
7734919Sxy150489 KSTAT_DATA_ULONG);
7744919Sxy150489 kstat_named_init(&e1000g_ksp->Xofftxc, "XOFFs_Xmitd",
7754919Sxy150489 KSTAT_DATA_ULONG);
7764919Sxy150489 kstat_named_init(&e1000g_ksp->Fcruc, "Recv_Unsupport_FC_Pkts",
7774919Sxy150489 KSTAT_DATA_ULONG);
7785882Syy150190 #ifdef E1000G_DEBUG
7794919Sxy150489 kstat_named_init(&e1000g_ksp->Prc64, "Pkts_Recvd_( 64b)",
7804919Sxy150489 KSTAT_DATA_ULONG);
7814919Sxy150489 kstat_named_init(&e1000g_ksp->Prc127, "Pkts_Recvd_( 65- 127b)",
7824919Sxy150489 KSTAT_DATA_ULONG);
7834919Sxy150489 kstat_named_init(&e1000g_ksp->Prc255, "Pkts_Recvd_( 127- 255b)",
7844919Sxy150489 KSTAT_DATA_ULONG);
7854919Sxy150489 kstat_named_init(&e1000g_ksp->Prc511, "Pkts_Recvd_( 256- 511b)",
7864919Sxy150489 KSTAT_DATA_ULONG);
7874919Sxy150489 kstat_named_init(&e1000g_ksp->Prc1023, "Pkts_Recvd_( 511-1023b)",
7884919Sxy150489 KSTAT_DATA_ULONG);
7894919Sxy150489 kstat_named_init(&e1000g_ksp->Prc1522, "Pkts_Recvd_(1024-1522b)",
7904919Sxy150489 KSTAT_DATA_ULONG);
7915882Syy150190 #endif
7924919Sxy150489 kstat_named_init(&e1000g_ksp->Gprc, "Good_Pkts_Recvd",
7934919Sxy150489 KSTAT_DATA_ULONG);
7944919Sxy150489 kstat_named_init(&e1000g_ksp->Gptc, "Good_Pkts_Xmitd",
7954919Sxy150489 KSTAT_DATA_ULONG);
7964919Sxy150489 kstat_named_init(&e1000g_ksp->Gorl, "Good_Octets_Recvd_Lo",
7974919Sxy150489 KSTAT_DATA_ULONG);
7984919Sxy150489 kstat_named_init(&e1000g_ksp->Gorh, "Good_Octets_Recvd_Hi",
7994919Sxy150489 KSTAT_DATA_ULONG);
8004919Sxy150489 kstat_named_init(&e1000g_ksp->Gotl, "Good_Octets_Xmitd_Lo",
8014919Sxy150489 KSTAT_DATA_ULONG);
8024919Sxy150489 kstat_named_init(&e1000g_ksp->Goth, "Good_Octets_Xmitd_Hi",
8034919Sxy150489 KSTAT_DATA_ULONG);
8044919Sxy150489 kstat_named_init(&e1000g_ksp->Ruc, "Recv_Undersize",
8054919Sxy150489 KSTAT_DATA_ULONG);
8064919Sxy150489 kstat_named_init(&e1000g_ksp->Rfc, "Recv_Frag",
8074919Sxy150489 KSTAT_DATA_ULONG);
8084919Sxy150489 kstat_named_init(&e1000g_ksp->Roc, "Recv_Oversize",
8094919Sxy150489 KSTAT_DATA_ULONG);
8104919Sxy150489 kstat_named_init(&e1000g_ksp->Rjc, "Recv_Jabber",
8114919Sxy150489 KSTAT_DATA_ULONG);
8124919Sxy150489 kstat_named_init(&e1000g_ksp->Torl, "Total_Octets_Recvd_Lo",
8134919Sxy150489 KSTAT_DATA_ULONG);
8144919Sxy150489 kstat_named_init(&e1000g_ksp->Torh, "Total_Octets_Recvd_Hi",
8154919Sxy150489 KSTAT_DATA_ULONG);
8164919Sxy150489 kstat_named_init(&e1000g_ksp->Totl, "Total_Octets_Xmitd_Lo",
8174919Sxy150489 KSTAT_DATA_ULONG);
8184919Sxy150489 kstat_named_init(&e1000g_ksp->Toth, "Total_Octets_Xmitd_Hi",
8194919Sxy150489 KSTAT_DATA_ULONG);
8204919Sxy150489 kstat_named_init(&e1000g_ksp->Tpr, "Total_Packets_Recvd",
8214919Sxy150489 KSTAT_DATA_ULONG);
8224919Sxy150489 kstat_named_init(&e1000g_ksp->Tpt, "Total_Packets_Xmitd",
8234919Sxy150489 KSTAT_DATA_ULONG);
8245882Syy150190 #ifdef E1000G_DEBUG
8254919Sxy150489 kstat_named_init(&e1000g_ksp->Ptc64, "Pkts_Xmitd_( 64b)",
8264919Sxy150489 KSTAT_DATA_ULONG);
8274919Sxy150489 kstat_named_init(&e1000g_ksp->Ptc127, "Pkts_Xmitd_( 65- 127b)",
8284919Sxy150489 KSTAT_DATA_ULONG);
8294919Sxy150489 kstat_named_init(&e1000g_ksp->Ptc255, "Pkts_Xmitd_( 128- 255b)",
8304919Sxy150489 KSTAT_DATA_ULONG);
8314919Sxy150489 kstat_named_init(&e1000g_ksp->Ptc511, "Pkts_Xmitd_( 255- 511b)",
8324919Sxy150489 KSTAT_DATA_ULONG);
8334919Sxy150489 kstat_named_init(&e1000g_ksp->Ptc1023, "Pkts_Xmitd_( 512-1023b)",
8344919Sxy150489 KSTAT_DATA_ULONG);
8354919Sxy150489 kstat_named_init(&e1000g_ksp->Ptc1522, "Pkts_Xmitd_(1024-1522b)",
8364919Sxy150489 KSTAT_DATA_ULONG);
8375882Syy150190 #endif
8384919Sxy150489 kstat_named_init(&e1000g_ksp->Tncrs, "Xmit_with_No_CRS",
8394919Sxy150489 KSTAT_DATA_ULONG);
8404919Sxy150489 kstat_named_init(&e1000g_ksp->Tsctc, "Xmit_TCP_Seg_Contexts",
8414919Sxy150489 KSTAT_DATA_ULONG);
8424919Sxy150489 kstat_named_init(&e1000g_ksp->Tsctfc, "Xmit_TCP_Seg_Contexts_Fail",
8434919Sxy150489 KSTAT_DATA_ULONG);
8443526Sxy150489
8454919Sxy150489 #ifdef E1000G_DEBUG
8464919Sxy150489 kstat_named_init(&e1000g_ksp->rx_none, "Rx No Data",
8474919Sxy150489 KSTAT_DATA_ULONG);
8484919Sxy150489 kstat_named_init(&e1000g_ksp->rx_multi_desc, "Rx Span Multi Desc",
8494919Sxy150489 KSTAT_DATA_ULONG);
8504919Sxy150489 kstat_named_init(&e1000g_ksp->rx_no_freepkt, "Rx Freelist Empty",
8514919Sxy150489 KSTAT_DATA_ULONG);
8524919Sxy150489 kstat_named_init(&e1000g_ksp->rx_avail_freepkt, "Rx Freelist Avail",
8533526Sxy150489 KSTAT_DATA_ULONG);
8543526Sxy150489
8553526Sxy150489 kstat_named_init(&e1000g_ksp->tx_under_size, "Tx Pkt Under Size",
8563526Sxy150489 KSTAT_DATA_ULONG);
8573526Sxy150489 kstat_named_init(&e1000g_ksp->tx_exceed_frags, "Tx Exceed Max Frags",
8583526Sxy150489 KSTAT_DATA_ULONG);
8594919Sxy150489 kstat_named_init(&e1000g_ksp->tx_empty_frags, "Tx Empty Frags",
8603526Sxy150489 KSTAT_DATA_ULONG);
8614919Sxy150489 kstat_named_init(&e1000g_ksp->tx_recycle, "Tx Recycle",
8623526Sxy150489 KSTAT_DATA_ULONG);
8634919Sxy150489 kstat_named_init(&e1000g_ksp->tx_recycle_intr, "Tx Recycle Intr",
8643526Sxy150489 KSTAT_DATA_ULONG);
8654919Sxy150489 kstat_named_init(&e1000g_ksp->tx_recycle_retry, "Tx Recycle Retry",
8663526Sxy150489 KSTAT_DATA_ULONG);
8674919Sxy150489 kstat_named_init(&e1000g_ksp->tx_recycle_none, "Tx Recycled None",
8683526Sxy150489 KSTAT_DATA_ULONG);
8694919Sxy150489 kstat_named_init(&e1000g_ksp->tx_copy, "Tx Send Copy",
8703526Sxy150489 KSTAT_DATA_ULONG);
8714919Sxy150489 kstat_named_init(&e1000g_ksp->tx_bind, "Tx Send Bind",
8723526Sxy150489 KSTAT_DATA_ULONG);
8734919Sxy150489 kstat_named_init(&e1000g_ksp->tx_multi_copy, "Tx Copy Multi Frags",
8743526Sxy150489 KSTAT_DATA_ULONG);
8754919Sxy150489 kstat_named_init(&e1000g_ksp->tx_multi_cookie, "Tx Bind Multi Cookies",
8763526Sxy150489 KSTAT_DATA_ULONG);
8774919Sxy150489 kstat_named_init(&e1000g_ksp->tx_lack_desc, "Tx Desc Insufficient",
8783526Sxy150489 KSTAT_DATA_ULONG);
8794919Sxy150489 #endif
8803526Sxy150489
8813526Sxy150489 /*
8823526Sxy150489 * Function to provide kernel stat update on demand
8833526Sxy150489 */
8844919Sxy150489 ksp->ks_update = e1000g_update_stats;
8853526Sxy150489
8863526Sxy150489 /*
8873526Sxy150489 * Pointer into provider's raw statistics
8883526Sxy150489 */
8893526Sxy150489 ksp->ks_private = (void *)Adapter;
8903526Sxy150489
8913526Sxy150489 /*
8923526Sxy150489 * Add kstat to systems kstat chain
8933526Sxy150489 */
8943526Sxy150489 kstat_install(ksp);
8953526Sxy150489
8963526Sxy150489 return (DDI_SUCCESS);
8973526Sxy150489 }
89810680SMin.Xu@Sun.COM
89910680SMin.Xu@Sun.COM /*
90010680SMin.Xu@Sun.COM * e1000g_read_phy_stat - read certain PHY statistics
90110680SMin.Xu@Sun.COM *
90210680SMin.Xu@Sun.COM * Certain statistics are read from MAC registers on some silicon types
90310680SMin.Xu@Sun.COM * but are read from the PHY on other silicon types. This routine
90410680SMin.Xu@Sun.COM * handles that difference as needed.
90510680SMin.Xu@Sun.COM */
90610680SMin.Xu@Sun.COM static uint32_t
e1000g_read_phy_stat(struct e1000_hw * hw,int reg)90710680SMin.Xu@Sun.COM e1000g_read_phy_stat(struct e1000_hw *hw, int reg)
90810680SMin.Xu@Sun.COM {
90910680SMin.Xu@Sun.COM uint16_t phy_low, phy_high;
91010680SMin.Xu@Sun.COM uint32_t val;
91110680SMin.Xu@Sun.COM
91210680SMin.Xu@Sun.COM /* get statistic from PHY in these cases */
91310680SMin.Xu@Sun.COM if ((hw->phy.type == e1000_phy_82578) ||
91410680SMin.Xu@Sun.COM (hw->phy.type == e1000_phy_82577)) {
91510680SMin.Xu@Sun.COM
91610680SMin.Xu@Sun.COM switch (reg) {
91710680SMin.Xu@Sun.COM case E1000_SCC:
91810680SMin.Xu@Sun.COM (void) e1000_read_phy_reg(hw, HV_SCC_UPPER, &phy_high);
91910680SMin.Xu@Sun.COM (void) e1000_read_phy_reg(hw, HV_SCC_LOWER, &phy_low);
92010680SMin.Xu@Sun.COM val = ((uint32_t)phy_high << 16) | (uint32_t)phy_low;
92110680SMin.Xu@Sun.COM break;
92210680SMin.Xu@Sun.COM
92310680SMin.Xu@Sun.COM case E1000_MCC:
92410680SMin.Xu@Sun.COM (void) e1000_read_phy_reg(hw, HV_MCC_UPPER, &phy_high);
92510680SMin.Xu@Sun.COM (void) e1000_read_phy_reg(hw, HV_MCC_LOWER, &phy_low);
92610680SMin.Xu@Sun.COM val = ((uint32_t)phy_high << 16) | (uint32_t)phy_low;
92710680SMin.Xu@Sun.COM break;
92810680SMin.Xu@Sun.COM
92910680SMin.Xu@Sun.COM case E1000_ECOL:
93010680SMin.Xu@Sun.COM (void) e1000_read_phy_reg(hw, HV_ECOL_UPPER, &phy_high);
93110680SMin.Xu@Sun.COM (void) e1000_read_phy_reg(hw, HV_ECOL_LOWER, &phy_low);
93210680SMin.Xu@Sun.COM val = ((uint32_t)phy_high << 16) | (uint32_t)phy_low;
93310680SMin.Xu@Sun.COM break;
93410680SMin.Xu@Sun.COM
93510680SMin.Xu@Sun.COM case E1000_COLC:
93610680SMin.Xu@Sun.COM (void) e1000_read_phy_reg(hw, HV_COLC_UPPER, &phy_high);
93710680SMin.Xu@Sun.COM (void) e1000_read_phy_reg(hw, HV_COLC_LOWER, &phy_low);
93810680SMin.Xu@Sun.COM val = ((uint32_t)phy_high << 16) | (uint32_t)phy_low;
93910680SMin.Xu@Sun.COM break;
94010680SMin.Xu@Sun.COM
94110680SMin.Xu@Sun.COM case E1000_LATECOL:
94210680SMin.Xu@Sun.COM (void) e1000_read_phy_reg(hw, HV_LATECOL_UPPER,
94310680SMin.Xu@Sun.COM &phy_high);
94410680SMin.Xu@Sun.COM (void) e1000_read_phy_reg(hw, HV_LATECOL_LOWER,
94510680SMin.Xu@Sun.COM &phy_low);
94610680SMin.Xu@Sun.COM val = ((uint32_t)phy_high << 16) | (uint32_t)phy_low;
94710680SMin.Xu@Sun.COM break;
94810680SMin.Xu@Sun.COM
94910680SMin.Xu@Sun.COM case E1000_DC:
95010680SMin.Xu@Sun.COM (void) e1000_read_phy_reg(hw, HV_DC_UPPER, &phy_high);
95110680SMin.Xu@Sun.COM (void) e1000_read_phy_reg(hw, HV_DC_LOWER, &phy_low);
95210680SMin.Xu@Sun.COM val = ((uint32_t)phy_high << 16) | (uint32_t)phy_low;
95310680SMin.Xu@Sun.COM break;
95410680SMin.Xu@Sun.COM
95510680SMin.Xu@Sun.COM case E1000_TNCRS:
95610680SMin.Xu@Sun.COM (void) e1000_read_phy_reg(hw, HV_TNCRS_UPPER,
95710680SMin.Xu@Sun.COM &phy_high);
95810680SMin.Xu@Sun.COM (void) e1000_read_phy_reg(hw, HV_TNCRS_LOWER,
95910680SMin.Xu@Sun.COM &phy_low);
96010680SMin.Xu@Sun.COM val = ((uint32_t)phy_high << 16) | (uint32_t)phy_low;
96110680SMin.Xu@Sun.COM break;
96210680SMin.Xu@Sun.COM
96310680SMin.Xu@Sun.COM default:
96410680SMin.Xu@Sun.COM break;
96510680SMin.Xu@Sun.COM }
96610680SMin.Xu@Sun.COM
96710680SMin.Xu@Sun.COM /* get statistic from MAC otherwise */
96810680SMin.Xu@Sun.COM } else {
96910680SMin.Xu@Sun.COM val = E1000_READ_REG(hw, reg);
97010680SMin.Xu@Sun.COM }
97110680SMin.Xu@Sun.COM
97210680SMin.Xu@Sun.COM return (val);
97310680SMin.Xu@Sun.COM }
974*11878SVenu.Iyer@Sun.COM
975*11878SVenu.Iyer@Sun.COM /*
976*11878SVenu.Iyer@Sun.COM * Retrieve a value for one of the statistics for a particular rx ring
977*11878SVenu.Iyer@Sun.COM */
978*11878SVenu.Iyer@Sun.COM int
e1000g_rx_ring_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)979*11878SVenu.Iyer@Sun.COM e1000g_rx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
980*11878SVenu.Iyer@Sun.COM {
981*11878SVenu.Iyer@Sun.COM e1000g_rx_ring_t *rx_ring = (e1000g_rx_ring_t *)rh;
982*11878SVenu.Iyer@Sun.COM struct e1000g *Adapter = rx_ring->adapter;
983*11878SVenu.Iyer@Sun.COM struct e1000_hw *hw = &Adapter->shared;
984*11878SVenu.Iyer@Sun.COM p_e1000g_stat_t e1000g_ksp =
985*11878SVenu.Iyer@Sun.COM (p_e1000g_stat_t)Adapter->e1000g_ksp->ks_data;
986*11878SVenu.Iyer@Sun.COM uint32_t low_val, high_val;
987*11878SVenu.Iyer@Sun.COM
988*11878SVenu.Iyer@Sun.COM rw_enter(&Adapter->chip_lock, RW_READER);
989*11878SVenu.Iyer@Sun.COM
990*11878SVenu.Iyer@Sun.COM if (Adapter->e1000g_state & E1000G_SUSPENDED) {
991*11878SVenu.Iyer@Sun.COM rw_exit(&Adapter->chip_lock);
992*11878SVenu.Iyer@Sun.COM return (ECANCELED);
993*11878SVenu.Iyer@Sun.COM }
994*11878SVenu.Iyer@Sun.COM
995*11878SVenu.Iyer@Sun.COM switch (stat) {
996*11878SVenu.Iyer@Sun.COM case MAC_STAT_RBYTES:
997*11878SVenu.Iyer@Sun.COM /*
998*11878SVenu.Iyer@Sun.COM * The 64-bit register will reset whenever the upper
999*11878SVenu.Iyer@Sun.COM * 32 bits are read. So we need to read the lower
1000*11878SVenu.Iyer@Sun.COM * 32 bits first, then read the upper 32 bits.
1001*11878SVenu.Iyer@Sun.COM */
1002*11878SVenu.Iyer@Sun.COM low_val = E1000_READ_REG(hw, E1000_TORL);
1003*11878SVenu.Iyer@Sun.COM high_val = E1000_READ_REG(hw, E1000_TORH);
1004*11878SVenu.Iyer@Sun.COM *val = (uint64_t)e1000g_ksp->Torh.value.ul << 32 |
1005*11878SVenu.Iyer@Sun.COM (uint64_t)e1000g_ksp->Torl.value.ul;
1006*11878SVenu.Iyer@Sun.COM *val += (uint64_t)high_val << 32 | (uint64_t)low_val;
1007*11878SVenu.Iyer@Sun.COM
1008*11878SVenu.Iyer@Sun.COM e1000g_ksp->Torl.value.ul = (uint32_t)*val;
1009*11878SVenu.Iyer@Sun.COM e1000g_ksp->Torh.value.ul = (uint32_t)(*val >> 32);
1010*11878SVenu.Iyer@Sun.COM break;
1011*11878SVenu.Iyer@Sun.COM
1012*11878SVenu.Iyer@Sun.COM case MAC_STAT_IPACKETS:
1013*11878SVenu.Iyer@Sun.COM e1000g_ksp->Tpr.value.ul +=
1014*11878SVenu.Iyer@Sun.COM E1000_READ_REG(hw, E1000_TPR);
1015*11878SVenu.Iyer@Sun.COM *val = e1000g_ksp->Tpr.value.ul;
1016*11878SVenu.Iyer@Sun.COM break;
1017*11878SVenu.Iyer@Sun.COM
1018*11878SVenu.Iyer@Sun.COM default:
1019*11878SVenu.Iyer@Sun.COM *val = 0;
1020*11878SVenu.Iyer@Sun.COM rw_exit(&Adapter->chip_lock);
1021*11878SVenu.Iyer@Sun.COM return (ENOTSUP);
1022*11878SVenu.Iyer@Sun.COM }
1023*11878SVenu.Iyer@Sun.COM
1024*11878SVenu.Iyer@Sun.COM rw_exit(&Adapter->chip_lock);
1025*11878SVenu.Iyer@Sun.COM
1026*11878SVenu.Iyer@Sun.COM if (e1000g_check_acc_handle(Adapter->osdep.reg_handle) != DDI_FM_OK)
1027*11878SVenu.Iyer@Sun.COM ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_UNAFFECTED);
1028*11878SVenu.Iyer@Sun.COM
1029*11878SVenu.Iyer@Sun.COM return (0);
1030*11878SVenu.Iyer@Sun.COM }
1031