Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 18 Jun 2018 20:12:55 +0000 (UTC)
From:      Eric Joyner <erj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r335338 - in head/sys: amd64/conf conf dev/ixl modules modules/ixl modules/ixlv
Message-ID:  <201806182012.w5IKCtQ7053689@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: erj
Date: Mon Jun 18 20:12:54 2018
New Revision: 335338
URL: https://svnweb.freebsd.org/changeset/base/335338

Log:
  ixl(4): Update to use iflib
  
  Update the driver to use iflib in order to bring performance,
  maintainability, and (hopefully) stability benefits to the driver.
  
  The driver currently isn't completely ported; features that are missing:
  
  - VF driver (ixlv)
  - SR-IOV host support
  - RDMA support
  
  The plan is to have these re-added to the driver before the next FreeBSD release.
  
  Reviewed by:	gallatin@
  Contributions by: gallatin@, mmacy@, krzysztof.galazka@intel.com
  Tested by:	jeffrey.e.pieper@intel.com
  MFC after:	1 month
  Sponsored by:	Intel Corporation
  Differential Revision:	https://reviews.freebsd.org/D15577

Added:
  head/sys/dev/ixl/ixl_debug.h   (contents, props changed)
Modified:
  head/sys/amd64/conf/GENERIC
  head/sys/conf/files.amd64
  head/sys/dev/ixl/i40e_osdep.c
  head/sys/dev/ixl/if_ixl.c
  head/sys/dev/ixl/if_ixlv.c
  head/sys/dev/ixl/ixl.h
  head/sys/dev/ixl/ixl_pf.h
  head/sys/dev/ixl/ixl_pf_i2c.c
  head/sys/dev/ixl/ixl_pf_iov.c
  head/sys/dev/ixl/ixl_pf_main.c
  head/sys/dev/ixl/ixl_pf_qmgr.c
  head/sys/dev/ixl/ixl_txrx.c
  head/sys/dev/ixl/ixlv.h
  head/sys/dev/ixl/ixlvc.c
  head/sys/modules/Makefile
  head/sys/modules/ixl/Makefile
  head/sys/modules/ixlv/Makefile

Modified: head/sys/amd64/conf/GENERIC
==============================================================================
--- head/sys/amd64/conf/GENERIC	Mon Jun 18 19:53:11 2018	(r335337)
+++ head/sys/amd64/conf/GENERIC	Mon Jun 18 20:12:54 2018	(r335338)
@@ -240,8 +240,8 @@ device		em			# Intel PRO/1000 Gigabit Ethernet Family
 device		ix			# Intel PRO/10GbE PCIE PF Ethernet
 device		ixv			# Intel PRO/10GbE PCIE VF Ethernet
 device		ixl			# Intel XL710 40Gbe PCIE Ethernet
-options		IXL_IW			# Enable iWARP Client Interface in ixl(4)
-device		ixlv			# Intel XL710 40Gbe VF PCIE Ethernet
+#options		IXL_IW			# Enable iWARP Client Interface in ixl(4)
+#device		ixlv			# Intel XL710 40Gbe VF PCIE Ethernet
 device		le			# AMD Am7900 LANCE and Am79C9xx PCnet
 device		ti			# Alteon Networks Tigon I/II gigabit Ethernet
 device		txp			# 3Com 3cR990 (``Typhoon'')

Modified: head/sys/conf/files.amd64
==============================================================================
--- head/sys/conf/files.amd64	Mon Jun 18 19:53:11 2018	(r335337)
+++ head/sys/conf/files.amd64	Mon Jun 18 20:12:54 2018	(r335338)
@@ -270,10 +270,10 @@ dev/ixl/ixl_pf_iov.c		optional	ixl pci  pci_iov \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/ixl_pf_i2c.c		optional	ixl pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
-dev/ixl/ixl_iw.c		optional	ixl pci \
-	compile-with "${NORMAL_C} -I$S/dev/ixl"
-dev/ixl/if_ixlv.c		optional	ixlv pci \
-	compile-with "${NORMAL_C} -I$S/dev/ixl"
+#dev/ixl/ixl_iw.c		optional	ixl pci \
+#	compile-with "${NORMAL_C} -I$S/dev/ixl"
+#dev/ixl/if_ixlv.c		optional	ixlv pci \
+#	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/ixlvc.c			optional	ixlv pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/ixl_txrx.c		optional	ixl pci | ixlv pci \

Modified: head/sys/dev/ixl/i40e_osdep.c
==============================================================================
--- head/sys/dev/ixl/i40e_osdep.c	Mon Jun 18 19:53:11 2018	(r335337)
+++ head/sys/dev/ixl/i40e_osdep.c	Mon Jun 18 20:12:54 2018	(r335338)
@@ -132,7 +132,7 @@ i40e_free_dma_mem(struct i40e_hw *hw, struct i40e_dma_
 	bus_dmamap_unload(mem->tag, mem->map);
 	bus_dmamem_free(mem->tag, mem->va, mem->map);
 	bus_dma_tag_destroy(mem->tag);
-	return (0);
+	return (I40E_SUCCESS);
 }
 
 void

Modified: head/sys/dev/ixl/if_ixl.c
==============================================================================
--- head/sys/dev/ixl/if_ixl.c	Mon Jun 18 19:53:11 2018	(r335337)
+++ head/sys/dev/ixl/if_ixl.c	Mon Jun 18 20:12:54 2018	(r335338)
@@ -51,60 +51,79 @@
 #define IXL_DRIVER_VERSION_MINOR	9
 #define IXL_DRIVER_VERSION_BUILD	9
 
-char ixl_driver_version[] = __XSTRING(IXL_DRIVER_VERSION_MAJOR) "."
-			    __XSTRING(IXL_DRIVER_VERSION_MINOR) "."
-			    __XSTRING(IXL_DRIVER_VERSION_BUILD) "-k";
+#define IXL_DRIVER_VERSION_STRING			\
+    __XSTRING(IXL_DRIVER_VERSION_MAJOR) "."		\
+    __XSTRING(IXL_DRIVER_VERSION_MINOR) "."		\
+    __XSTRING(IXL_DRIVER_VERSION_BUILD) "-iflib-k"
 
 /*********************************************************************
  *  PCI Device ID Table
  *
  *  Used by probe to select devices to load on
- *  Last field stores an index into ixl_strings
- *  Last entry must be all 0s
  *
- *  { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
+ *  ( Vendor ID, Device ID, Branding String )
  *********************************************************************/
 
