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:
Gleb Smirnoff 2005-10-14 11:00:15 +00:00
parent 6b32f3d3f2
commit 66e58c20dd
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=151314

View File

@ -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);