summaryrefslogtreecommitdiff
path: root/usr/src/uts/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common')
-rwxr-xr-xusr/src/uts/common/io/rge/rge.h6
-rwxr-xr-xusr/src/uts/common/io/rge/rge_chip.c5
-rwxr-xr-xusr/src/uts/common/io/rge/rge_main.c7
-rwxr-xr-xusr/src/uts/common/io/rge/rge_rxtx.c34
4 files changed, 48 insertions, 4 deletions
diff --git a/usr/src/uts/common/io/rge/rge.h b/usr/src/uts/common/io/rge/rge.h
index 199190097f..e34c6de58e 100755
--- a/usr/src/uts/common/io/rge/rge.h
+++ b/usr/src/uts/common/io/rge/rge.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -352,7 +352,9 @@ typedef struct {
} chip_id_t;
typedef struct rge_stats {
+ uint64_t rpackets;
uint64_t rbytes;
+ uint64_t opackets;
uint64_t obytes;
uint32_t overflow;
uint32_t defer; /* dot3StatsDeferredTransmissions */
@@ -362,6 +364,8 @@ typedef struct rge_stats {
uint32_t intr; /* interrupt count */
uint16_t chip_reset;
uint16_t phy_reset;
+ boolean_t tx_pre_ismax;
+ boolean_t tx_cur_ismax;
} rge_stats_t;
/*
diff --git a/usr/src/uts/common/io/rge/rge_chip.c b/usr/src/uts/common/io/rge/rge_chip.c
index e68301c9db..9d2d6c8cbd 100755
--- a/usr/src/uts/common/io/rge/rge_chip.c
+++ b/usr/src/uts/common/io/rge/rge_chip.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -956,7 +956,8 @@ rge_chip_init(rge_t *rgep)
val16 = rge_reg_get8(rgep, PHY_STATUS_REG);
val16 = 0x12<<8 | val16;
- if (rgep->chipid.mac_ver != MAC_VER_8101E) {
+ if (rgep->chipid.mac_ver != MAC_VER_8101E &&
+ rgep->chipid.mac_ver != MAC_VER_8168B_C) {
rge_reg_put16(rgep, PHY_STATUS_REG, val16);
rge_reg_put32(rgep, RT_CSI_DATA_REG, 0x00021c01);
rge_reg_put32(rgep, RT_CSI_ACCESS_REG, 0x8000f088);
diff --git a/usr/src/uts/common/io/rge/rge_main.c b/usr/src/uts/common/io/rge/rge_main.c
index 107cb01eca..446a928c4c 100755
--- a/usr/src/uts/common/io/rge/rge_main.c
+++ b/usr/src/uts/common/io/rge/rge_main.c
@@ -706,6 +706,13 @@ rge_reset(rge_t *rgep)
mutex_exit(rgep->rc_lock);
mutex_exit(rgep->rx_lock);
+ rgep->stats.rpackets = 0;
+ rgep->stats.rbytes = 0;
+ rgep->stats.opackets = 0;
+ rgep->stats.obytes = 0;
+ rgep->stats.tx_pre_ismax = B_FALSE;
+ rgep->stats.tx_cur_ismax = B_FALSE;
+
RGE_DEBUG(("rge_reset($%p) done", (void *)rgep));
}
diff --git a/usr/src/uts/common/io/rge/rge_rxtx.c b/usr/src/uts/common/io/rge/rge_rxtx.c
index 3585da8135..e78ce16ac5 100755
--- a/usr/src/uts/common/io/rge/rge_rxtx.c
+++ b/usr/src/uts/common/io/rge/rge_rxtx.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -260,6 +260,7 @@ rge_receive_packet(rge_t *rgep, uint32_t slot)
return (NULL);
}
rgep->stats.rbytes += packet_len;
+ rgep->stats.rpackets ++;
/*
* VLAN packet ?
@@ -543,6 +544,11 @@ rge_send_copy(rge_t *rgep, mblk_t *mp, uint16_t tci)
}
}
rgep->stats.obytes += totlen;
+ rgep->stats.tx_pre_ismax = rgep->stats.tx_cur_ismax;
+ if (totlen == rgep->ethmax_size)
+ rgep->stats.tx_cur_ismax = B_TRUE;
+ else
+ rgep->stats.tx_cur_ismax = B_FALSE;
/*
* We'e reached the end of the chain; and we should have
@@ -607,6 +613,8 @@ rge_send(rge_t *rgep, mblk_t *mp)
{
struct ether_vlan_header *ehp;
uint16_t tci;
+ rge_hw_stats_t *bstp;
+ uint8_t counter;
ASSERT(mp->b_next == NULL);
@@ -646,9 +654,33 @@ rge_send(rge_t *rgep, mblk_t *mp)
if (--rgep->tx_flow == 0) {
DMA_SYNC(rgep->tx_desc, DDI_DMA_SYNC_FORDEV);
rge_tx_trigger(rgep);
+ rgep->stats.opackets ++;
if (rgep->tx_free < RGE_SEND_SLOTS/2)
rge_send_recycle(rgep);
rgep->tc_tail = rgep->tx_next;
+
+ /*
+ * It's observed that in current Realtek PCI-E chips, tx
+ * request of the second fragment for upper layer packets
+ * will be ignored if the hardware transmission is in
+ * progress and will not be processed when the tx engine
+ * is idle. So one solution is to re-issue the requests
+ * if the hardware and the software tx packets statistics
+ * are inconsistent.
+ */
+ if (rgep->chipid.is_pcie && rgep->stats.tx_pre_ismax) {
+ for (counter = 0; counter < 10; counter ++) {
+ mutex_enter(rgep->genlock);
+ rge_hw_stats_dump(rgep);
+ mutex_exit(rgep->genlock);
+ bstp = rgep->hw_stats;
+ if (rgep->stats.opackets
+ != RGE_BSWAP_64(bstp->rcv_ok))
+ rge_tx_trigger(rgep);
+ else
+ break;
+ }
+ }
}
mutex_exit(rgep->tx_lock);