-static ixl_vendor_info_t ixl_vendor_info_array[] =
+static pci_vendor_info_t ixl_vendor_info_array[] =
 {
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710, 0, 0, 0},
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_B, 0, 0, 0},
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_C, 0, 0, 0},
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_A, 0, 0, 0},
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_B, 0, 0, 0},
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_C, 0, 0, 0},
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T, 0, 0, 0},
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T4, 0, 0, 0},
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_X722, 0, 0, 0},
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_X722, 0, 0, 0},
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_X722, 0, 0, 0},
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_1G_BASE_T_X722, 0, 0, 0},
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T_X722, 0, 0, 0},
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_I_X722, 0, 0, 0},
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_B, 0, 0, 0},
-	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_SFP28, 0, 0, 0},
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710, "Intel(R) Ethernet Controller X710 for 10GbE SFP+"),
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_B, "Intel(R) Ethernet Controller XL710 for 40GbE backplane"),
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_C, "Intel(R) Ethernet Controller X710 for 10GbE backplane"),
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_A, "Intel(R) Ethernet Controller XL710 for 40GbE QSFP+"),
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_B, "Intel(R) Ethernet Controller XL710 for 40GbE QSFP+"),
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_C, "Intel(R) Ethernet Controller X710 for 10GbE QSFP+"),
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T, "Intel(R) Ethernet Controller X710 for 10GBASE-T"),
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T4, "Intel(R) Ethernet Controller X710/X557-AT 10GBASE-T"),
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_X722, "Intel(R) Ethernet Connection X722 for 10GbE backplane"),
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_X722, "Intel(R) Ethernet Connection X722 for 10GbE QSFP+"),
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_X722, "Intel(R) Ethernet Connection X722 for 10GbE SFP+"),
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_1G_BASE_T_X722, "Intel(R) Ethernet Connection X722 for 1GbE"),
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T_X722, "Intel(R) Ethernet Connection X722 for 10GBASE-T"),
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_I_X722, "Intel(R) Ethernet Connection X722 for 10GbE SFP+"),
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_B, "Intel(R) Ethernet Controller XXV710 for 25GbE backplane"),
+	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_SFP28, "Intel(R) Ethernet Controller XXV710 for 25GbE SFP28"),
 	/* required last entry */
-	{0, 0, 0, 0, 0}
+	PVID_END
 };
 
 /*********************************************************************
- *  Table of branding strings
- *********************************************************************/
-
-static char    *ixl_strings[] = {
-	"Intel(R) Ethernet Connection 700 Series PF Driver"
-};
-
-
-/*********************************************************************
  *  Function prototypes
  *********************************************************************/
-static int      ixl_probe(device_t);
-static int      ixl_attach(device_t);
-static int      ixl_detach(device_t);
-static int      ixl_shutdown(device_t);
+/*** IFLIB interface ***/
+static void	*ixl_register(device_t dev);
+static int	 ixl_if_attach_pre(if_ctx_t ctx);
+static int	 ixl_if_attach_post(if_ctx_t ctx);
+static int	 ixl_if_detach(if_ctx_t ctx);
+static int	 ixl_if_shutdown(if_ctx_t ctx);
+static int	 ixl_if_suspend(if_ctx_t ctx);
+static int	 ixl_if_resume(if_ctx_t ctx);
+static int	 ixl_if_msix_intr_assign(if_ctx_t ctx, int msix);
+static void	 ixl_if_enable_intr(if_ctx_t ctx);
+static void	 ixl_if_disable_intr(if_ctx_t ctx);
+static int	 ixl_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid);
+static int	 ixl_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid);
+static int	 ixl_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int ntxqs, int ntxqsets);
+static int	 ixl_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nqs, int nqsets);
+static void	 ixl_if_queues_free(if_ctx_t ctx);
+static void	 ixl_if_update_admin_status(if_ctx_t ctx);
+static void	 ixl_if_multi_set(if_ctx_t ctx);
+static int	 ixl_if_mtu_set(if_ctx_t ctx, uint32_t mtu);
+static void	 ixl_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr);
+static int	 ixl_if_media_change(if_ctx_t ctx);
+static int	 ixl_if_promisc_set(if_ctx_t ctx, int flags);
+static void	 ixl_if_timer(if_ctx_t ctx, uint16_t qid);
+static void	 ixl_if_vlan_register(if_ctx_t ctx, u16 vtag);
+static void	 ixl_if_vlan_unregister(if_ctx_t ctx, u16 vtag);
+static uint64_t	 ixl_if_get_counter(if_ctx_t ctx, ift_counter cnt);
+static void	 ixl_if_vflr_handle(if_ctx_t ctx);
+// static void	 ixl_if_link_intr_enable(if_ctx_t ctx);
+static int	 ixl_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req);
+static int	 ixl_if_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data);
 
-static int	ixl_save_pf_tunables(struct ixl_pf *);
+/*** Other ***/
+static int	 ixl_mc_filter_apply(void *arg, struct ifmultiaddr *ifma, int);
+static void	 ixl_save_pf_tunables(struct ixl_pf *);
+static int	 ixl_allocate_pci_resources(struct ixl_pf *);
 
 /*********************************************************************
  *  FreeBSD Device Interface Entry Points
@@ -112,16 +131,17 @@ static int	ixl_save_pf_tunables(struct ixl_pf *);
 
 static device_method_t ixl_methods[] = {
 	/* Device interface */
