Fix poll mode assumption breaking.
ixgbe_{enable,disable}_intr() forcibly enable/disable all interrupts regardless of current state. That can break poll mode assumption, that is, queue interrupts must not occur while polling Tx/Rx rings. E.g. "ifconfig ixg0 delete && ifconfig ixg0 192.168.0.1" on heavy load traffic can causes this issue. This fix may have 1% or 2% performance impact at short packets. XXX ixgbe_rearm_queues() which is called only via watchdog can also break this poll mode assumption because writing EICS casues interrupts immediately when interrupt auto mask enabled. We will fix it with other issues about watchdog later. ok by msaitoh@n.o.
This commit is contained in:
parent
8083c34295
commit
74808152cc
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ix_txrx.c,v 1.32 2018/02/22 10:02:08 msaitoh Exp $ */
|
||||
/* $NetBSD: ix_txrx.c,v 1.33 2018/02/26 04:19:00 knakahara Exp $ */
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
|
@ -2260,6 +2260,9 @@ ixgbe_allocate_queues(struct adapter *adapter)
|
|||
que->me = i;
|
||||
que->txr = &adapter->tx_rings[i];
|
||||
que->rxr = &adapter->rx_rings[i];
|
||||
|
||||
mutex_init(&que->im_mtx, MUTEX_DEFAULT, IPL_NET);
|
||||
que->im_nest = 0;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ixgbe.c,v 1.126 2018/02/22 10:02:08 msaitoh Exp $ */
|
||||
/* $NetBSD: ixgbe.c,v 1.127 2018/02/26 04:19:00 knakahara Exp $ */
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
|
@ -2384,9 +2384,14 @@ static inline void
|
|||
ixgbe_enable_queue(struct adapter *adapter, u32 vector)
|
||||
{
|
||||
struct ixgbe_hw *hw = &adapter->hw;
|
||||
struct ix_queue *que = &adapter->queues[vector];
|
||||
u64 queue = (u64)(1ULL << vector);
|
||||
u32 mask;
|
||||
|
||||
mutex_enter(&que->im_mtx);
|
||||
if (que->im_nest > 0 && --que->im_nest > 0)
|
||||
goto out;
|
||||
|
||||
if (hw->mac.type == ixgbe_mac_82598EB) {
|
||||
mask = (IXGBE_EIMS_RTX_QUEUE & queue);
|
||||
IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
|
||||
|
@ -2398,6 +2403,8 @@ ixgbe_enable_queue(struct adapter *adapter, u32 vector)
|
|||
if (mask)
|
||||
IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
|
||||
}
|
||||
out:
|
||||
mutex_exit(&que->im_mtx);
|
||||
} /* ixgbe_enable_queue */
|
||||
|
||||
/************************************************************************
|
||||
|
@ -2407,9 +2414,14 @@ static inline void
|
|||
ixgbe_disable_queue(struct adapter *adapter, u32 vector)
|
||||
{
|
||||
struct ixgbe_hw *hw = &adapter->hw;
|
||||
struct ix_queue *que = &adapter->queues[vector];
|
||||
u64 queue = (u64)(1ULL << vector);
|
||||
u32 mask;
|
||||
|
||||
mutex_enter(&que->im_mtx);
|
||||
if (que->im_nest++ > 0)
|
||||
goto out;
|
||||
|
||||
if (hw->mac.type == ixgbe_mac_82598EB) {
|
||||
mask = (IXGBE_EIMS_RTX_QUEUE & queue);
|
||||
IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask);
|
||||
|
@ -2421,6 +2433,8 @@ ixgbe_disable_queue(struct adapter *adapter, u32 vector)
|
|||
if (mask)
|
||||
IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask);
|
||||
}
|
||||
out:
|
||||
mutex_exit(&que->im_mtx);
|
||||
} /* ixgbe_disable_queue */
|
||||
|
||||
/************************************************************************
|
||||
|
@ -3427,6 +3441,10 @@ ixgbe_detach(device_t dev, int flags)
|
|||
|
||||
ixgbe_free_transmit_structures(adapter);
|
||||
ixgbe_free_receive_structures(adapter);
|
||||
for (int i = 0; i < adapter->num_queues; i++) {
|
||||
struct ix_queue * que = &adapter->queues[i];
|
||||
mutex_destroy(&que->im_mtx);
|
||||
}
|
||||
free(adapter->queues, M_DEVBUF);
|
||||
free(adapter->mta, M_DEVBUF);
|
||||
|
||||
|
@ -4568,15 +4586,17 @@ ixgbe_enable_intr(struct adapter *adapter)
|
|||
static void
|
||||
ixgbe_disable_intr(struct adapter *adapter)
|
||||
{
|
||||
struct ix_queue *que = adapter->queues;
|
||||
|
||||
/* disable interrupts other than queues */
|
||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~IXGBE_EIMC_RTX_QUEUE);
|
||||
|
||||
if (adapter->msix_mem)
|
||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, 0);
|
||||
if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
|
||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
|
||||
} else {
|
||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000);
|
||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0);
|
||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < adapter->num_queues; i++, que++)
|
||||
ixgbe_disable_queue(adapter, que->msix);
|
||||
|
||||
IXGBE_WRITE_FLUSH(&adapter->hw);
|
||||
|
||||
return;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ixgbe.h,v 1.30 2018/02/22 10:02:08 msaitoh Exp $ */
|
||||
/* $NetBSD: ixgbe.h,v 1.31 2018/02/26 04:19:00 knakahara Exp $ */
|
||||
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
@ -335,6 +335,9 @@ struct ix_queue {
|
|||
struct evcnt irqs;
|
||||
char namebuf[32];
|
||||
char evnamebuf[32];
|
||||
|
||||
kmutex_t im_mtx; /* lock for im_nest and this queue's EIMS/EIMC bit */
|
||||
int im_nest;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue