Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Sep 2007 17:21:13 -0400
From:      "Robert Wojciechowski" <robertw@expressyard.com>
To:        <pyunyh@gmail.com>
Cc:        shigeaki@f.csce.kyushu-u.ac.jp, freebsd-net@freebsd.org, Josh Mouch <jmouch@expressyard.com>
Subject:   RE: FreeBSD nfe driver and IPMI cards
Message-ID:  <85D4F2C294E8434CA0AF775741532686623694@server1.ssgi.local>
In-Reply-To: <20070912004554.GA8992@cdnetworks.co.kr>
References:  <85D4F2C294E8434CA0AF775741532686623679@server1.ssgi.local> <20070912004554.GA8992@cdnetworks.co.kr>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
>  > I'm the FreeBSD nfe driver from
>  >
http://www.f.csce.kyushu-u.ac.jp/~shigeaki/software/freebsd-nfe.html
>  > with FreeBSD 6-stable with good results for the most part. The only
>  > issue I've experienced is that during a detach/shutdown of if_nfe,
> the
>  > IPMI IP address I have set on my servers ceases to respond as well
> as
>  > the ability to manage the servers.
>  >
>  >
>  >
>  > I traced the problem down to nfe_stop() and the fact that it
> completely
>  > disables the Rx and Tx on the NIC. I have patched the driver to not
>  > disable the Rx/Tx and IPMI continues to work after a 'ifconfig nfe0
>  > down', 'shutdown -p now', etc.
>  >
>  >
>  >
>  > Does anyone have any comments on this change I've made and any
> possible
>  > side effects? Can this be included in the mainstream distribution
of
> the
> 
> Because MAC is still alive if's possible to recieve a packet. All DMA
> maps are unloaded and buffers are already freed in nfe_stop so it
> would cause panic I guess. But I'm not familiar with IPMI so I'm not
> sure.

Interesting, that is an issue that was also resolved by the forcedeth
driver in Linux by resetting in nv_close to prevent DMA into freed
memory.

> 
>  > nfe drivers (and updated in 7-CURRENT) without causing any adverse
>  > problems?
>  >
> 
> I have no experience on IPMI but the change you've made would not
> completely solve the issue. I guess supporting IPMI needs lots of
> more work including:
>  o Autodetect IPMI capability.
>  o Autodetect active IPMI session in device attach and don't blindly
>    reset MAC/PHY.
>  o Don't blindly stop Tx/Rx on device detach.
> Given that lack of publicly available datasheet for the hardware
> supporing IPMI would be severly limited. Fortunately Linux seems to
> have basic IPMI support in their forcedeth driver. Their code doesn't
> easy to read but you may see what should be done in driver. However
> I have no idea what we can do when active IPMI session is present in
> driver attach phase. Normally PHY driver would reset PHY hardware
> itself in driver attach which in turn would result in losing the IPMI
> connection.
> 

Since we have no idea how to auto-detect IPMI, I added a device sysctl
(enable_ipmi) to control the behavior I'm testing in-house right now.

If the enable_ipmi sysctl is enabled, it'll:

  * resets after disabling the Rx/Tx and before disabling interrupts
  * re-enables the Rx/Tx after the ring buffers are freed, just like
forcedeth but also enabling the Tx for IPMI (Linux just enabled the Rx
for WOL)

I have attached my new patch to this email that does the above, guarded
by the sysctl.

I have no idea how to handle the second case you mentioned, during
attach. It does indeed cause a disruption in IPMI, but only for a few
seconds. Where is the MAC and PHY reset and if it wasn't reset when
using IPMI, what problems could it cause?

-- Robert

[-- Attachment #2 --]
diff -ur nfe-20070816/if_nfe.c nfe-20070816-ssgi/if_nfe.c
--- nfe-20070816/if_nfe.c	Tue Sep 11 07:36:24 2007
+++ nfe-20070816-ssgi/if_nfe.c	Wed Sep 12 13:02:37 2007
@@ -24,7 +24,7 @@
 __FBSDID("$FreeBSD: src/sys/dev/nfe/if_nfe.c,v 1.19 2007/07/24 01:11:00 yongari Exp $");
 
 /* Uncomment the following line to enable polling. */
-#define	DEVICE_POLLING
+/* #define	DEVICE_POLLING */
 
 #ifdef HAVE_KERNEL_OPTION_HEADERS
 #include "opt_device_polling.h"
@@ -81,6 +81,7 @@
 static int  nfe_resume(device_t);
 static void nfe_shutdown(device_t);
 static void nfe_power(struct nfe_softc *);
+static void nfe_reset(struct nfe_softc *);
 static int  nfe_miibus_readreg(device_t, int, int);
 static int  nfe_miibus_writereg(device_t, int, int, int);
 static void nfe_miibus_statchg(device_t);
@@ -127,6 +128,7 @@
 static void nfe_dma_map_segs(void *, bus_dma_segment_t *, int, int);
 
 static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int);
+static int sysctl_hw_nfe_enable_ipmi(SYSCTL_HANDLER_ARGS);
 static int sysctl_hw_nfe_proc_limit(SYSCTL_HANDLER_ARGS);
 
 #ifdef NFE_DEBUG
@@ -534,6 +536,23 @@
 
 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+	    OID_AUTO, "enable_ipmi", CTLTYPE_INT | CTLFLAG_RW,