-	DEVMETHOD(device_probe, ixl_probe),
-	DEVMETHOD(device_attach, ixl_attach),
-	DEVMETHOD(device_detach, ixl_detach),
-	DEVMETHOD(device_shutdown, ixl_shutdown),
+	DEVMETHOD(device_register, ixl_register),
+	DEVMETHOD(device_probe, iflib_device_probe),
+	DEVMETHOD(device_attach, iflib_device_attach),
+	DEVMETHOD(device_detach, iflib_device_detach),
+	DEVMETHOD(device_shutdown, iflib_device_shutdown),
 #ifdef PCI_IOV
 	DEVMETHOD(pci_iov_init, ixl_iov_init),
 	DEVMETHOD(pci_iov_uninit, ixl_iov_uninit),
 	DEVMETHOD(pci_iov_add_vf, ixl_add_vf),
 #endif
-	{0, 0}
+	DEVMETHOD_END
 };
 
 static driver_t ixl_driver = {
@@ -130,15 +150,52 @@ static driver_t ixl_driver = {
 
 devclass_t ixl_devclass;
 DRIVER_MODULE(ixl, pci, ixl_driver, ixl_devclass, 0, 0);
+MODULE_VERSION(ixl, 3);
 
-MODULE_VERSION(ixl, 1);
-
 MODULE_DEPEND(ixl, pci, 1, 1, 1);
 MODULE_DEPEND(ixl, ether, 1, 1, 1);
-#if defined(DEV_NETMAP) && __FreeBSD_version >= 1100000
-MODULE_DEPEND(ixl, netmap, 1, 1, 1);
-#endif /* DEV_NETMAP */
+MODULE_DEPEND(ixl, iflib, 1, 1, 1);
 
+static device_method_t ixl_if_methods[] = {
+	DEVMETHOD(ifdi_attach_pre, ixl_if_attach_pre),
+	DEVMETHOD(ifdi_attach_post, ixl_if_attach_post),
+	DEVMETHOD(ifdi_detach, ixl_if_detach),
+	DEVMETHOD(ifdi_shutdown, ixl_if_shutdown),
+	DEVMETHOD(ifdi_suspend, ixl_if_suspend),
+	DEVMETHOD(ifdi_resume, ixl_if_resume),
+	DEVMETHOD(ifdi_init, ixl_if_init),
+	DEVMETHOD(ifdi_stop, ixl_if_stop),
+	DEVMETHOD(ifdi_msix_intr_assign, ixl_if_msix_intr_assign),
+	DEVMETHOD(ifdi_intr_enable, ixl_if_enable_intr),
+	DEVMETHOD(ifdi_intr_disable, ixl_if_disable_intr),
+	//DEVMETHOD(ifdi_link_intr_enable, ixl_if_link_intr_enable),
+	DEVMETHOD(ifdi_rx_queue_intr_enable, ixl_if_rx_queue_intr_enable),
+	DEVMETHOD(ifdi_tx_queue_intr_enable, ixl_if_tx_queue_intr_enable),
+	DEVMETHOD(ifdi_tx_queues_alloc, ixl_if_tx_queues_alloc),
+	DEVMETHOD(ifdi_rx_queues_alloc, ixl_if_rx_queues_alloc),
+	DEVMETHOD(ifdi_queues_free, ixl_if_queues_free),
+	DEVMETHOD(ifdi_update_admin_status, ixl_if_update_admin_status),
+	DEVMETHOD(ifdi_multi_set, ixl_if_multi_set),
+	DEVMETHOD(ifdi_mtu_set, ixl_if_mtu_set),
+	DEVMETHOD(ifdi_media_status, ixl_if_media_status),
+	DEVMETHOD(ifdi_media_change, ixl_if_media_change),
+	DEVMETHOD(ifdi_promisc_set, ixl_if_promisc_set),
+	DEVMETHOD(ifdi_timer, ixl_if_timer),
+	DEVMETHOD(ifdi_vlan_register, ixl_if_vlan_register),
+	DEVMETHOD(ifdi_vlan_unregister, ixl_if_vlan_unregister),
+	DEVMETHOD(ifdi_get_counter, ixl_if_get_counter),
+	DEVMETHOD(ifdi_vflr_handle, ixl_if_vflr_handle),
+	DEVMETHOD(ifdi_i2c_req, ixl_if_i2c_req),
+	DEVMETHOD(ifdi_priv_ioctl, ixl_if_priv_ioctl),
+	// ifdi_led_func
+	// ifdi_debug
+	DEVMETHOD_END
+};
+
+static driver_t ixl_if_driver = {
+	"ixl_if", ixl_if_methods, sizeof(struct ixl_pf)
+};
+
 /*
 ** TUNEABLE PARAMETERS:
 */
@@ -147,39 +204,6 @@ static SYSCTL_NODE(_hw, OID_AUTO, ixl, CTLFLAG_RD, 0,
                    "IXL driver parameters");
 
 /*
- * MSIX should be the default for best performance,
- * but this allows it to be forced off for testing.
- */
-static int ixl_enable_msix = 1;
-TUNABLE_INT("hw.ixl.enable_msix", &ixl_enable_msix);
-SYSCTL_INT(_hw_ixl, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixl_enable_msix, 0,
-    "Enable MSI-X interrupts");
-
-/*
-** Number of descriptors per ring
-** - TX and RX sizes are independently configurable
-*/
-static int ixl_tx_ring_size = IXL_DEFAULT_RING;
-TUNABLE_INT("hw.ixl.tx_ring_size", &ixl_tx_ring_size);
-SYSCTL_INT(_hw_ixl, OID_AUTO, tx_ring_size, CTLFLAG_RDTUN,
-    &ixl_tx_ring_size, 0, "TX Descriptor Ring Size");
-
-static int ixl_rx_ring_size = IXL_DEFAULT_RING;
-TUNABLE_INT("hw.ixl.rx_ring_size", &ixl_rx_ring_size);
-SYSCTL_INT(_hw_ixl, OID_AUTO, rx_ring_size, CTLFLAG_RDTUN,
-    &ixl_rx_ring_size, 0, "RX Descriptor Ring Size");
-
-/* 
-** This can be set manually, if left as 0 the
-** number of queues will be calculated based
-** on cpus and msix vectors available.
-*/
-static int ixl_max_queues = 0;
-TUNABLE_INT("hw.ixl.max_queues", &ixl_max_queues);
-SYSCTL_INT(_hw_ixl, OID_AUTO, max_queues, CTLFLAG_RDTUN,
-    &ixl_max_queues, 0, "Number of Queues");
-
-/*
  * Leave this on unless you need to send flow control
  * frames (or other control frames) from software
  */
@@ -190,6 +214,13 @@ SYSCTL_INT(_hw_ixl, OID_AUTO, enable_tx_fc_filter, CTL
     &ixl_enable_tx_fc_filter, 0,
     "Filter out packets with Ethertype 0x8808 from being sent out by non-HW sources");
 
+static int ixl_i2c_access_method = 0;
+TUNABLE_INT("hw.ixl.i2c_access_method",
+    &ixl_i2c_access_method);
+SYSCTL_INT(_hw_ixl, OID_AUTO, i2c_access_method, CTLFLAG_RDTUN,
+    &ixl_i2c_access_method, 0,
+    IXL_SYSCTL_HELP_I2C_METHOD);
+
 /*
  * Different method for processing TX descriptor
  * completion.
@@ -215,20 +246,22 @@ SYSCTL_INT(_hw_ixl, OID_AUTO, shared_debug_mask, CTLFL
     &ixl_shared_debug_mask, 0,
     "Display debug statements that are printed in shared code");
 
+#if 0
 /*
 ** Controls for Interrupt Throttling 
 **	- true/false for dynamic adjustment
 ** 	- default values for static ITR
 */
-static int ixl_dynamic_rx_itr = 1;
+static int ixl_dynamic_rx_itr = 0;
 TUNABLE_INT("hw.ixl.dynamic_rx_itr", &ixl_dynamic_rx_itr);
 SYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_rx_itr, CTLFLAG_RDTUN,
     &ixl_dynamic_rx_itr, 0, "Dynamic RX Interrupt Rate");
 
-static int ixl_dynamic_tx_itr = 1;
+static int ixl_dynamic_tx_itr = 0;
 TUNABLE_INT("hw.ixl.dynamic_tx_itr", &ixl_dynamic_tx_itr);
 SYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_tx_itr, CTLFLAG_RDTUN,
     &ixl_dynamic_tx_itr, 0, "Dynamic TX Interrupt Rate");
