From the PR:
The receive function em_process_receive_interrupts() unlocks the adapter while ether_input() processes the packet, and then locks it back. In the meantime, em_init() may be called, either from em_watchdog() from softclock interrupt or from the ifconfig(8) program. The em_init() resets the card, in particular it sets adapter->next_rx_desc_to_check to 0 and resets hardware RX Head and Tail descriptor pointers. The loop in em_process_receive_interrupts() does not expect these things to change, and a mess may result. This fixes long wedges of em(4) interfaces receive part under high load and IP fastforwarding enabled. PR: kern/87418 Submitted by: Dmitrij Tejblum <tejblum yandex-team.ru>
This commit is contained in:
parent
6b32f3d3f2
commit
66e58c20dd
@ -2755,6 +2755,7 @@ em_process_receive_interrupts(struct adapter * adapter, int count)
|
||||
}
|
||||
|
||||
while ((current_desc->status & E1000_RXD_STAT_DD) && (count != 0)) {
|
||||
struct mbuf *m = NULL;
|
||||
|
||||
mp = adapter->rx_buffer_area[i].m_head;
|
||||
bus_dmamap_sync(adapter->rxtag, adapter->rx_buffer_area[i].map,
|
||||
@ -2846,16 +2847,10 @@ em_process_receive_interrupts(struct adapter * adapter, int count)
|
||||
(current_desc->special &
|
||||
E1000_RXD_SPC_VLAN_MASK),
|
||||
adapter->fmp = NULL);
|
||||
|
||||
if (adapter->fmp != NULL) {
|
||||
struct mbuf *m = adapter->fmp;
|
||||
|
||||
adapter->fmp = NULL;
|
||||
EM_UNLOCK(adapter);
|
||||
(*ifp->if_input)(ifp, m);
|
||||
EM_LOCK(adapter);
|
||||
}
|
||||
adapter->lmp = NULL;
|
||||
m = adapter->fmp;
|
||||
adapter->fmp = NULL;
|
||||
adapter->lmp = NULL;
|
||||
}
|
||||
} else {
|
||||
adapter->dropped_pkts++;
|
||||
@ -2873,11 +2868,16 @@ em_process_receive_interrupts(struct adapter * adapter, int count)
|
||||
E1000_WRITE_REG(&adapter->hw, RDT, i);
|
||||
|
||||
/* Advance our pointers to the next descriptor */
|
||||
if (++i == adapter->num_rx_desc) {
|
||||
i = 0;
|
||||
current_desc = adapter->rx_desc_base;
|
||||
} else
|
||||
current_desc++;
|
||||
if (++i == adapter->num_rx_desc)
|
||||
i = 0;
|
||||
if (m != NULL) {
|
||||
adapter->next_rx_desc_to_check = i;
|
||||
EM_UNLOCK(adapter);
|
||||
(*ifp->if_input)(ifp, m);
|
||||
EM_LOCK(adapter);
|
||||
i = adapter->next_rx_desc_to_check;
|
||||
}
|
||||
current_desc = &adapter->rx_desc_base[i];
|
||||
}
|
||||
bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map,
|
||||
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
|
||||
|
Loading…
x
Reference in New Issue
Block a user