summaryrefslogtreecommitdiffstats
path: root/sys/dev/em
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2005-10-20 08:46:43 +0000
committerglebius <glebius@FreeBSD.org>2005-10-20 08:46:43 +0000
commitdfc409a7f8c5e92350da19dcf29892cecb411225 (patch)
treee35e2b1445ed5710c7336ceadefef9837409ba2f /sys/dev/em
parent2cd8b1e9bf3e489f55d37732b86595e11f319ed2 (diff)
downloadFreeBSD-src-dfc409a7f8c5e92350da19dcf29892cecb411225.zip
FreeBSD-src-dfc409a7f8c5e92350da19dcf29892cecb411225.tar.gz
Revamp interrupt handling in em(4) driver:
o Do not mask the RX overrun interrupt. o Rewrite em_intr(): - Axe EM_MAX_INTR. - Cycle acknowledging interrupts and processing packets until zero interrupt cause register is read. - If RX overrun comes in log this fact. [ NetBSD also resets adapter in this case, but my tests showed that this is not needed and only pessimizes behavior under heavy load. ] - Since almost all functions is rewritten, style the remaining lines. This fixes em(4) interfaces wedging under high load. In collaboration with: wpaul, cognet Obtained from: NetBSD
Diffstat (limited to 'sys/dev/em')
-rw-r--r--sys/dev/em/if_em.c68
-rw-r--r--sys/dev/em/if_em.h9
-rw-r--r--sys/dev/em/if_em_hw.h1
3 files changed, 39 insertions, 39 deletions
diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c
index ed7bde0..75d3d59 100644
--- a/sys/dev/em/if_em.c
+++ b/sys/dev/em/if_em.c
@@ -985,51 +985,57 @@ em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
static void
em_intr(void *arg)
{
- u_int32_t loop_cnt = EM_MAX_INTR;
- u_int32_t reg_icr;
- struct ifnet *ifp;
- struct adapter *adapter = arg;
+ struct adapter *adapter = arg;
+ struct ifnet *ifp;
+ uint32_t reg_icr;
+ int wantinit = 0;
EM_LOCK(adapter);
- ifp = adapter->ifp;
+ ifp = adapter->ifp;
#ifdef DEVICE_POLLING
- if (ifp->if_capenable & IFCAP_POLLING) {
+ if (ifp->if_capenable & IFCAP_POLLING) {
EM_UNLOCK(adapter);
- return;
+ return;
}
#endif /* DEVICE_POLLING */
- reg_icr = E1000_READ_REG(&adapter->hw, ICR);
- if (!reg_icr) {
- EM_UNLOCK(adapter);
- return;
- }
-
- /* Link status change */
- if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
- callout_stop(&adapter->timer);
- adapter->hw.get_link_status = 1;
- em_check_for_link(&adapter->hw);
- em_print_link_status(adapter);
- callout_reset(&adapter->timer, hz, em_local_timer, adapter);
- }
+ for (;;) {
+ reg_icr = E1000_READ_REG(&adapter->hw, ICR);
+ if (reg_icr == 0)
+ break;
- while (loop_cnt > 0) {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- em_process_receive_interrupts(adapter, -1);
- em_clean_transmit_interrupts(adapter);
- }
- loop_cnt--;
- }
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ em_process_receive_interrupts(adapter, -1);
+ em_clean_transmit_interrupts(adapter);
+ }
- if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
+ /* Link status change */
+ if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+ callout_stop(&adapter->timer);
+ adapter->hw.get_link_status = 1;
+ em_check_for_link(&adapter->hw);
+ em_print_link_status(adapter);
+ callout_reset(&adapter->timer, hz, em_local_timer,
+ adapter);
+ }
+
+ if (reg_icr & E1000_ICR_RXO) {
+ log(LOG_WARNING, "%s: RX overrun\n", ifp->if_xname);
+ wantinit = 1;
+ }
+ }
+#if 0
+ if (wantinit)
+ em_init_locked(adapter);
+#endif
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- em_start_locked(ifp);
+ em_start_locked(ifp);
EM_UNLOCK(adapter);
- return;
+ return;
}
diff --git a/sys/dev/em/if_em.h b/sys/dev/em/if_em.h
index 097ab0e..82abdcc 100644
--- a/sys/dev/em/if_em.h
+++ b/sys/dev/em/if_em.h
@@ -47,6 +47,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <sys/module.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
+#include <sys/syslog.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -163,14 +164,6 @@ POSSIBILITY OF SUCH DAMAGE.
*/
#define EM_RADV 64
-
-/*
- * This parameter controls the maximum no of times the driver will loop
- * in the isr.
- * Minimum Value = 1
- */
-#define EM_MAX_INTR 3
-
/*
* Inform the stack about transmit checksum offload capabilities.
*/
diff --git a/sys/dev/em/if_em_hw.h b/sys/dev/em/if_em_hw.h
index 5ad3853..11f3b0e 100644
--- a/sys/dev/em/if_em_hw.h
+++ b/sys/dev/em/if_em_hw.h
@@ -556,6 +556,7 @@ uint8_t em_arc_subsystem_valid(struct em_hw *hw);
E1000_IMS_TXDW | \
E1000_IMS_RXDMT0 | \
E1000_IMS_RXSEQ | \
+ E1000_IMS_RXO | \
E1000_IMS_LSC)
OpenPOWER on IntegriCloud