+#endif
 
 static int ixl_rx_itr = IXL_ITR_8K;
 TUNABLE_INT("hw.ixl.rx_itr", &ixl_rx_itr);
@@ -256,165 +289,131 @@ SYSCTL_INT(_hw_ixl, OID_AUTO, limit_iwarp_msix, CTLFLA
     &ixl_limit_iwarp_msix, 0, "Limit MSIX vectors assigned to iWARP");
 #endif
 
-#ifdef DEV_NETMAP
-#define NETMAP_IXL_MAIN /* only bring in one part of the netmap code */
-#include <dev/netmap/if_ixl_netmap.h>
-#endif /* DEV_NETMAP */
+extern struct if_txrx ixl_txrx_hwb;
+extern struct if_txrx ixl_txrx_dwb;
 
-/*********************************************************************
- *  Device identification routine
- *
- *  ixl_probe determines if the driver should be loaded on
- *  the hardware based on PCI vendor/device id of the device.
- *
- *  return BUS_PROBE_DEFAULT on success, positive on failure
- *********************************************************************/
+static struct if_shared_ctx ixl_sctx_init = {
+	.isc_magic = IFLIB_MAGIC,
+	.isc_q_align = PAGE_SIZE,
+	.isc_tx_maxsize = IXL_TSO_SIZE,
+	.isc_tx_maxsegsize = IXL_MAX_DMA_SEG_SIZE,
 
-static int
-ixl_probe(device_t dev)
-{
-	ixl_vendor_info_t *ent;
+	.isc_rx_maxsize = 16384,
+	.isc_rx_nsegments = IXL_MAX_RX_SEGS,
+	.isc_rx_maxsegsize = IXL_MAX_DMA_SEG_SIZE,
+	.isc_nfl = 1,
+	.isc_ntxqs = 1,
+	.isc_nrxqs = 1,
 
-	u16	pci_vendor_id, pci_device_id;
-	u16	pci_subvendor_id, pci_subdevice_id;
-	char	device_name[256];
+	.isc_admin_intrcnt = 1,
+	.isc_vendor_info = ixl_vendor_info_array,
+	.isc_driver_version = IXL_DRIVER_VERSION_STRING,
+	.isc_driver = &ixl_if_driver,
+	.isc_flags = IFLIB_NEED_SCRATCH | IFLIB_NEED_ZERO_CSUM | IFLIB_ADMIN_ALWAYS_RUN,
 
-#if 0
-	INIT_DEBUGOUT("ixl_probe: begin");
-#endif
-	pci_vendor_id = pci_get_vendor(dev);
-	if (pci_vendor_id != I40E_INTEL_VENDOR_ID)
-		return (ENXIO);
+	.isc_nrxd_min = {IXL_MIN_RING},
+	.isc_ntxd_min = {IXL_MIN_RING},
+	.isc_nrxd_max = {IXL_MAX_RING},
+	.isc_ntxd_max = {IXL_MAX_RING},
+	.isc_nrxd_default = {IXL_DEFAULT_RING},
+	.isc_ntxd_default = {IXL_DEFAULT_RING},
+};
 
-	pci_device_id = pci_get_device(dev);
-	pci_subvendor_id = pci_get_subvendor(dev);
-	pci_subdevice_id = pci_get_subdevice(dev);
+if_shared_ctx_t ixl_sctx = &ixl_sctx_init;
 
-	ent = ixl_vendor_info_array;
-	while (ent->vendor_id != 0) {
-		if ((pci_vendor_id == ent->vendor_id) &&
-		    (pci_device_id == ent->device_id) &&
-
-		    ((pci_subvendor_id == ent->subvendor_id) ||
-		     (ent->subvendor_id == 0)) &&
-
-		    ((pci_subdevice_id == ent->subdevice_id) ||
-		     (ent->subdevice_id == 0))) {
-			sprintf(device_name, "%s, Version - %s",
-				ixl_strings[ent->index],
-				ixl_driver_version);
-			device_set_desc_copy(dev, device_name);
-			return (BUS_PROBE_DEFAULT);
-		}
-		ent++;
-	}
-	return (ENXIO);
+/*** Functions ***/
+static void *
+ixl_register(device_t dev)
+{
+	return (ixl_sctx);
 }
 
-/*
- * Sanity check and save off tunable values.
- */
 static int
-ixl_save_pf_tunables(struct ixl_pf *pf)
+ixl_allocate_pci_resources(struct ixl_pf *pf)
 {
-	device_t dev = pf->dev;
+	int             rid;
+	struct i40e_hw *hw = &pf->hw;
+	device_t dev = iflib_get_dev(pf->vsi.ctx);
 
-	/* Save tunable information */
-	pf->enable_msix = ixl_enable_msix;
-	pf->max_queues = ixl_max_queues;
-	pf->enable_tx_fc_filter = ixl_enable_tx_fc_filter;
-	pf->dynamic_rx_itr = ixl_dynamic_rx_itr;
-	pf->dynamic_tx_itr = ixl_dynamic_tx_itr;
-	pf->dbg_mask = ixl_core_debug_mask;
-	pf->hw.debug_mask = ixl_shared_debug_mask;
-#ifdef DEV_NETMAP
-	if (ixl_enable_head_writeback == 0)
-		device_printf(dev, "Head writeback mode cannot be disabled "
-		    "when netmap is enabled\n");
-	pf->vsi.enable_head_writeback = 1;
-#else
-	pf->vsi.enable_head_writeback = !!(ixl_enable_head_writeback);
-#endif
+	/* Map BAR0 */
+	rid = PCIR_BAR(0);
+	pf->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &rid, RF_ACTIVE);
+ 
+	if (!(pf->pci_mem)) {
+		device_printf(dev, "Unable to allocate bus resource: PCI memory\n");
+		return (ENXIO);
+	}
 
-	ixl_vsi_setup_rings_size(&pf->vsi, ixl_tx_ring_size, ixl_rx_ring_size);
+	/* Save off the PCI information */
+	hw->vendor_id = pci_get_vendor(dev);
+	hw->device_id = pci_get_device(dev);
+	hw->revision_id = pci_read_config(dev, PCIR_REVID, 1);
+	hw->subsystem_vendor_id =
+	    pci_read_config(dev, PCIR_SUBVEND_0, 2);
+	hw->subsystem_device_id =
+	    pci_read_config(dev, PCIR_SUBDEV_0, 2);
 
-	if (ixl_tx_itr < 0 || ixl_tx_itr > IXL_MAX_ITR) {
-		device_printf(dev, "Invalid tx_itr value of %d set!\n",
-		    ixl_tx_itr);
-		device_printf(dev, "tx_itr must be between %d and %d, "
-		    "inclusive\n",
-		    0, IXL_MAX_ITR);
-		device_printf(dev, "Using default value of %d instead\n",
-		    IXL_ITR_4K);
-		pf->tx_itr = IXL_ITR_4K;
-	} else
-		pf->tx_itr = ixl_tx_itr;
+	hw->bus.device = pci_get_slot(dev);
+	hw->bus.func = pci_get_function(dev);
 
-	if (ixl_rx_itr < 0 || ixl_rx_itr > IXL_MAX_ITR) {
-		device_printf(dev, "Invalid rx_itr value of %d set!\n",
-		    ixl_rx_itr);
-		device_printf(dev, "rx_itr must be between %d and %d, "
-		    "inclusive\n",
-		    0, IXL_MAX_ITR);
-		device_printf(dev, "Using default value of %d instead\n",
-		    IXL_ITR_8K);
-		pf->rx_itr = IXL_ITR_8K;
-	} else
-		pf->rx_itr = ixl_rx_itr;
+	/* Save off register access information */
+	pf->osdep.mem_bus_space_tag =
+		rman_get_bustag(pf->pci_mem);
+	pf->osdep.mem_bus_space_handle =
+		rman_get_bushandle(pf->pci_mem);
+	pf->osdep.mem_bus_space_size = rman_get_size(pf->pci_mem);
+	pf->osdep.flush_reg = I40E_GLGEN_STAT;
+	pf->osdep.dev = dev;
 
-	return (0);
-}
+	pf->hw.hw_addr = (u8 *) &pf->osdep.mem_bus_space_handle;
+	pf->hw.back = &pf->osdep;
+ 
+ 	return (0);
+ }
 
