diff options
Diffstat (limited to 'usr/src/uts/common')
-rwxr-xr-x | usr/src/uts/common/io/rge/rge.h | 6 | ||||
-rwxr-xr-x | usr/src/uts/common/io/rge/rge_chip.c | 5 | ||||
-rwxr-xr-x | usr/src/uts/common/io/rge/rge_main.c | 7 | ||||
-rwxr-xr-x | usr/src/uts/common/io/rge/rge_rxtx.c | 34 |
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); |