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
This commit is contained in:
parent
22b1904845
commit
5422f907d4
@ -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;
|
||||
}
|
||||
for (;;) {
|
||||
reg_icr = E1000_READ_REG(&adapter->hw, ICR);
|
||||
if (reg_icr == 0)
|
||||
break;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user