-/*********************************************************************
- *  Device initialization routine
- *
- *  The attach entry point is called when the driver is being loaded.
- *  This routine identifies the type of hardware, allocates all resources
- *  and initializes the hardware.
- *
- *  return 0 on success, positive on failure
- *********************************************************************/
-
 static int
-ixl_attach(device_t dev)
+ixl_if_attach_pre(if_ctx_t ctx)
 {
-	struct ixl_pf	*pf;
-	struct i40e_hw	*hw;
-	struct ixl_vsi  *vsi;
+	device_t dev;
+	struct ixl_pf *pf;
+	struct i40e_hw *hw;
+	struct ixl_vsi *vsi;
+	if_softc_ctx_t scctx;
+	struct i40e_filter_control_settings filter;
 	enum i40e_status_code status;
-	int             error = 0;
+	int error = 0;
 
-	INIT_DEBUGOUT("ixl_attach: begin");
+	INIT_DEBUGOUT("ixl_if_attach_pre: begin");
 
 	/* Allocate, clear, and link in our primary soft structure */
-	pf = device_get_softc(dev);
-	pf->dev = pf->osdep.dev = dev;
+	dev = iflib_get_dev(ctx);
+	pf = iflib_get_softc(ctx);
+	vsi = &pf->vsi;
+	vsi->back = pf;
+	pf->dev = dev;
 	hw = &pf->hw;
 
 	/*
 	** Note this assumes we have a single embedded VSI,
 	** this could be enhanced later to allocate multiple
 	*/
-	vsi = &pf->vsi;
-	vsi->dev = pf->dev;
-	vsi->back = pf;
+	//vsi->dev = pf->dev;
+	vsi->hw = &pf->hw;
+	vsi->id = 0;
+	vsi->num_vlans = 0;
+	vsi->ctx = ctx;
+	vsi->media = iflib_get_media(ctx);
+	vsi->shared = scctx = iflib_get_softc_ctx(ctx);
 
 	/* Save tunable values */
-	error = ixl_save_pf_tunables(pf);
-	if (error)
-		return (error);
+	ixl_save_pf_tunables(pf);
 
-	/* Core Lock Init*/
-	IXL_PF_LOCK_INIT(pf, device_get_nameunit(dev));
-
-	/* Set up the timer callout */
-	callout_init_mtx(&pf->timer, &pf->pf_mtx, 0);
-
 	/* Do PCI setup - map BAR0, etc */
 	if (ixl_allocate_pci_resources(pf)) {
 		device_printf(dev, "Allocation of PCI resources failed\n");
 		error = ENXIO;
-		goto err_out;
+		goto err_pci_res;
 	}
 
 	/* Establish a clean starting point */
@@ -478,16 +477,11 @@ ixl_attach(device_t dev)
 	/* Get capabilities from the device */
 	error = ixl_get_hw_capabilities(pf);
 	if (error) {
-		device_printf(dev, "HW capabilities failure!\n");
+		device_printf(dev, "get_hw_capabilities failed: %d\n",
+		    error);
 		goto err_get_cap;
 	}
 
-	/*
-	 * Allocate interrupts and figure out number of queues to use
-	 * for PF interface
-	 */
-	pf->msix = ixl_init_msix(pf);
-
 	/* Set up host memory cache */
 	status = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp,
 	    hw->func_caps.num_rx_qp, 0, 0);
