diff options
author | glebius <glebius@FreeBSD.org> | 2005-10-20 08:46:43 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2005-10-20 08:46:43 +0000 |
commit | dfc409a7f8c5e92350da19dcf29892cecb411225 (patch) | |
tree | e35e2b1445ed5710c7336ceadefef9837409ba2f /sys/dev/em | |
parent | 2cd8b1e9bf3e489f55d37732b86595e11f319ed2 (diff) | |
download | FreeBSD-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.c | 68 | ||||
-rw-r--r-- | sys/dev/em/if_em.h | 9 | ||||
-rw-r--r-- | sys/dev/em/if_em_hw.h | 1 |
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) |