From owner-svn-src-projects@FreeBSD.ORG Mon Sep 27 15:24:17 2010 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 03285106564A; Mon, 27 Sep 2010 15:24:17 +0000 (UTC) (envelope-from attilio@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E5D9D8FC0C; Mon, 27 Sep 2010 15:24:16 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o8RFOGCG040229; Mon, 27 Sep 2010 15:24:16 GMT (envelope-from attilio@svn.freebsd.org) Received: (from attilio@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o8RFOGOm040224; Mon, 27 Sep 2010 15:24:16 GMT (envelope-from attilio@svn.freebsd.org) Message-Id: <201009271524.o8RFOGOm040224@svn.freebsd.org> From: Attilio Rao Date: Mon, 27 Sep 2010 15:24:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r213200 - in projects/sv/sys: dev/e1000 netinet X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 27 Sep 2010 15:24:17 -0000 Author: attilio Date: Mon Sep 27 15:24:16 2010 New Revision: 213200 URL: http://svn.freebsd.org/changeset/base/213200 Log: Implement netdump interfaces for if_em and if_lem specifically and, contemporary, rework the netdump hooks. The netdump methods are now composed by the following interfaces: - normal polling operation - polling operation that tries to skip locking as much as it can (to be used in DDB case in order to increase chances of deadlock avoidance) - functions for enabling and disabling interrupts when DEVICE_POLLING option is not enabled, in order to avoid problems with polling. The normal/unlocked version of polling is a bit awkward but still used in several places in the FreeBSD kernel and effective when entering DDB. The implementation of netdump_methods is suited for having independency between NETDUMP_CLIENT and DEVICE_POLLING. Right now, the only issue left open is using unlocked version in the KDB_UNATTENDED version too, but it is going to be fixed soon. Reviewed by: rstone Modified: projects/sv/sys/dev/e1000/if_em.c projects/sv/sys/dev/e1000/if_lem.c projects/sv/sys/netinet/netdump.h projects/sv/sys/netinet/netdump_client.c Modified: projects/sv/sys/dev/e1000/if_em.c ============================================================================== --- projects/sv/sys/dev/e1000/if_em.c Mon Sep 27 14:50:51 2010 (r213199) +++ projects/sv/sys/dev/e1000/if_em.c Mon Sep 27 15:24:16 2010 (r213200) @@ -35,6 +35,7 @@ #ifdef HAVE_KERNEL_OPTION_HEADERS #include "opt_device_polling.h" #include "opt_inet.h" +#include "opt_netdump.h" #endif #include @@ -73,6 +74,9 @@ #include #include #include +#ifdef NETDUMP_CLIENT +#include +#endif #include #include @@ -283,14 +287,32 @@ static void em_add_rx_process_limit(stru static __inline void em_rx_discard(struct rx_ring *, int); -#ifdef DEVICE_POLLING +#if defined(DEVICE_POLLING) || defined(NETDUMP_CLIENT) +static int _em_poll_generic(struct ifnet *ifp, enum poll_cmd cmd, + int count, int locking); static poll_handler_t em_poll; -#endif /* POLLING */ +#endif +#ifdef NETDUMP_CLIENT +static poll_handler_t em_poll_unlocked; +static ndumplock_handler_t em_ndump_disable_intr; +static ndumplock_handler_t em_ndump_enable_intr; +#endif /********************************************************************* * FreeBSD Device Interface Entry Points *********************************************************************/ +#ifdef NETDUMP_CLIENT + +static struct netdump_methods em_ndump_methods = { + .poll_locked = em_poll, + .poll_unlocked = em_poll_unlocked, + .disable_intr = em_ndump_disable_intr, + .enable_intr = em_ndump_enable_intr +}; + +#endif + static device_method_t em_methods[] = { /* Device interface */ DEVMETHOD(device_probe, em_probe), @@ -1355,14 +1377,14 @@ em_init(void *arg) } -#ifdef DEVICE_POLLING +#if defined(DEVICE_POLLING) || defined(NETDUMP_CLIENT) /********************************************************************* * * Legacy polling routine: note this only works with single queue * *********************************************************************/ static int -em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) +_em_poll_generic(struct ifnet *ifp, enum poll_cmd cmd, int count, int locking) { struct adapter *adapter = ifp->if_softc; struct tx_ring *txr = adapter->tx_rings; @@ -1370,9 +1392,11 @@ em_poll(struct ifnet *ifp, enum poll_cmd u32 reg_icr; int rx_done; - EM_CORE_LOCK(adapter); + if (locking != 0) + EM_CORE_LOCK(adapter); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - EM_CORE_UNLOCK(adapter); + if (locking != 0) + EM_CORE_UNLOCK(adapter); return (0); } @@ -1386,11 +1410,13 @@ em_poll(struct ifnet *ifp, enum poll_cmd em_local_timer, adapter); } } - EM_CORE_UNLOCK(adapter); + if (locking != 0) + EM_CORE_UNLOCK(adapter); em_rxeof(rxr, count, &rx_done); - EM_TX_LOCK(txr); + if (locking != 0) + EM_TX_LOCK(txr); em_txeof(txr); #ifdef EM_MULTIQUEUE if (!drbr_empty(ifp, txr->br)) @@ -1399,12 +1425,50 @@ em_poll(struct ifnet *ifp, enum poll_cmd if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) em_start_locked(ifp, txr); #endif - EM_TX_UNLOCK(txr); + if (locking != 0) + EM_TX_UNLOCK(txr); return (rx_done); } -#endif /* DEVICE_POLLING */ +static int +em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) +{ + + return (_em_poll_generic(ifp, cmd, count, 1)); +} +#endif /* !DEVICE_POLLING && !NETDUMP_CLIENT */ + +#ifdef NETDUMP_CLIENT +static int +em_poll_unlocked(struct ifnet *ifp, enum poll_cmd cmd, int count) +{ + + return (_em_poll_generic(ifp, cmd, count, 0)); +} + +static void +em_ndump_disable_intr(struct ifnet *ifp) +{ + struct adapter *adapter; + + adapter = ifp->if_softc; + EM_CORE_LOCK(adapter); + em_disable_intr(adapter); + EM_CORE_UNLOCK(adapter); +} + +static void +em_ndump_enable_intr(struct ifnet *ifp) +{ + struct adapter *adapter; + + adapter = ifp->if_softc; + EM_CORE_LOCK(adapter); + em_enable_intr(adapter); + EM_CORE_UNLOCK(adapter); +} +#endif /* !NETDUMP_CLIENT */ /********************************************************************* * @@ -2676,6 +2740,9 @@ em_setup_interface(device_t dev, struct ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = em_ioctl; ifp->if_start = em_start; +#ifdef NETDUMP_CLIENT + ifp->if_ndumpfuncs = &em_ndump_methods; +#endif IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 1); ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 1; IFQ_SET_READY(&ifp->if_snd); Modified: projects/sv/sys/dev/e1000/if_lem.c ============================================================================== --- projects/sv/sys/dev/e1000/if_lem.c Mon Sep 27 14:50:51 2010 (r213199) +++ projects/sv/sys/dev/e1000/if_lem.c Mon Sep 27 15:24:16 2010 (r213200) @@ -35,6 +35,7 @@ #ifdef HAVE_KERNEL_OPTION_HEADERS #include "opt_device_polling.h" #include "opt_inet.h" +#include "opt_netdump.h" #endif #include @@ -72,6 +73,9 @@ #include #include #include +#ifdef NETDUMP_CLIENT +#include +#endif #include #include @@ -262,14 +266,32 @@ static void lem_add_rx_process_limit(str const char *, int *, int); #endif /* ~EM_LEGACY_IRQ */ -#ifdef DEVICE_POLLING +#if defined(DEVICE_POLLING) || defined(NETDUMP_CLIENT) +static int _lem_poll_generic(struct ifnet *ifp, enum poll_cmd cmd, + int count, int locking); static poll_handler_t lem_poll; -#endif /* POLLING */ +#endif +#ifdef NETDUMP_CLIENT +static poll_handler_t lem_poll_unlocked; +static ndumplock_handler_t lem_ndump_disable_intr; +static ndumplock_handler_t lem_ndump_enable_intr; +#endif /********************************************************************* * FreeBSD Device Interface Entry Points *********************************************************************/ +#ifdef NETDUMP_CLIENT + +static struct netdump_methods lem_ndump_methods = { + .poll_locked = lem_poll, + .poll_unlocked = lem_poll_unlocked, + .disable_intr = lem_ndump_disable_intr, + .enable_intr = lem_ndump_enable_intr +}; + +#endif + static device_method_t lem_methods[] = { /* Device interface */ DEVMETHOD(device_probe, lem_probe), @@ -1239,21 +1261,23 @@ lem_init(void *arg) } -#ifdef DEVICE_POLLING +#if defined(DEVICE_POLLING) || defined(NETDUMP_CLIENT) /********************************************************************* * * Legacy polling routine * *********************************************************************/ static int -lem_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) +_lem_poll_generic(struct ifnet *ifp, enum poll_cmd cmd, int count, int locking) { struct adapter *adapter = ifp->if_softc; u32 reg_icr, rx_done = 0; - EM_CORE_LOCK(adapter); + if (locking != 0) + EM_CORE_LOCK(adapter); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - EM_CORE_UNLOCK(adapter); + if (locking != 0) + EM_CORE_UNLOCK(adapter); return (rx_done); } @@ -1267,18 +1291,59 @@ lem_poll(struct ifnet *ifp, enum poll_cm lem_local_timer, adapter); } } - EM_CORE_UNLOCK(adapter); + if (locking != 0) + EM_CORE_UNLOCK(adapter); lem_rxeof(adapter, count, &rx_done); - EM_TX_LOCK(adapter); + if (locking != 0) + EM_TX_LOCK(adapter); lem_txeof(adapter); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) lem_start_locked(ifp); - EM_TX_UNLOCK(adapter); + if (locking != 0) + EM_TX_UNLOCK(adapter); return (rx_done); } -#endif /* DEVICE_POLLING */ + +static int +lem_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) +{ + + return (_lem_poll_generic(ifp, cmd, count, 1)); +} +#endif /* !DEVICE_POLLING && !NETDUMP_CLIENT */ + +#ifdef NETDUMP_CLIENT +static int +lem_poll_unlocked(struct ifnet *ifp, enum poll_cmd cmd, int count) +{ + + return (_lem_poll_generic(ifp, cmd, count, 0)); +} + +static void +lem_ndump_disable_intr(struct ifnet *ifp) +{ + struct adapter *adapter; + + adapter = ifp->if_softc; + EM_CORE_LOCK(adapter); + lem_disable_intr(adapter); + EM_CORE_UNLOCK(adapter); +} + +static void +lem_ndump_enable_intr(struct ifnet *ifp) +{ + struct adapter *adapter; + + adapter = ifp->if_softc; + EM_CORE_LOCK(adapter); + lem_enable_intr(adapter); + EM_CORE_UNLOCK(adapter); +} +#endif /* !NETDUMP_CLIENT */ #ifdef EM_LEGACY_IRQ /********************************************************************* @@ -2416,6 +2481,9 @@ lem_setup_interface(device_t dev, struct ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = lem_ioctl; ifp->if_start = lem_start; +#ifdef NETDUMP_CLIENT + ifp->if_ndumpfuncs = &lem_ndump_methods; +#endif IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 1); ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 1; IFQ_SET_READY(&ifp->if_snd); Modified: projects/sv/sys/netinet/netdump.h ============================================================================== --- projects/sv/sys/netinet/netdump.h Mon Sep 27 14:50:51 2010 (r213199) +++ projects/sv/sys/netinet/netdump.h Mon Sep 27 15:24:16 2010 (r213200) @@ -64,10 +64,10 @@ struct netdump_msg { typedef void ndumplock_handler_t(struct ifnet *); struct netdump_methods { - ndumplock_handler_t *test_get_lock; - ndumplock_handler_t *acquire_lock; - ndumplock_handler_t *release_lock; poll_handler_t *poll_locked; + poll_handler_t *poll_unlocked; + ndumplock_handler_t *disable_intr; + ndumplock_handler_t *enable_intr; }; #endif Modified: projects/sv/sys/netinet/netdump_client.c ============================================================================== --- projects/sv/sys/netinet/netdump_client.c Mon Sep 27 14:50:51 2010 (r213199) +++ projects/sv/sys/netinet/netdump_client.c Mon Sep 27 15:24:16 2010 (r213200) @@ -1063,7 +1063,12 @@ done: static void netdump_network_poll() { - nd_nic->if_ndumpfuncs->poll_locked(nd_nic, POLL_AND_CHECK_STATUS, 1000); + if (panicstr == NULL) + nd_nic->if_ndumpfuncs->poll_locked(nd_nic, + POLL_AND_CHECK_STATUS, 1000); + else + nd_nic->if_ndumpfuncs->poll_unlocked(nd_nic, + POLL_AND_CHECK_STATUS, 1000); } /*- @@ -1172,20 +1177,13 @@ netdump_trigger(void *arg, int howto) dumptid = curthread->td_tid; dumping++; - if (panicstr == NULL) - nd_nic->if_ndumpfuncs->acquire_lock(nd_nic); + if (panicstr == NULL && (nd_nic->if_capenable & IFCAP_POLLING) == 0) + nd_nic->if_ndumpfuncs->disable_intr(nd_nic); /* Make the card use *our* receive callback */ old_if_input = nd_nic->if_input; nd_nic->if_input = netdump_pkt_in; - /* Check if we can use polling */ - if (!(nd_nic->if_capenable & IFCAP_POLLING)) { - printf("netdump_trigger: Can't dump: interface %s does not have" - " polling enabled.\n", nd_nic->if_xname); - goto trig_abort; - } - if (nd_gw.s_addr == INADDR_ANY) { nd_gw.s_addr = nd_server.s_addr; } @@ -1230,8 +1228,8 @@ netdump_trigger(void *arg, int howto) trig_abort: if (old_if_input) nd_nic->if_input = old_if_input; - if (panicstr == NULL) - nd_nic->if_ndumpfuncs->release_lock(nd_nic); + if (panicstr == NULL && (nd_nic->if_capenable & IFCAP_POLLING) == 0) + nd_nic->if_ndumpfuncs->enable_intr(nd_nic); dumping--; }