@@ -496,7 +490,6 @@ ixl_attach(device_t dev)
 		    i40e_stat_str(hw, status));
 		goto err_get_cap;
 	}
-
 	status = i40e_configure_lan_hmc(hw, I40E_HMC_MODEL_DIRECT_ONLY);
 	if (status) {
 		device_printf(dev, "configure_lan_hmc failed: %s\n",
@@ -504,23 +497,6 @@ ixl_attach(device_t dev)
 		goto err_mac_hmc;
 	}
 
-	/* Init queue allocation manager */
-	error = ixl_pf_qmgr_init(&pf->qmgr, hw->func_caps.num_tx_qp);
-	if (error) {
-		device_printf(dev, "Failed to init queue manager for PF queues, error %d\n",
-		    error);
-		goto err_mac_hmc;
-	}
-	/* reserve a contiguous allocation for the PF's VSI */
-	error = ixl_pf_qmgr_alloc_contiguous(&pf->qmgr, vsi->num_queues, &pf->qtag);
-	if (error) {
-		device_printf(dev, "Failed to reserve queues for PF LAN VSI, error %d\n",
-		    error);
-		goto err_mac_hmc;
-	}
-	device_printf(dev, "Allocating %d queues for PF LAN VSI; %d queues active\n",
-	    pf->qtag.num_allocated, pf->qtag.num_active);
-
 	/* Disable LLDP from the firmware for certain NVM versions */
 	if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 3)) ||
 	    (pf->hw.aq.fw_maj_ver < 4)) {
@@ -536,46 +512,120 @@ ixl_attach(device_t dev)
 		goto err_mac_hmc;
 	}
 	bcopy(hw->mac.addr, hw->mac.perm_addr, ETHER_ADDR_LEN);
+	iflib_set_mac(ctx, hw->mac.addr);
 	i40e_get_port_mac_addr(hw, hw->mac.port_addr);
 
+	/* Set up the device filtering */
+	bzero(&filter, sizeof(filter));
+	filter.enable_ethtype = TRUE;
+	filter.enable_macvlan = TRUE;
+	filter.enable_fdir = FALSE;
+	filter.hash_lut_size = I40E_HASH_LUT_SIZE_512;
+	if (i40e_set_filter_control(hw, &filter))
+		device_printf(dev, "i40e_set_filter_control() failed\n");
+
 	/* Query device FW LLDP status */
 	ixl_get_fw_lldp_status(pf);
 	/* Tell FW to apply DCB config on link up */
-	if ((hw->mac.type != I40E_MAC_X722)
-	    && ((pf->hw.aq.api_maj_ver > 1)
-	    || (pf->hw.aq.api_maj_ver == 1 && pf->hw.aq.api_min_ver >= 7)))
-		i40e_aq_set_dcb_parameters(hw, true, NULL);
+	i40e_aq_set_dcb_parameters(hw, true, NULL);
 
-	/* Initialize mac filter list for VSI */
-	SLIST_INIT(&vsi->ftl);
-
-	/* Set up SW VSI and allocate queue memory and rings */
-	if (ixl_setup_stations(pf)) { 
-		device_printf(dev, "setup stations failed!\n");
-		error = ENOMEM;
-		goto err_mac_hmc;
+	/* Fill out iflib parameters */
+	if (hw->mac.type == I40E_MAC_X722)
+		scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 128;
+	else
+		scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 64;
+	if (vsi->enable_head_writeback) {
+		scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0]
+		    * sizeof(struct i40e_tx_desc) + sizeof(u32), DBA_ALIGN);
+		scctx->isc_txrx = &ixl_txrx_hwb;
+	} else {
+		scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0]
+		    * sizeof(struct i40e_tx_desc), DBA_ALIGN);
+		scctx->isc_txrx = &ixl_txrx_dwb;
 	}
