svn commit: r213200 - in projects/sv/sys: dev/e1000 netinet
Attilio Rao
attilio at FreeBSD.org
Mon Sep 27 15:24:17 UTC 2010
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--;
}
More information about the svn-src-projects
mailing list