diff options
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/uts/common/io/rge/rge.h | 3 | ||||
| -rw-r--r-- | usr/src/uts/common/io/rge/rge_chip.c | 37 | ||||
| -rw-r--r-- | usr/src/uts/common/io/rge/rge_rxtx.c | 10 |
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) { |
