Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Sep 2010 15:24:16 +0000 (UTC)
From:      Attilio Rao <attilio@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r213200 - in projects/sv/sys: dev/e1000 netinet
Message-ID:  <201009271524.o8RFOGOm040224@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <sys/param.h>
@@ -73,6 +74,9 @@
 #include <netinet/if_ether.h>
 #include <netinet/ip.h>
 #include <netinet/ip6.h>
+#ifdef NETDUMP_CLIENT
+#include <netinet/netdump.h>
+#endif
 #include <netinet/tcp.h>
 #include <netinet/udp.h>
 
@@ -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 <sys/param.h>
@@ -72,6 +73,9 @@
 #include <netinet/if_ether.h>
 #include <netinet/ip.h>
 #include <netinet/ip6.h>
+#ifdef NETDUMP_CLIENT
+#include <netinet/netdump.h>
+#endif
 #include <netinet/tcp.h>
 #include <netinet/udp.h>
 
@@ -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--;
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201009271524.o8RFOGOm040224>