+	    &sc->nfe_enable_ipmi, 0, sysctl_hw_nfe_enable_ipmi, "I",
+	    "enable IPMI");
+
+	sc->nfe_enable_ipmi = NFE_ENABLE_IPMI_DEFAULT;
+	error = resource_int_value(device_get_name(dev), device_get_unit(dev),
+	    "enable_ipmi", &sc->nfe_enable_ipmi);
+	if (error == 0) {
+		if (sc->nfe_process_limit < 0 || sc->nfe_process_limit > 1) {
+			device_printf(dev, "enable_ipmi value out of range; "
+			    "using default: %d\n", NFE_ENABLE_IPMI_DEFAULT);
+			sc->nfe_enable_ipmi = NFE_ENABLE_IPMI_DEFAULT;
+		}
+	}
+
+	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
 	    OID_AUTO, "process_limit", CTLTYPE_INT | CTLFLAG_RW,
 	    &sc->nfe_process_limit, 0, sysctl_hw_nfe_proc_limit, "I",
 	    "max number of Rx events to process");
@@ -779,12 +798,7 @@
 
 	if ((sc->nfe_flags & NFE_PWR_MGMT) == 0)
 		return;
-	NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_RESET | NFE_RXTX_BIT2);
-	NFE_WRITE(sc, NFE_MAC_RESET, NFE_MAC_RESET_MAGIC);
-	DELAY(100);
-	NFE_WRITE(sc, NFE_MAC_RESET, 0);
-	DELAY(100);
-	NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_BIT2);
+	nfe_reset(sc);
 	pwr = NFE_READ(sc, NFE_PWR2_CTL);
 	pwr &= ~NFE_PWR2_WAKEUP_MASK;
 	if (sc->nfe_revid >= 0xa3 &&
@@ -794,6 +808,15 @@
 	NFE_WRITE(sc, NFE_PWR2_CTL, pwr);
 }
 
+static void
+nfe_reset(struct nfe_softc *sc)
+{
+	NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_RESET | NFE_RXTX_BIT2);
+	NFE_WRITE(sc, NFE_MAC_RESET, NFE_MAC_RESET_MAGIC);
+	DELAY(100);
+	NFE_WRITE(sc, NFE_MAC_RESET, 0);
+	DELAY(100);
+}
 
 static void
 nfe_miibus_statchg(device_t dev)
@@ -3009,6 +3032,11 @@
 	/* disable Rx */
 	NFE_WRITE(sc, NFE_RX_CTL, 0);
 
+	/* reset the Tx/Rx so the NIC does not DMA into freed memory */
+	if (&sc->nfe_enable_ipmi) {
+		nfe_reset(sc);
+	}
+
 	/* disable interrupts */
 	nfe_disable_intr(sc);
 
@@ -3055,6 +3083,12 @@
 			tdata->m = NULL;
 		}
 	}
+
+	/* enable the Tx/Rx for IPMI support */
+	if (&sc->nfe_enable_ipmi) {
+		NFE_WRITE(sc, NFE_TX_CTL, NFE_TX_START);
+		NFE_WRITE(sc, NFE_RX_CTL, NFE_RX_START);
+	}
 }
 
 
@@ -3210,4 +3244,11 @@
 
 	return (sysctl_int_range(oidp, arg1, arg2, req, NFE_PROC_MIN,
 	    NFE_PROC_MAX));
+}
+
+
+static int
+sysctl_hw_nfe_enable_ipmi(SYSCTL_HANDLER_ARGS)
+{
+	return (sysctl_int_range(oidp, arg1, arg2, req, 0, 1));
 }
Only in nfe-20070816-ssgi: if_nfe.c.orig
Only in nfe-20070816-ssgi: if_nfe.c.rej
Binary files nfe-20070816/if_nfe.ko and nfe-20070816-ssgi/if_nfe.ko differ
Binary files nfe-20070816/if_nfe.o and nfe-20070816-ssgi/if_nfe.o differ
diff -ur nfe-20070816/if_nfereg.h nfe-20070816-ssgi/if_nfereg.h
--- nfe-20070816/if_nfereg.h	Wed Aug 15 20:51:18 2007
+++ nfe-20070816-ssgi/if_nfereg.h	Wed Sep 12 12:45:37 2007
@@ -22,6 +22,7 @@
 #define	NFE_JUMBO_RX_RING_COUNT	NFE_RX_RING_COUNT
 #define	NFE_TX_RING_COUNT	256
 
+#define	NFE_ENABLE_IPMI_DEFAULT	0
 #define	NFE_PROC_DEFAULT	((NFE_RX_RING_COUNT * 3) / 4)
 #define	NFE_PROC_MIN		50
 #define	NFE_PROC_MAX		(NFE_RX_RING_COUNT - 1)
diff -ur nfe-20070816/if_nfevar.h nfe-20070816-ssgi/if_nfevar.h
--- nfe-20070816/if_nfevar.h	Wed Aug 15 20:51:18 2007
+++ nfe-20070816-ssgi/if_nfevar.h	Wed Sep 12 12:35:47 2007
@@ -115,6 +115,7 @@
 	int			nfe_suspended;
 	int			nfe_framesize;
 	int			nfe_process_limit;
+	int			nfe_enable_ipmi;
 	int			nfe_force_tx;
 	uint32_t		nfe_irq_status;
 	uint32_t		nfe_irq_mask;

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