summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/io/rge/rge.h3
-rw-r--r--usr/src/uts/common/io/rge/rge_chip.c37
-rw-r--r--usr/src/uts/common/io/rge/rge_rxtx.c10
3 files changed, 43 insertions, 7 deletions
diff --git a/usr/src/uts/common/io/rge/rge.h b/usr/src/uts/common/io/rge/rge.h
index 7765276082..7ee3183434 100644
--- 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -494,6 +494,7 @@ typedef struct rge {
clock_t tick_delta;
uint64_t last_opackets;
uint64_t last_rpackets;
+ uint32_t rx_fifo_ovf;
} rge_t;
/*
diff --git a/usr/src/uts/common/io/rge/rge_chip.c b/usr/src/uts/common/io/rge/rge_chip.c
index 4bb5f16aca..9c09e0dfc5 100644
--- a/usr/src/uts/common/io/rge/rge_chip.c
+++ b/usr/src/uts/common/io/rge/rge_chip.c
@@ -43,6 +43,7 @@ static uint32_t rge_autorecover = 1;
*/
#define RGE_DBG RGE_DBG_REGS /* debug flag for this code */
static uint32_t rge_watchdog_count = 1 << 5;
+static uint32_t rge_rx_watchdog_count = 1 << 3;
/*
* Operating register get/set access routines
@@ -716,6 +717,7 @@ rge_chip_ident(rge_t *rgep)
/* set pci latency timer */
if (chip->mac_ver == MAC_VER_8169 ||
chip->mac_ver == MAC_VER_8169S_D ||
+ chip->mac_ver == MAC_VER_8169S_E ||
chip->mac_ver == MAC_VER_8169SC)
pci_config_put8(rgep->cfg_handle, PCI_CONF_LATENCY_TIMER, 0x40);
@@ -723,9 +725,9 @@ rge_chip_ident(rge_t *rgep)
val16 = rge_reg_get16(rgep, RT_CONFIG_1_REG);
val16 &= 0x0300;
if (val16 == 0x1) /* 66Mhz PCI */
- pci_config_put32(rgep->cfg_handle, 0x7c, 0x00ff00ff);
+ rge_reg_put32(rgep, 0x7c, 0x000700ff);
else if (val16 == 0x0) /* 33Mhz PCI */
- pci_config_put32(rgep->cfg_handle, 0x7c, 0x00ffff00);
+ rge_reg_put32(rgep, 0x7c, 0x0007ff00);
}
/*
@@ -921,6 +923,10 @@ rge_chip_init(rge_t *rgep)
val16 |= CPLUS_BIT14 | MUL_PCI_RW_ENABLE;
rge_reg_put8(rgep, RESV_82_REG, 0x01);
}
+ if (chip->mac_ver == MAC_VER_8169S_E ||
+ chip->mac_ver == MAC_VER_8169SC) {
+ val16 |= MUL_PCI_RW_ENABLE;
+ }
rge_reg_put16(rgep, CPLUS_COMMAND_REG, val16 & (~0x03));
/*
@@ -1060,6 +1066,8 @@ rge_chip_start(rge_t *rgep)
if (rgep->chipid.is_pcie) {
rgep->int_mask |= NO_TXDESC_INT;
}
+ rgep->rx_fifo_ovf = 0;
+ rgep->int_mask |= RX_FIFO_OVERFLOW_INT;
rge_reg_put16(rgep, INT_MASK_REG, rgep->int_mask);
/*
@@ -1470,6 +1478,22 @@ rge_intr(caddr_t arg1, caddr_t arg2)
rge_chip_cyclic(rgep);
}
+ if (int_status & RX_FIFO_OVERFLOW_INT) {
+ /* start rx watchdog timeout detection */
+ rgep->rx_fifo_ovf = 1;
+ if (rgep->int_mask & RX_FIFO_OVERFLOW_INT) {
+ rgep->int_mask &= ~RX_FIFO_OVERFLOW_INT;
+ update_int_mask = B_TRUE;
+ }
+ } else if (int_status & RGE_RX_INT) {
+ /* stop rx watchdog timeout detection */
+ rgep->rx_fifo_ovf = 0;
+ if ((rgep->int_mask & RX_FIFO_OVERFLOW_INT) == 0) {
+ rgep->int_mask |= RX_FIFO_OVERFLOW_INT;
+ update_int_mask = B_TRUE;
+ }
+ }
+
mutex_exit(rgep->genlock);
/*
@@ -1567,6 +1591,15 @@ rge_factotum_stall_check(rge_t *rgep)
ASSERT(mutex_owned(rgep->genlock));
/*
+ * Specific check for RX stall ...
+ */
+ rgep->rx_fifo_ovf <<= 1;
+ if (rgep->rx_fifo_ovf > rge_rx_watchdog_count) {
+ RGE_REPORT((rgep, "rx_hang detected"));
+ return (B_TRUE);
+ }
+
+ /*
* Specific check for Tx stall ...
*
* The 'watchdog' counter is incremented whenever a packet
diff --git a/usr/src/uts/common/io/rge/rge_rxtx.c b/usr/src/uts/common/io/rge/rge_rxtx.c
index 4cf866473a..a2d881c67b 100644
--- 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -697,10 +697,12 @@ rge_m_tx(void *arg, mblk_t *mp)
rw_enter(rgep->errlock, RW_READER);
if ((rgep->rge_mac_state != RGE_MAC_STARTED) ||
- (rgep->rge_chip_state != RGE_CHIP_RUNNING)) {
- RGE_DEBUG(("rge_m_tx: tx doesn't work"));
+ (rgep->rge_chip_state != RGE_CHIP_RUNNING) ||
+ (rgep->param_link_up != LINK_STATE_UP)) {
rw_exit(rgep->errlock);
- return (mp);
+ RGE_DEBUG(("rge_m_tx: tx doesn't work"));
+ freemsgchain(mp);
+ return (NULL);
}
while (mp != NULL) {