+	scctx->isc_rxqsizes[0] = roundup2(scctx->isc_nrxd[0]
+	    * sizeof(union i40e_32byte_rx_desc), DBA_ALIGN);
+	scctx->isc_msix_bar = PCIR_BAR(IXL_MSIX_BAR);
+	scctx->isc_tx_nsegments = IXL_MAX_TX_SEGS;
+	scctx->isc_tx_tso_segments_max = IXL_MAX_TSO_SEGS;
+	scctx->isc_tx_tso_size_max = IXL_TSO_SIZE;
+	scctx->isc_tx_tso_segsize_max = IXL_MAX_DMA_SEG_SIZE;
+	scctx->isc_rss_table_size = pf->hw.func_caps.rss_table_size;
+	scctx->isc_tx_csum_flags = CSUM_OFFLOAD;
+	scctx->isc_capenable = IXL_CAPS;
 
+	INIT_DEBUGOUT("ixl_if_attach_pre: end");
+	return (0);
+
+err_mac_hmc:
+	i40e_shutdown_lan_hmc(hw);
+err_get_cap:
+	i40e_shutdown_adminq(hw);
+err_out:
+	ixl_free_pci_resources(pf);
+err_pci_res:
+	return (error);
+}
+
+static int
+ixl_if_attach_post(if_ctx_t ctx)
+{
+	device_t dev;
+	struct ixl_pf *pf;
+	struct i40e_hw *hw;
+	struct ixl_vsi *vsi;
+	int error = 0;
+	enum i40e_status_code status;
+
+	INIT_DEBUGOUT("ixl_if_attach_post: begin");
+
+	dev = iflib_get_dev(ctx);
+	pf = iflib_get_softc(ctx);
+	vsi = &pf->vsi;
+	vsi->ifp = iflib_get_ifp(ctx);
+	hw = &pf->hw;
+
 	/* Setup OS network interface / ifnet */
-	if (ixl_setup_interface(dev, vsi)) {
+	if (ixl_setup_interface(dev, pf)) {
 		device_printf(dev, "interface setup failed!\n");
 		error = EIO;
-		goto err_late;
+		goto err;
 	}
 
 	/* Determine link state */
 	if (ixl_attach_get_link_status(pf)) {
 		error = EINVAL;
-		goto err_late;
+		goto err;
 	}
 
 	error = ixl_switch_config(pf);
 	if (error) {
 		device_printf(dev, "Initial ixl_switch_config() failed: %d\n",
 		     error);
-		goto err_late;
+		goto err;
 	}
 
+	/* Add protocol filters to list */
+	ixl_init_filters(vsi);
+
+	/* Init queue allocation manager */
+	error = ixl_pf_qmgr_init(&pf->qmgr, hw->func_caps.num_tx_qp);
+	if (error) {
+		device_printf(dev, "Failed to init queue manager for PF queues, error %d\n",
+		    error);
+		goto err;
+	}
+	/* reserve a contiguous allocation for the PF's VSI */
+	error = ixl_pf_qmgr_alloc_contiguous(&pf->qmgr,
+	    max(vsi->num_rx_queues, vsi->num_tx_queues), &pf->qtag);
+	if (error) {
+		device_printf(dev, "Failed to reserve queues for PF LAN VSI, error %d\n",
+		    error);
+		goto err;
+	}
+	device_printf(dev, "Allocating %d queues for PF LAN VSI; %d queues active\n",
+	    pf->qtag.num_allocated, pf->qtag.num_active);
+
 	/* Limit PHY interrupts to link, autoneg, and modules failure */
 	status = i40e_aq_set_phy_int_mask(hw, IXL_DEFAULT_PHY_INT_MASK,
 	    NULL);
@@ -583,91 +633,35 @@ ixl_attach(device_t dev)
 		device_printf(dev, "i40e_aq_set_phy_mask() failed: err %s,"
 		    " aq_err %s\n", i40e_stat_str(hw, status),
 		    i40e_aq_str(hw, hw->aq.asq_last_status));
-		goto err_late;
+		goto err;
 	}
 
-	/* Get the bus configuration and set the shared code's config */
+	/* Get the bus configuration and set the shared code */
 	ixl_get_bus_info(pf);
 
-	/*
-	 * In MSI-X mode, initialize the Admin Queue interrupt,
-	 * so userland tools can communicate with the adapter regardless of
-	 * the ifnet interface's status.
-	 */
-	if (pf->msix > 1) {
-		error = ixl_setup_adminq_msix(pf);
-		if (error) {
-			device_printf(dev, "ixl_setup_adminq_msix() error: %d\n",
-			    error);
-			goto err_late;
-		}
-		error = ixl_setup_adminq_tq(pf);
-		if (error) {
-			device_printf(dev, "ixl_setup_adminq_tq() error: %d\n",
-			    error);
-			goto err_late;
-		}
-		ixl_configure_intr0_msix(pf);
-		ixl_enable_intr0(hw);
-
-		error = ixl_setup_queue_msix(vsi);
-		if (error)
-			device_printf(dev, "ixl_setup_queue_msix() error: %d\n",
-			    error);
-		error = ixl_setup_queue_tqs(vsi);
-		if (error)
-			device_printf(dev, "ixl_setup_queue_tqs() error: %d\n",
-			    error);
-	} else {
-		error = ixl_setup_legacy(pf);
-
-		error = ixl_setup_adminq_tq(pf);
-		if (error) {
-			device_printf(dev, "ixl_setup_adminq_tq() error: %d\n",
-			    error);
-			goto err_late;
-		}
-
-		error = ixl_setup_queue_tqs(vsi);
-		if (error)
-			device_printf(dev, "ixl_setup_queue_tqs() error: %d\n",
-			    error);
+	/* Keep admin queue interrupts active while driver is loaded */
+	if (vsi->shared->isc_intr == IFLIB_INTR_MSIX) {
+ 		ixl_configure_intr0_msix(pf);
+ 		ixl_enable_intr0(hw);
 	}
 
-	if (error) {
-		device_printf(dev, "interrupt setup error: %d\n", error);
-	}
-
 	/* Set initial advertised speed sysctl value */
 	ixl_set_initial_advertised_speeds(pf);
 
 	/* Initialize statistics & add sysctls */
 	ixl_add_device_sysctls(pf);
-
 	ixl_pf_reset_stats(pf);
 	ixl_update_stats_counters(pf);
 	ixl_add_hw_stats(pf);
 
-	/* Register for VLAN events */
-	vsi->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
-	    ixl_register_vlan, vsi, EVENTHANDLER_PRI_FIRST);
-	vsi->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
-	    ixl_unregister_vlan, vsi, EVENTHANDLER_PRI_FIRST);
+	hw->phy.get_link_info = true;
+	i40e_get_link_status(hw, &pf->link_up);
+	ixl_update_link_status(pf);
 
 #ifdef PCI_IOV
 	ixl_initialize_sriov(pf);
 #endif
 
