Date: Fri, 14 Oct 2005 04:31:35 +0400 (MSD) From: Dmitrij Tejblum <tejblum@yandex-team.ru> To: FreeBSD-gnats-submit@FreeBSD.org Subject: kern/87418: [if_em] [patch] The em driver sometimes stop receive data Message-ID: <200510140031.j9E0VZFr092939@walrus18.yandex.ru> Resent-Message-ID: <200510140040.j9E0eG8m095176@freefall.freebsd.org>
index | next in thread | raw e-mail
>Number: 87418
>Category: kern
>Synopsis: [if_em] [patch] The em driver sometimes stop receive data
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Fri Oct 14 00:40:15 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator: Dmitrij Tejblum
>Release: FreeBSD 5.4-STABLE i386
>Organization:
OOO Yandex
>Environment:
>Description:
The receive function em_process_receive_interrupts() unlock the adapter
while ether_input() process the packet, and then lock it back. In the
meantime, em_init() may be called (either from em_watchdog() from softclock
interrupt or from the ifconfig program). em_init() reset the card, in
particular it set adapter->next_rx_desc_to_check to 0 and reset 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.
>How-To-Repeat:
>Fix:
The following patch tries to make em_process_receive_interrupts() fully
reenterant (1.73 was incomplete) and fix the described problem.
(I removed a code for FreeBSD 4: I don't want to deal with it and BTW Intel
themselves ships different drivers for RELENG_4, RELENG_5 and RELENG_6.)
Index: dev/em/if_em.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/em/if_em.c,v
retrieving revision 1.75
diff -u -p -r1.75 if_em.c
--- dev/em/if_em.c 5 Oct 2005 10:09:14 -0000 1.75
+++ dev/em/if_em.c 14 Oct 2005 00:27:28 -0000
@@ -2785,7 +2785,7 @@ static void
em_process_receive_interrupts(struct adapter * adapter, int count)
{
struct ifnet *ifp;
- struct mbuf *mp;
+ struct mbuf *mp, *m;
#if __FreeBSD_version < 500000
struct ether_header *eh;
#endif
@@ -2811,6 +2811,7 @@ em_process_receive_interrupts(struct ada
while ((current_desc->status & E1000_RXD_STAT_DD) && (count != 0)) {
+ m = NULL;
mp = adapter->rx_buffer_area[i].m_head;
bus_dmamap_sync(adapter->rxtag, adapter->rx_buffer_area[i].map,
BUS_DMASYNC_POSTREAD);
@@ -2895,19 +2896,6 @@ em_process_receive_interrupts(struct ada
adapter->fmp->m_pkthdr.rcvif = ifp;
ifp->if_ipackets++;
-#if __FreeBSD_version < 500000
- eh = mtod(adapter->fmp, struct ether_header *);
- /* Remove ethernet header from mbuf */
- m_adj(adapter->fmp, sizeof(struct ether_header));
- em_receive_checksum(adapter, current_desc,
- adapter->fmp);
- if (current_desc->status & E1000_RXD_STAT_VP)
- VLAN_INPUT_TAG(eh, adapter->fmp,
- (current_desc->special &
- E1000_RXD_SPC_VLAN_MASK));
- else
- ether_input(ifp, eh, adapter->fmp);
-#else
em_receive_checksum(adapter, current_desc,
adapter->fmp);
@@ -2917,15 +2905,9 @@ em_process_receive_interrupts(struct ada
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);
- }
-#endif
+ if (adapter->fmp != NULL)
+ m = adapter->fmp;
+ adapter->fmp = NULL;
adapter->lmp = NULL;
}
} else {
@@ -2944,11 +2926,16 @@ em_process_receive_interrupts(struct ada
E1000_WRITE_REG(&adapter->hw, RDT, i);
/* Advance our pointers to the next descriptor */
- if (++i == adapter->num_rx_desc) {
+ if (++i == adapter->num_rx_desc)
i = 0;
- current_desc = adapter->rx_desc_base;
- } else
- current_desc++;
+ 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);
>Release-Note:
>Audit-Trail:
>Unformatted:
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200510140031.j9E0VZFr092939>
