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>
next in thread | raw e-mail | index | archive | help
>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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200510140031.j9E0VZFr092939>