svn commit: r185644 - in stable/6: share/man/man4 sys/amd64/conf
sys/conf sys/dev/nfe sys/i386/conf sys/modules sys/modules/nfe
John Baldwin
jhb at FreeBSD.org
Fri Dec 5 09:44:27 PST 2008
Author: jhb
Date: Fri Dec 5 17:44:26 2008
New Revision: 185644
URL: http://svn.freebsd.org/changeset/base/185644
Log:
MFC: Add the nfe(4) driver as an alternative to nve(4). To avoid
astonishment, nve(4) takes precedence over nfe(4) in this branch.
I have also not added it to GENERIC.
Reviewed by: yongari (briefly)
Added:
stable/6/share/man/man4/nfe.4
- copied, changed from r159967, head/share/man/man4/nfe.4
stable/6/sys/dev/nfe/
stable/6/sys/dev/nfe/if_nfe.c (contents, props changed)
stable/6/sys/dev/nfe/if_nfereg.h (contents, props changed)
stable/6/sys/dev/nfe/if_nfevar.h (contents, props changed)
stable/6/sys/modules/nfe/
stable/6/sys/modules/nfe/Makefile (contents, props changed)
Modified:
stable/6/share/man/man4/ (props changed)
stable/6/share/man/man4/Makefile
stable/6/share/man/man4/polling.4
stable/6/share/man/man4/xl.4 (props changed)
stable/6/sys/amd64/conf/NOTES
stable/6/sys/conf/files.amd64
stable/6/sys/conf/files.i386
stable/6/sys/i386/conf/NOTES
stable/6/sys/modules/Makefile
Modified: stable/6/share/man/man4/Makefile
==============================================================================
--- stable/6/share/man/man4/Makefile Fri Dec 5 17:13:40 2008 (r185643)
+++ stable/6/share/man/man4/Makefile Fri Dec 5 17:44:26 2008 (r185644)
@@ -180,6 +180,7 @@ MAN= aac.4 \
ncv.4 \
netgraph.4 \
netintro.4 \
+ ${_nfe.4} \
${_nfsmb.4} \
ng_async.4 \
ng_atm.4 \
@@ -469,6 +470,7 @@ MLINKS+=mxge.4 if_mxge.4
MLINKS+=my.4 if_my.4
MLINKS+=netintro.4 net.4 \
netintro.4 networking.4
+MLINKS+=${_nfe.4} ${_if_nfe.4}
MLINKS+=nge.4 if_nge.4
MLINKS+=${_nve.4} ${_if_nve.4}
MLINKS+=oldcard.4 card.4
@@ -522,9 +524,11 @@ MLINKS+=watchdog.4 SW_WATCHDOG.4
.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386"
_amdsmb.4= amdsmb.4
_coretemp.4= coretemp.4
+_if_nfe.4= if_nfe.4
_if_nve.4= if_nve.4
_ipmi.4= ipmi.4
_nfsmb.4= nfsmb.4
+_nfe.4= nfe.4
_nve.4= nve.4
_rr232x.4= rr232x.4
_spkr.4= spkr.4
Copied and modified: stable/6/share/man/man4/nfe.4 (from r159967, head/share/man/man4/nfe.4)
==============================================================================
--- head/share/man/man4/nfe.4 Mon Jun 26 23:41:07 2006 (r159967, copy source)
+++ stable/6/share/man/man4/nfe.4 Fri Dec 5 17:44:26 2008 (r185644)
@@ -16,7 +16,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 6, 2006
+.Dd October 2, 2008
.Dt NFE 4
.Os
.Sh NAME
@@ -28,7 +28,7 @@ place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device miibus"
-.Cd "device nve"
+.Cd "device nfe"
.Ed
.Pp
Alternatively, to load the driver as a
@@ -42,31 +42,139 @@ The
.Nm
driver supports PCI Ethernet adapters based on the NVIDIA
nForce Media and Communications Processors (MCP), such as
-the nForce, nForce 2, nForce 3, CK804, MCP04, MCP51 and MCP55
-Ethernet controller chips.
+the nForce, nForce 2, nForce 3, CK804, MCP04, MCP51, MCP55,
+MCP61, MCP65, MCP67, MCP73, MCP77 and MCP79 Ethernet
+controller chips.
+.Pp
+Supported features include (hardware support provided):
+.Pp
+.Bl -bullet -compact
+.It
+Receive/Transmit IP/TCP/UDP checksum offload
+.It
+Hardware VLAN tag insertion/stripping
+.It
+TCP segmentation offload (TSO)
+.It
+MSI/MSI-X
+.It
+Jumbo Frames
+.El
+.Pp
+Support for Jumbo Frames is provided via the interface MTU setting.
+Selecting an MTU larger than 1500 bytes with the
+.Xr ifconfig 8
+utility configures the adapter to receive and transmit Jumbo Frames.
.Pp
The
.Nm
-driver supports the following
-.Ar media
-types:
-.Pp
-.Bl -tag -width autoselect -compact
+driver supports the following media types:
+.Bl -tag -width "10baseT/UTP"
.It Cm autoselect
Enable autoselection of the media type and options.
-.It Cm 10baseT
+.It Cm 10baseT/UTP
Set 10Mbps operation.
.It Cm 100baseTX
Set 100Mbps (Fast Ethernet) operation.
.It Cm 1000baseT
Set 1000Mbps (Gigabit Ethernet) operation (recent models only).
.El
+.Pp
+The
+.Nm
+driver supports the following media options:
+.Bl -tag -width ".Cm 10baseT/UTP"
+.It Cm half-duplex
+Force half duplex operation.
+.It Cm full-duplex
+Force full duplex operation.
+.El
+.Pp
+For more information on configuring this device, see
+.Xr ifconfig 8 .
+.Sh HARDWARE
+The
+.Nm
+driver supports the following NVIDIA MCP onboard adapters:
+.Pp
+.Bl -bullet -compact
+.It
+NVIDIA nForce MCP Networking Adapter
+.It
+NVIDIA nForce MCP04 Networking Adapter
+.It
+NVIDIA nForce 430 MCP12 Networking Adapter
+.It
+NVIDIA nForce 430 MCP13 Networking Adapter
+.It
+NVIDIA nForce MCP51 Networking Adapter
+.It
+NVIDIA nForce MCP55 Networking Adapter
+.It
+NVIDIA nForce MCP61 Networking Adapter
+.It
+NVIDIA nForce MCP65 Networking Adapter
+.It
+NVIDIA nForce MCP67 Networking Adapter
+.It
+NVIDIA nForce MCP73 Networking Adapter
+.It
+NVIDIA nForce MCP77 Networking Adapter
+.It
+NVIDIA nForce MCP79 Networking Adapter
+.It
+NVIDIA nForce2 MCP2 Networking Adapter
+.It
+NVIDIA nForce2 400 MCP4 Networking Adapter
+.It
+NVIDIA nForce2 400 MCP5 Networking Adapter
+.It
+NVIDIA nForce3 MCP3 Networking Adapter
+.It
+NVIDIA nForce3 250 MCP6 Networking Adapter
+.It
+NVIDIA nForce3 MCP7 Networking Adapter
+.It
+NVIDIA nForce4 CK804 MCP8 Networking Adapter
+.It
+NVIDIA nForce4 CK804 MCP9 Networking Adapter
+.El
+.Sh LOADER TUNABLES
+Tunables can be set at the
+.Xr loader 8
+prompt before booting the kernel or stored in
+.Xr loader.conf 5 .
+.Bl -tag -width indent
+.It Va hw.nfe.msi_disable
+Whether or not MSI support is enabled in the driver.
+The default value is 0.
+.It Va hw.nfe.msix_disable
+Whether or not MSI-X support is enabled in the driver.
+The default value is 0.
+.El
+.Sh SYSCTL VARIABLES
+The following
+.Xr sysctl 8
+variables can be used to modify or monitor
+.Nm
+behavior.
+.Bl -tag -width indent
+.It Va dev.nfe.%d.process_limit
+Maximum number of Rx events to be processed in the event loop
+before rescheduling a taskqueue.
+The accepted range is 50 to 255, the default value is 192.
+The interface does not need to be brought down and up again
+before a change takes effect.
+.El
.Sh SEE ALSO
+.Xr altq 4 ,
.Xr arp 4 ,
.Xr intro 4 ,
.Xr miibus 4 ,
.Xr netintro 4 ,
.Xr pci 4 ,
+.Xr polling 4 ,
+.Xr sysctl 8 ,
.Xr ifconfig 8
.Sh HISTORY
The
@@ -74,7 +182,7 @@ The
device driver first appeared in
.Ox 3.9 ,
and then in
-.Fx 6.0 .
+.Fx 7.0 .
.Sh AUTHORS
.An -nosplit
The
@@ -92,5 +200,3 @@ driver was ported to
by
.An Shigeaki Tagashira
.Aq shigeaki at se.hiroshima-u.ac.jp .
-.Sh CAVEATS
-NVIDIA refuse to release any documentation on their products.
Modified: stable/6/share/man/man4/polling.4
==============================================================================
--- stable/6/share/man/man4/polling.4 Fri Dec 5 17:13:40 2008 (r185643)
+++ stable/6/share/man/man4/polling.4 Fri Dec 5 17:44:26 2008 (r185644)
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 2, 2006
+.Dd April 6, 2007
.Dt POLLING 4
.Os
.Sh NAME
@@ -184,6 +184,7 @@ As of this writing, the
.Xr fwip 4 ,
.Xr fxp 4 ,
.Xr ixgb 4 ,
+.Xr nfe 4 ,
.Xr nge 4 ,
.Xr re 4 ,
.Xr rl 4 ,
Modified: stable/6/sys/amd64/conf/NOTES
==============================================================================
--- stable/6/sys/amd64/conf/NOTES Fri Dec 5 17:13:40 2008 (r185643)
+++ stable/6/sys/amd64/conf/NOTES Fri Dec 5 17:44:26 2008 (r185644)
@@ -234,6 +234,7 @@ options DRM_DEBUG # Include debug print
# lnc: Lance/PCnet cards (Isolan, Novell NE2100, NE32-VL, AMD Am7990 and
# Am79C960)
# mxge: Myricom Myri-10G 10GbE NIC
+# nfe: nVidia nForce MCP on-board Ethernet Networking (BSD open source)
# nve: nVidia nForce MCP on-board Ethernet Networking
#XXX# still calls MD i386 kvtop function instead of vtophys etc
@@ -243,6 +244,7 @@ options DRM_DEBUG # Include debug print
#XXX#options ED_SIC
#XXX#device lnc
device mxge # Myricom Myri-10G 10GbE NIC
+device nfe # nVidia nForce MCP on-board Ethernet Networking
device nve # nVidia nForce MCP on-board Ethernet Networking
device ath
Modified: stable/6/sys/conf/files.amd64
==============================================================================
--- stable/6/sys/conf/files.amd64 Fri Dec 5 17:13:40 2008 (r185643)
+++ stable/6/sys/conf/files.amd64 Fri Dec 5 17:44:26 2008 (r185644)
@@ -200,6 +200,7 @@ dev/mxge/mxge_ethp_z8e.c optional mxge p
dev/mxge/mxge_rss_eth_z8e.c optional mxge pci
dev/mxge/mxge_rss_ethp_z8e.c optional mxge pci
net/zlib.c optional mxge
+dev/nfe/if_nfe.c optional nfe pci
dev/nve/if_nve.c optional nve pci
dev/nvram/nvram.c optional nvram isa
dev/rr232x/os_bsd.c optional rr232x
Modified: stable/6/sys/conf/files.i386
==============================================================================
--- stable/6/sys/conf/files.i386 Fri Dec 5 17:13:40 2008 (r185643)
+++ stable/6/sys/conf/files.i386 Fri Dec 5 17:44:26 2008 (r185644)
@@ -234,6 +234,7 @@ dev/mxge/mxge_ethp_z8e.c optional mxge p
dev/mxge/mxge_rss_eth_z8e.c optional mxge pci
dev/mxge/mxge_rss_ethp_z8e.c optional mxge pci
net/zlib.c optional mxge
+dev/nfe/if_nfe.c optional nfe pci
dev/nve/if_nve.c optional nve pci
dev/nvram/nvram.c optional nvram isa
dev/ppc/ppc.c optional ppc
Added: stable/6/sys/dev/nfe/if_nfe.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ stable/6/sys/dev/nfe/if_nfe.c Fri Dec 5 17:44:26 2008 (r185644)
@@ -0,0 +1,2993 @@
+/* $OpenBSD: if_nfe.c,v 1.54 2006/04/07 12:38:12 jsg Exp $ */
+
+/*-
+ * Copyright (c) 2006 Shigeaki Tagashira <shigeaki at se.hiroshima-u.ac.jp>
+ * Copyright (c) 2006 Damien Bergamini <damien.bergamini at free.fr>
+ * Copyright (c) 2005, 2006 Jonathan Gray <jsg at openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* Driver for NVIDIA nForce MCP Fast Ethernet and Gigabit Ethernet */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_KERNEL_OPTION_HEADERS
+#include "opt_device_polling.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/endian.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_vlan_var.h>
+
+#include <net/bpf.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/nfe/if_nfereg.h>
+#include <dev/nfe/if_nfevar.h>
+
+MODULE_DEPEND(nfe, pci, 1, 1, 1);
+MODULE_DEPEND(nfe, ether, 1, 1, 1);
+MODULE_DEPEND(nfe, miibus, 1, 1, 1);
+
+/* "device miibus" required. See GENERIC if you get errors here. */
+#include "miibus_if.h"
+
+static int nfe_probe(device_t);
+static int nfe_attach(device_t);
+static int nfe_detach(device_t);
+static int nfe_suspend(device_t);
+static int nfe_resume(device_t);
+static int nfe_shutdown(device_t);
+static void nfe_power(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);
+static void nfe_link_task(void *, int);
+static void nfe_set_intr(struct nfe_softc *);
+static __inline void nfe_enable_intr(struct nfe_softc *);
+static __inline void nfe_disable_intr(struct nfe_softc *);
+static int nfe_ioctl(struct ifnet *, u_long, caddr_t);
+static void nfe_alloc_msix(struct nfe_softc *, int);
+static void nfe_intr(void *);
+static void nfe_int_task(void *, int);
+static __inline void nfe_discard_rxbuf(struct nfe_softc *, int);
+static __inline void nfe_discard_jrxbuf(struct nfe_softc *, int);
+static int nfe_newbuf(struct nfe_softc *, int);
+static int nfe_jnewbuf(struct nfe_softc *, int);
+static int nfe_rxeof(struct nfe_softc *, int);
+static int nfe_jrxeof(struct nfe_softc *, int);
+static void nfe_txeof(struct nfe_softc *);
+static int nfe_encap(struct nfe_softc *, struct mbuf **);
+static void nfe_setmulti(struct nfe_softc *);
+static void nfe_tx_task(void *, int);
+static void nfe_start(struct ifnet *);
+static void nfe_watchdog(struct ifnet *);
+static void nfe_init(void *);
+static void nfe_init_locked(void *);
+static void nfe_stop(struct ifnet *);
+static int nfe_alloc_rx_ring(struct nfe_softc *, struct nfe_rx_ring *);
+static void nfe_alloc_jrx_ring(struct nfe_softc *, struct nfe_jrx_ring *);
+static int nfe_init_rx_ring(struct nfe_softc *, struct nfe_rx_ring *);
+static int nfe_init_jrx_ring(struct nfe_softc *, struct nfe_jrx_ring *);
+static void nfe_free_rx_ring(struct nfe_softc *, struct nfe_rx_ring *);
+static void nfe_free_jrx_ring(struct nfe_softc *, struct nfe_jrx_ring *);
+static int nfe_alloc_tx_ring(struct nfe_softc *, struct nfe_tx_ring *);
+static void nfe_init_tx_ring(struct nfe_softc *, struct nfe_tx_ring *);
+static void nfe_free_tx_ring(struct nfe_softc *, struct nfe_tx_ring *);
+static int nfe_ifmedia_upd(struct ifnet *);
+static void nfe_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static void nfe_tick(void *);
+static void nfe_get_macaddr(struct nfe_softc *, uint8_t *);
+static void nfe_set_macaddr(struct nfe_softc *, uint8_t *);
+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_proc_limit(SYSCTL_HANDLER_ARGS);
+
+#ifdef NFE_DEBUG
+static int nfedebug = 0;
+#define DPRINTF(sc, ...) do { \
+ if (nfedebug) \
+ device_printf((sc)->nfe_dev, __VA_ARGS__); \
+} while (0)
+#define DPRINTFN(sc, n, ...) do { \
+ if (nfedebug >= (n)) \
+ device_printf((sc)->nfe_dev, __VA_ARGS__); \
+} while (0)
+#else
+#define DPRINTF(sc, ...)
+#define DPRINTFN(sc, n, ...)
+#endif
+
+#define NFE_LOCK(_sc) mtx_lock(&(_sc)->nfe_mtx)
+#define NFE_UNLOCK(_sc) mtx_unlock(&(_sc)->nfe_mtx)
+#define NFE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->nfe_mtx, MA_OWNED)
+
+/* Tunables. */
+static int msi_disable = 0;
+static int msix_disable = 0;
+static int jumbo_disable = 0;
+TUNABLE_INT("hw.nfe.msi_disable", &msi_disable);
+TUNABLE_INT("hw.nfe.msix_disable", &msix_disable);
+TUNABLE_INT("hw.nfe.jumbo_disable", &jumbo_disable);
+
+static device_method_t nfe_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, nfe_probe),
+ DEVMETHOD(device_attach, nfe_attach),
+ DEVMETHOD(device_detach, nfe_detach),
+ DEVMETHOD(device_suspend, nfe_suspend),
+ DEVMETHOD(device_resume, nfe_resume),
+ DEVMETHOD(device_shutdown, nfe_shutdown),
+
+ /* bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, nfe_miibus_readreg),
+ DEVMETHOD(miibus_writereg, nfe_miibus_writereg),
+ DEVMETHOD(miibus_statchg, nfe_miibus_statchg),
+
+ { NULL, NULL }
+};
+
+static driver_t nfe_driver = {
+ "nfe",
+ nfe_methods,
+ sizeof(struct nfe_softc)
+};
+
+static devclass_t nfe_devclass;
+
+DRIVER_MODULE(nfe, pci, nfe_driver, nfe_devclass, 0, 0);
+DRIVER_MODULE(miibus, nfe, miibus_driver, miibus_devclass, 0, 0);
+
+static struct nfe_type nfe_devs[] = {
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE_LAN,
+ "NVIDIA nForce MCP Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_LAN,
+ "NVIDIA nForce2 MCP2 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN1,
+ "NVIDIA nForce2 400 MCP4 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN2,
+ "NVIDIA nForce2 400 MCP5 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN1,
+ "NVIDIA nForce3 MCP3 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_250_LAN,
+ "NVIDIA nForce3 250 MCP6 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN4,
+ "NVIDIA nForce3 MCP7 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_LAN1,
+ "NVIDIA nForce4 CK804 MCP8 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_LAN2,
+ "NVIDIA nForce4 CK804 MCP9 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN1,
+ "NVIDIA nForce MCP04 Networking Adapter"}, /* MCP10 */
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN2,
+ "NVIDIA nForce MCP04 Networking Adapter"}, /* MCP11 */
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE430_LAN1,
+ "NVIDIA nForce 430 MCP12 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE430_LAN2,
+ "NVIDIA nForce 430 MCP13 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN1,
+ "NVIDIA nForce MCP55 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN2,
+ "NVIDIA nForce MCP55 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN1,
+ "NVIDIA nForce MCP61 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN2,
+ "NVIDIA nForce MCP61 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN3,
+ "NVIDIA nForce MCP61 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN4,
+ "NVIDIA nForce MCP61 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN1,
+ "NVIDIA nForce MCP65 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN2,
+ "NVIDIA nForce MCP65 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN3,
+ "NVIDIA nForce MCP65 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN4,
+ "NVIDIA nForce MCP65 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN1,
+ "NVIDIA nForce MCP67 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN2,
+ "NVIDIA nForce MCP67 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN3,
+ "NVIDIA nForce MCP67 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN4,
+ "NVIDIA nForce MCP67 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_LAN1,
+ "NVIDIA nForce MCP73 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_LAN2,
+ "NVIDIA nForce MCP73 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_LAN3,
+ "NVIDIA nForce MCP73 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_LAN4,
+ "NVIDIA nForce MCP73 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_LAN1,
+ "NVIDIA nForce MCP77 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_LAN2,
+ "NVIDIA nForce MCP77 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_LAN3,
+ "NVIDIA nForce MCP77 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_LAN4,
+ "NVIDIA nForce MCP77 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_LAN1,
+ "NVIDIA nForce MCP79 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_LAN2,
+ "NVIDIA nForce MCP79 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_LAN3,
+ "NVIDIA nForce MCP79 Networking Adapter"},
+ {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_LAN4,
+ "NVIDIA nForce MCP79 Networking Adapter"},
+ {0, 0, NULL}
+};
+
+
+/* Probe for supported hardware ID's */
+static int
+nfe_probe(device_t dev)
+{
+ struct nfe_type *t;
+
+ t = nfe_devs;
+ /* Check for matching PCI DEVICE ID's */
+ while (t->name != NULL) {
+ if ((pci_get_vendor(dev) == t->vid_id) &&
+ (pci_get_device(dev) == t->dev_id)) {
+ device_set_desc(dev, t->name);
+ return (BUS_PROBE_LOW_PRIORITY);
+ }
+ t++;
+ }
+
+ return (ENXIO);
+}
+
+static void
+nfe_alloc_msix(struct nfe_softc *sc, int count)
+{
+ int rid;
+
+ rid = PCIR_BAR(2);
+ sc->nfe_msix_res = bus_alloc_resource_any(sc->nfe_dev, SYS_RES_MEMORY,
+ &rid, RF_ACTIVE);
+ if (sc->nfe_msix_res == NULL) {
+ device_printf(sc->nfe_dev,
+ "couldn't allocate MSIX table resource\n");
+ return;
+ }
+ rid = PCIR_BAR(3);
+ sc->nfe_msix_pba_res = bus_alloc_resource_any(sc->nfe_dev,
+ SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->nfe_msix_pba_res == NULL) {
+ device_printf(sc->nfe_dev,
+ "couldn't allocate MSIX PBA resource\n");
+ bus_release_resource(sc->nfe_dev, SYS_RES_MEMORY, PCIR_BAR(2),
+ sc->nfe_msix_res);
+ sc->nfe_msix_res = NULL;
+ return;
+ }
+
+ if (pci_alloc_msix(sc->nfe_dev, &count) == 0) {
+ if (count == NFE_MSI_MESSAGES) {
+ if (bootverbose)
+ device_printf(sc->nfe_dev,
+ "Using %d MSIX messages\n", count);
+ sc->nfe_msix = 1;
+ } else {
+ if (bootverbose)
+ device_printf(sc->nfe_dev,
+ "couldn't allocate MSIX\n");
+ pci_release_msi(sc->nfe_dev);
+ bus_release_resource(sc->nfe_dev, SYS_RES_MEMORY,
+ PCIR_BAR(3), sc->nfe_msix_pba_res);
+ bus_release_resource(sc->nfe_dev, SYS_RES_MEMORY,
+ PCIR_BAR(2), sc->nfe_msix_res);
+ sc->nfe_msix_pba_res = NULL;
+ sc->nfe_msix_res = NULL;
+ }
+ }
+}
+
+static int
+nfe_attach(device_t dev)
+{
+ struct nfe_softc *sc;
+ struct ifnet *ifp;
+ bus_addr_t dma_addr_max;
+ int error = 0, i, msic, reg, rid;
+
+ sc = device_get_softc(dev);
+ sc->nfe_dev = dev;
+
+ mtx_init(&sc->nfe_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
+ MTX_DEF);
+ callout_init_mtx(&sc->nfe_stat_ch, &sc->nfe_mtx, 0);
+ TASK_INIT(&sc->nfe_link_task, 0, nfe_link_task, sc);
+
+ pci_enable_busmaster(dev);
+
+ rid = PCIR_BAR(0);
+ sc->nfe_res[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->nfe_res[0] == NULL) {
+ device_printf(dev, "couldn't map memory resources\n");
+ mtx_destroy(&sc->nfe_mtx);
+ return (ENXIO);
+ }
+
+ if (pci_find_extcap(dev, PCIY_EXPRESS, ®) == 0) {
+ uint16_t v, width;
+
+ v = pci_read_config(dev, reg + 0x08, 2);
+ /* Change max. read request size to 4096. */
+ v &= ~(7 << 12);
+ v |= (5 << 12);
+ pci_write_config(dev, reg + 0x08, v, 2);
+
+ v = pci_read_config(dev, reg + 0x0c, 2);
+ /* link capability */
+ v = (v >> 4) & 0x0f;
+ width = pci_read_config(dev, reg + 0x12, 2);
+ /* negotiated link width */
+ width = (width >> 4) & 0x3f;
+ if (v != width)
+ device_printf(sc->nfe_dev,
+ "warning, negotiated width of link(x%d) != "
+ "max. width of link(x%d)\n", width, v);
+ }
+
+ /* Allocate interrupt */
+ if (msix_disable == 0 || msi_disable == 0) {
+ if (msix_disable == 0 &&
+ (msic = pci_msix_count(dev)) == NFE_MSI_MESSAGES)
+ nfe_alloc_msix(sc, msic);
+ if (msi_disable == 0 && sc->nfe_msix == 0 &&
+ (msic = pci_msi_count(dev)) == NFE_MSI_MESSAGES &&
+ pci_alloc_msi(dev, &msic) == 0) {
+ if (msic == NFE_MSI_MESSAGES) {
+ if (bootverbose)
+ device_printf(dev,
+ "Using %d MSI messages\n", msic);
+ sc->nfe_msi = 1;
+ } else
+ pci_release_msi(dev);
+ }
+ }
+
+ if (sc->nfe_msix == 0 && sc->nfe_msi == 0) {
+ rid = 0;
+ sc->nfe_irq[0] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_SHAREABLE | RF_ACTIVE);
+ if (sc->nfe_irq[0] == NULL) {
+ device_printf(dev, "couldn't allocate IRQ resources\n");
+ error = ENXIO;
+ goto fail;
+ }
+ } else {
+ for (i = 0, rid = 1; i < NFE_MSI_MESSAGES; i++, rid++) {
+ sc->nfe_irq[i] = bus_alloc_resource_any(dev,
+ SYS_RES_IRQ, &rid, RF_ACTIVE);
+ if (sc->nfe_irq[i] == NULL) {
+ device_printf(dev,
+ "couldn't allocate IRQ resources for "
+ "message %d\n", rid);
+ error = ENXIO;
+ goto fail;
+ }
+ }
+ /* Map interrupts to vector 0. */
+ if (sc->nfe_msix != 0) {
+ NFE_WRITE(sc, NFE_MSIX_MAP0, 0);
+ NFE_WRITE(sc, NFE_MSIX_MAP1, 0);
+ } else if (sc->nfe_msi != 0) {
+ NFE_WRITE(sc, NFE_MSI_MAP0, 0);
+ NFE_WRITE(sc, NFE_MSI_MAP1, 0);
+ }
+ }
+
+ /* Set IRQ status/mask register. */
+ sc->nfe_irq_status = NFE_IRQ_STATUS;
+ sc->nfe_irq_mask = NFE_IRQ_MASK;
+ sc->nfe_intrs = NFE_IRQ_WANTED;
+ sc->nfe_nointrs = 0;
+ if (sc->nfe_msix != 0) {
+ sc->nfe_irq_status = NFE_MSIX_IRQ_STATUS;
+ sc->nfe_nointrs = NFE_IRQ_WANTED;
+ } else if (sc->nfe_msi != 0) {
+ sc->nfe_irq_mask = NFE_MSI_IRQ_MASK;
+ sc->nfe_intrs = NFE_MSI_VECTOR_0_ENABLED;
+ }
+
+ sc->nfe_devid = pci_get_device(dev);
+ sc->nfe_revid = pci_get_revid(dev);
+ sc->nfe_flags = 0;
+
+ switch (sc->nfe_devid) {
+ case PCI_PRODUCT_NVIDIA_NFORCE3_LAN2:
+ case PCI_PRODUCT_NVIDIA_NFORCE3_LAN3:
+ case PCI_PRODUCT_NVIDIA_NFORCE3_LAN4:
+ case PCI_PRODUCT_NVIDIA_NFORCE3_LAN5:
+ sc->nfe_flags |= NFE_JUMBO_SUP | NFE_HW_CSUM;
+ break;
+ case PCI_PRODUCT_NVIDIA_MCP51_LAN1:
+ case PCI_PRODUCT_NVIDIA_MCP51_LAN2:
+ sc->nfe_flags |= NFE_40BIT_ADDR | NFE_PWR_MGMT;
+ break;
+ case PCI_PRODUCT_NVIDIA_CK804_LAN1:
+ case PCI_PRODUCT_NVIDIA_CK804_LAN2:
+ case PCI_PRODUCT_NVIDIA_MCP04_LAN1:
+ case PCI_PRODUCT_NVIDIA_MCP04_LAN2:
+ sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM;
+ break;
+ case PCI_PRODUCT_NVIDIA_MCP55_LAN1:
+ case PCI_PRODUCT_NVIDIA_MCP55_LAN2:
+ sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM |
+ NFE_HW_VLAN | NFE_PWR_MGMT | NFE_TX_FLOW_CTRL;
+ break;
+
+ case PCI_PRODUCT_NVIDIA_MCP61_LAN1:
+ case PCI_PRODUCT_NVIDIA_MCP61_LAN2:
+ case PCI_PRODUCT_NVIDIA_MCP61_LAN3:
+ case PCI_PRODUCT_NVIDIA_MCP61_LAN4:
+ case PCI_PRODUCT_NVIDIA_MCP67_LAN1:
+ case PCI_PRODUCT_NVIDIA_MCP67_LAN2:
+ case PCI_PRODUCT_NVIDIA_MCP67_LAN3:
+ case PCI_PRODUCT_NVIDIA_MCP67_LAN4:
+ case PCI_PRODUCT_NVIDIA_MCP73_LAN1:
+ case PCI_PRODUCT_NVIDIA_MCP73_LAN2:
+ case PCI_PRODUCT_NVIDIA_MCP73_LAN3:
+ case PCI_PRODUCT_NVIDIA_MCP73_LAN4:
+ sc->nfe_flags |= NFE_40BIT_ADDR | NFE_PWR_MGMT |
+ NFE_CORRECT_MACADDR | NFE_TX_FLOW_CTRL;
+ break;
+ case PCI_PRODUCT_NVIDIA_MCP77_LAN1:
+ case PCI_PRODUCT_NVIDIA_MCP77_LAN2:
+ case PCI_PRODUCT_NVIDIA_MCP77_LAN3:
+ case PCI_PRODUCT_NVIDIA_MCP77_LAN4:
+ /* XXX flow control */
+ sc->nfe_flags |= NFE_40BIT_ADDR | NFE_HW_CSUM | NFE_PWR_MGMT |
+ NFE_CORRECT_MACADDR;
+ break;
+ case PCI_PRODUCT_NVIDIA_MCP79_LAN1:
+ case PCI_PRODUCT_NVIDIA_MCP79_LAN2:
+ case PCI_PRODUCT_NVIDIA_MCP79_LAN3:
+ case PCI_PRODUCT_NVIDIA_MCP79_LAN4:
+ /* XXX flow control */
+ sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM |
+ NFE_PWR_MGMT | NFE_CORRECT_MACADDR;
+ break;
+ case PCI_PRODUCT_NVIDIA_MCP65_LAN1:
+ case PCI_PRODUCT_NVIDIA_MCP65_LAN2:
+ case PCI_PRODUCT_NVIDIA_MCP65_LAN3:
+ case PCI_PRODUCT_NVIDIA_MCP65_LAN4:
+ sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR |
+ NFE_PWR_MGMT | NFE_CORRECT_MACADDR | NFE_TX_FLOW_CTRL;
+ break;
+ }
+
+ nfe_power(sc);
+ /* Check for reversed ethernet address */
+ if ((NFE_READ(sc, NFE_TX_UNK) & NFE_MAC_ADDR_INORDER) != 0)
+ sc->nfe_flags |= NFE_CORRECT_MACADDR;
+ nfe_get_macaddr(sc, sc->eaddr);
+ /*
+ * Allocate the parent bus DMA tag appropriate for PCI.
+ */
+ dma_addr_max = BUS_SPACE_MAXADDR_32BIT;
+ if ((sc->nfe_flags & NFE_40BIT_ADDR) != 0)
+ dma_addr_max = NFE_DMA_MAXADDR;
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(sc->nfe_dev), /* parent */
+ 1, 0, /* alignment, boundary */
+ dma_addr_max, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ BUS_SPACE_MAXSIZE_32BIT, 0, /* maxsize, nsegments */
+ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->nfe_parent_tag);
+ if (error)
+ goto fail;
+
+ ifp = sc->nfe_ifp = if_alloc(IFT_ETHER);
+ if (ifp == NULL) {
+ device_printf(dev, "can not if_alloc()\n");
+ error = ENOSPC;
+ goto fail;
+ }
+ TASK_INIT(&sc->nfe_tx_task, 1, nfe_tx_task, ifp);
+
+ /*
+ * Allocate Tx and Rx rings.
+ */
+ if ((error = nfe_alloc_tx_ring(sc, &sc->txq)) != 0)
+ goto fail;
+
+ if ((error = nfe_alloc_rx_ring(sc, &sc->rxq)) != 0)
+ goto fail;
+
+ nfe_alloc_jrx_ring(sc, &sc->jrxq);
+
+ 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");
+
+ sc->nfe_process_limit = NFE_PROC_DEFAULT;
+ error = resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "process_limit", &sc->nfe_process_limit);
+ if (error == 0) {
+ if (sc->nfe_process_limit < NFE_PROC_MIN ||
+ sc->nfe_process_limit > NFE_PROC_MAX) {
+ device_printf(dev, "process_limit value out of range; "
+ "using default: %d\n", NFE_PROC_DEFAULT);
+ sc->nfe_process_limit = NFE_PROC_DEFAULT;
+ }
+ }
+
+ ifp->if_softc = sc;
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_mtu = ETHERMTU;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_ioctl = nfe_ioctl;
+ ifp->if_start = nfe_start;
+ ifp->if_hwassist = 0;
+ ifp->if_capabilities = 0;
+ ifp->if_watchdog = NULL;
+ ifp->if_init = nfe_init;
+ IFQ_SET_MAXLEN(&ifp->if_snd, NFE_TX_RING_COUNT - 1);
+ ifp->if_snd.ifq_drv_maxlen = NFE_TX_RING_COUNT - 1;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ if (sc->nfe_flags & NFE_HW_CSUM) {
+ ifp->if_capabilities |= IFCAP_HWCSUM;
+ ifp->if_hwassist |= NFE_CSUM_FEATURES;
+ }
+ ifp->if_capenable = ifp->if_capabilities;
+
+ sc->nfe_framesize = ifp->if_mtu + NFE_RX_HEADERS;
+ /* VLAN capability setup. */
+ ifp->if_capabilities |= IFCAP_VLAN_MTU;
+ if ((sc->nfe_flags & NFE_HW_VLAN) != 0) {
+ ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
+ }
+ ifp->if_capenable = ifp->if_capabilities;
+
+ /*
+ * Tell the upper layer(s) we support long frames.
+ * Must appear after the call to ether_ifattach() because
+ * ether_ifattach() sets ifi_hdrlen to the default value.
+ */
+ ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
+
+#ifdef DEVICE_POLLING
+ ifp->if_capabilities |= IFCAP_POLLING;
+#endif
+
+ /* Do MII setup */
+ if (mii_phy_probe(dev, &sc->nfe_miibus, nfe_ifmedia_upd,
+ nfe_ifmedia_sts)) {
+ device_printf(dev, "MII without any phy!\n");
+ error = ENXIO;
+ goto fail;
+ }
+ ether_ifattach(ifp, sc->eaddr);
+
+ TASK_INIT(&sc->nfe_int_task, 0, nfe_int_task, sc);
+ sc->nfe_tq = taskqueue_create_fast("nfe_taskq", M_WAITOK,
+ taskqueue_thread_enqueue, &sc->nfe_tq);
+ taskqueue_start_threads(&sc->nfe_tq, 1, PI_NET, "%s taskq",
+ device_get_nameunit(sc->nfe_dev));
+ error = 0;
+ if (sc->nfe_msi == 0 && sc->nfe_msix == 0) {
+ error = bus_setup_intr(dev, sc->nfe_irq[0],
+ INTR_TYPE_NET | INTR_FAST, nfe_intr, sc,
+ &sc->nfe_intrhand[0]);
+ } else {
+ for (i = 0; i < NFE_MSI_MESSAGES; i++) {
+ error = bus_setup_intr(dev, sc->nfe_irq[i],
+ INTR_TYPE_NET | INTR_FAST, nfe_intr, sc,
+ &sc->nfe_intrhand[i]);
+ if (error != 0)
+ break;
+ }
+ }
+ if (error) {
+ device_printf(dev, "couldn't set up irq\n");
+ taskqueue_free(sc->nfe_tq);
+ sc->nfe_tq = NULL;
+ ether_ifdetach(ifp);
+ goto fail;
+ }
+
+fail:
+ if (error)
+ nfe_detach(dev);
+
+ return (error);
+}
+
+
+static int
+nfe_detach(device_t dev)
+{
+ struct nfe_softc *sc;
+ struct ifnet *ifp;
+ uint8_t eaddr[ETHER_ADDR_LEN];
+ int i, rid;
+
+ sc = device_get_softc(dev);
+ KASSERT(mtx_initialized(&sc->nfe_mtx), ("nfe mutex not initialized"));
+ ifp = sc->nfe_ifp;
+
+#ifdef DEVICE_POLLING
+ if (ifp != NULL && ifp->if_capenable & IFCAP_POLLING)
+ ether_poll_deregister(ifp);
+#endif
+ if (device_is_attached(dev)) {
+ NFE_LOCK(sc);
+ nfe_stop(ifp);
+ ifp->if_flags &= ~IFF_UP;
+ NFE_UNLOCK(sc);
+ callout_drain(&sc->nfe_stat_ch);
+ taskqueue_drain(taskqueue_fast, &sc->nfe_tx_task);
+ taskqueue_drain(taskqueue_swi, &sc->nfe_link_task);
+ ether_ifdetach(ifp);
+ }
+
+ if (ifp) {
+ /* restore ethernet address */
+ if ((sc->nfe_flags & NFE_CORRECT_MACADDR) == 0) {
+ for (i = 0; i < ETHER_ADDR_LEN; i++) {
+ eaddr[i] = sc->eaddr[5 - i];
+ }
+ } else
+ bcopy(sc->eaddr, eaddr, ETHER_ADDR_LEN);
+ nfe_set_macaddr(sc, eaddr);
+ if_free(ifp);
+ }
+ if (sc->nfe_miibus)
+ device_delete_child(dev, sc->nfe_miibus);
+ bus_generic_detach(dev);
+ if (sc->nfe_tq != NULL) {
+ taskqueue_drain(sc->nfe_tq, &sc->nfe_int_task);
+ taskqueue_free(sc->nfe_tq);
+ sc->nfe_tq = NULL;
+ }
+
+ for (i = 0; i < NFE_MSI_MESSAGES; i++) {
+ if (sc->nfe_intrhand[i] != NULL) {
+ bus_teardown_intr(dev, sc->nfe_irq[i],
+ sc->nfe_intrhand[i]);
+ sc->nfe_intrhand[i] = NULL;
+ }
+ }
+
+ if (sc->nfe_msi == 0 && sc->nfe_msix == 0) {
+ if (sc->nfe_irq[0] != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0,
+ sc->nfe_irq[0]);
+ } else {
+ for (i = 0, rid = 1; i < NFE_MSI_MESSAGES; i++, rid++) {
+ if (sc->nfe_irq[i] != NULL) {
+ bus_release_resource(dev, SYS_RES_IRQ, rid,
+ sc->nfe_irq[i]);
+ sc->nfe_irq[i] = NULL;
+ }
+ }
+ pci_release_msi(dev);
+ }
+ if (sc->nfe_msix_pba_res != NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(3),
+ sc->nfe_msix_pba_res);
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable
mailing list