-#ifdef DEV_NETMAP
-	if (vsi->num_rx_desc == vsi->num_tx_desc) {
-		vsi->queues[0].num_desc = vsi->num_rx_desc;
-		ixl_netmap_attach(vsi);
-	} else
-		device_printf(dev,
-		    "Netmap is not supported when RX and TX descriptor ring sizes differ\n");
-
-#endif /* DEV_NETMAP */
-
 #ifdef IXL_IW
 	if (hw->func_caps.iwarp && ixl_enable_iwarp) {
 		pf->iw_enabled = (pf->iw_msix > 0) ? true : false;
@@ -677,7 +671,7 @@ ixl_attach(device_t dev)
 				device_printf(dev,
 				    "interfacing to iwarp driver failed: %d\n",
 				    error);
-				goto err_late;
+				goto err;
 			} else
 				device_printf(dev, "iWARP ready\n");
 		} else
@@ -689,54 +683,38 @@ ixl_attach(device_t dev)
 	}
 #endif
 
-	INIT_DEBUGOUT("ixl_attach: end");
+	INIT_DBG_DEV(dev, "end");
 	return (0);
 
-err_late:
-	if (vsi->ifp != NULL) {
-		ether_ifdetach(vsi->ifp);
-		if_free(vsi->ifp);
-	}
-err_mac_hmc:
-	i40e_shutdown_lan_hmc(hw);
-err_get_cap:
-	i40e_shutdown_adminq(hw);
-err_out:
-	ixl_free_pci_resources(pf);
-	ixl_free_vsi(vsi);
-	IXL_PF_LOCK_DESTROY(pf);
+err:
+	INIT_DEBUGOUT("end: error %d", error);
+	/* ixl_if_detach() is called on error from this */
 	return (error);
 }
 
-/*********************************************************************
- *  Device removal routine
- *
- *  The detach entry point is called when the driver is being removed.
- *  This routine stops the adapter and deallocates all the resources
- *  that were allocated for driver operation.
- *
- *  return 0 on success, positive on failure
- *********************************************************************/
-
 static int
-ixl_detach(device_t dev)
+ixl_if_detach(if_ctx_t ctx)
 {
-	struct ixl_pf		*pf = device_get_softc(dev);
-	struct i40e_hw		*hw = &pf->hw;
-	struct ixl_vsi		*vsi = &pf->vsi;
+	struct ixl_pf *pf = iflib_get_softc(ctx);
+	struct ixl_vsi *vsi = &pf->vsi;
+	struct i40e_hw *hw = &pf->hw;
+	device_t dev = pf->dev;
 	enum i40e_status_code	status;
 #if defined(PCI_IOV) || defined(IXL_IW)
 	int			error;
 #endif
 
-	INIT_DEBUGOUT("ixl_detach: begin");
+	INIT_DBG_DEV(dev, "begin");
 
-	/* Make sure VLANS are not using driver */
-	if (vsi->ifp->if_vlantrunk != NULL) {
-		device_printf(dev, "Vlan in use, detach first\n");
-		return (EBUSY);
+#ifdef IXL_IW
+	if (ixl_enable_iwarp && pf->iw_enabled) {
+		error = ixl_iw_pf_detach(pf);
+		if (error == EBUSY) {
+			device_printf(dev, "iwarp in use; stop it first.\n");
+			return (error);
+		}
 	}
-
+#endif
 #ifdef PCI_IOV
 	error = pci_iov_detach(dev);
 	if (error != 0) {
@@ -744,73 +722,989 @@ ixl_detach(device_t dev)
 		return (error);
 	}
 #endif
-
 	/* Remove all previously allocated media types */
-	ifmedia_removeall(&vsi->media);
+	ifmedia_removeall(vsi->media);
 
-	ether_ifdetach(vsi->ifp);
-	if (vsi->ifp->if_drv_flags & IFF_DRV_RUNNING)
-		ixl_stop(pf);
-
 	/* Shutdown LAN HMC */
-	status = i40e_shutdown_lan_hmc(hw);
-	if (status)
-		device_printf(dev,
-		    "Shutdown LAN HMC failed with code %d\n", status);
+	if (hw->hmc.hmc_obj) {
+		status = i40e_shutdown_lan_hmc(hw);
+		if (status)
+			device_printf(dev,
+			    "i40e_shutdown_lan_hmc() failed with status %s\n",
+			    i40e_stat_str(hw, status));
+	}
 
-	/* Teardown LAN queue resources */
-	ixl_teardown_queue_msix(vsi);
-	ixl_free_queue_tqs(vsi);
 	/* Shutdown admin queue */
 	ixl_disable_intr0(hw);
-	ixl_teardown_adminq_msix(pf);
-	ixl_free_adminq_tq(pf);
 	status = i40e_shutdown_adminq(hw);
 	if (status)
 		device_printf(dev,
-		    "Shutdown Admin queue failed with code %d\n", status);
+		    "i40e_shutdown_adminq() failed with status %s\n",
+		    i40e_stat_str(hw, status));
 
-	/* Unregister VLAN events */
-	if (vsi->vlan_attach != NULL)
-		EVENTHANDLER_DEREGISTER(vlan_config, vsi->vlan_attach);
-	if (vsi->vlan_detach != NULL)
-		EVENTHANDLER_DEREGISTER(vlan_unconfig, vsi->vlan_detach);
+	ixl_pf_qmgr_destroy(&pf->qmgr);
+	ixl_free_pci_resources(pf);
+	ixl_free_mac_filters(vsi);
+	INIT_DBG_DEV(dev, "end");
+	return (0);
+}
 

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



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