[BACK]Return to ixv.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / pci / ixgbe

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/dev/pci/ixgbe/ixv.c between version 1.2 and 1.2.6.7

version 1.2, 2014/03/25 16:19:14 version 1.2.6.7, 2017/02/05 13:40:45
Line 1 
Line 1 
 /******************************************************************************  /******************************************************************************
   
   Copyright (c) 2001-2010, Intel Corporation    Copyright (c) 2001-2015, Intel Corporation
   All rights reserved.    All rights reserved.
   
   Redistribution and use in source and binary forms, with or without    Redistribution and use in source and binary forms, with or without
Line 30 
Line 30 
   POSSIBILITY OF SUCH DAMAGE.    POSSIBILITY OF SUCH DAMAGE.
   
 ******************************************************************************/  ******************************************************************************/
 /*$FreeBSD: src/sys/dev/ixgbe/ixv.c,v 1.2 2011/03/23 13:10:15 jhb Exp $*/  /*$FreeBSD: head/sys/dev/ixgbe/if_ixv.c 302384 2016-07-07 03:39:18Z sbruno $*/
 /*$NetBSD$*/  /*$NetBSD$*/
   
 #include "opt_inet.h"  #include "opt_inet.h"
   #include "opt_inet6.h"
   
 #include "ixv.h"  #include "ixgbe.h"
   #include "vlan.h"
   
 /*********************************************************************  /*********************************************************************
  *  Driver version   *  Driver version
  *********************************************************************/   *********************************************************************/
 char ixv_driver_version[] = "1.0.0";  char ixv_driver_version[] = "1.4.6-k";
   
 /*********************************************************************  /*********************************************************************
  *  PCI Device ID Table   *  PCI Device ID Table
Line 52  char ixv_driver_version[] = "1.0.0";
Line 54  char ixv_driver_version[] = "1.0.0";
  *  { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }   *  { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
  *********************************************************************/   *********************************************************************/
   
 static ixv_vendor_info_t ixv_vendor_info_array[] =  static ixgbe_vendor_info_t ixv_vendor_info_array[] =
 {  {
         {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_VF, 0, 0, 0},          {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_VF, 0, 0, 0},
           {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_VF, 0, 0, 0},
           {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550_VF, 0, 0, 0},
           {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_VF, 0, 0, 0},
         /* required last entry */          /* required last entry */
         {0, 0, 0, 0, 0}          {0, 0, 0, 0, 0}
 };  };
Line 63  static ixv_vendor_info_t ixv_vendor_info
Line 68  static ixv_vendor_info_t ixv_vendor_info
  *  Table of branding strings   *  Table of branding strings
  *********************************************************************/   *********************************************************************/
   
 static char    *ixv_strings[] = {  static const char    *ixv_strings[] = {
         "Intel(R) PRO/10GbE Virtual Function Network Driver"          "Intel(R) PRO/10GbE Virtual Function Network Driver"
 };  };
   
 /*********************************************************************  /*********************************************************************
  *  Function prototypes   *  Function prototypes
  *********************************************************************/   *********************************************************************/
 static int      ixv_probe(device_t);  static int      ixv_probe(device_t, cfdata_t, void *);
 static int      ixv_attach(device_t);  static void     ixv_attach(device_t, device_t, void *);
 static int      ixv_detach(device_t);  static int      ixv_detach(device_t, int);
   #if 0
 static int      ixv_shutdown(device_t);  static int      ixv_shutdown(device_t);
 #if __FreeBSD_version < 800000  
 static void     ixv_start(struct ifnet *);  
 static void     ixv_start_locked(struct tx_ring *, struct ifnet *);  
 #else  
 static int      ixv_mq_start(struct ifnet *, struct mbuf *);  
 static int      ixv_mq_start_locked(struct ifnet *,  
                     struct tx_ring *, struct mbuf *);  
 static void     ixv_qflush(struct ifnet *);  
 #endif  #endif
 static int      ixv_ioctl(struct ifnet *, u_long, caddr_t);  static int      ixv_ioctl(struct ifnet *, u_long, void *);
 static void     ixv_init(void *);  static int      ixv_init(struct ifnet *);
 static void     ixv_init_locked(struct adapter *);  static void     ixv_init_locked(struct adapter *);
 static void     ixv_stop(void *);  static void     ixv_stop(void *);
 static void     ixv_media_status(struct ifnet *, struct ifmediareq *);  static void     ixv_media_status(struct ifnet *, struct ifmediareq *);
 static int      ixv_media_change(struct ifnet *);  static int      ixv_media_change(struct ifnet *);
 static void     ixv_identify_hardware(struct adapter *);  static void     ixv_identify_hardware(struct adapter *);
 static int      ixv_allocate_pci_resources(struct adapter *);  static int      ixv_allocate_pci_resources(struct adapter *,
 static int      ixv_allocate_msix(struct adapter *);                      const struct pci_attach_args *);
 static int      ixv_allocate_queues(struct adapter *);  static int      ixv_allocate_msix(struct adapter *,
                       const struct pci_attach_args *);
 static int      ixv_setup_msix(struct adapter *);  static int      ixv_setup_msix(struct adapter *);
 static void     ixv_free_pci_resources(struct adapter *);  static void     ixv_free_pci_resources(struct adapter *);
 static void     ixv_local_timer(void *);  static void     ixv_local_timer(void *);
   static void     ixv_local_timer_locked(void *);
 static void     ixv_setup_interface(device_t, struct adapter *);  static void     ixv_setup_interface(device_t, struct adapter *);
 static void     ixv_config_link(struct adapter *);  static void     ixv_config_link(struct adapter *);
   
 static int      ixv_allocate_transmit_buffers(struct tx_ring *);  
 static int      ixv_setup_transmit_structures(struct adapter *);  
 static void     ixv_setup_transmit_ring(struct tx_ring *);  
 static void     ixv_initialize_transmit_units(struct adapter *);  static void     ixv_initialize_transmit_units(struct adapter *);
 static void     ixv_free_transmit_structures(struct adapter *);  
 static void     ixv_free_transmit_buffers(struct tx_ring *);  
   
 static int      ixv_allocate_receive_buffers(struct rx_ring *);  
 static int      ixv_setup_receive_structures(struct adapter *);  
 static int      ixv_setup_receive_ring(struct rx_ring *);  
 static void     ixv_initialize_receive_units(struct adapter *);  static void     ixv_initialize_receive_units(struct adapter *);
 static void     ixv_free_receive_structures(struct adapter *);  
 static void     ixv_free_receive_buffers(struct rx_ring *);  
   
 static void     ixv_enable_intr(struct adapter *);  static void     ixv_enable_intr(struct adapter *);
 static void     ixv_disable_intr(struct adapter *);  static void     ixv_disable_intr(struct adapter *);
 static bool     ixv_txeof(struct tx_ring *);  
 static bool     ixv_rxeof(struct ix_queue *, int);  
 static void     ixv_rx_checksum(u32, struct mbuf *, u32);  
 static void     ixv_set_multi(struct adapter *);  static void     ixv_set_multi(struct adapter *);
 static void     ixv_update_link_status(struct adapter *);  static void     ixv_update_link_status(struct adapter *);
 static void     ixv_refresh_mbufs(struct rx_ring *, int);  static int      ixv_sysctl_debug(SYSCTLFN_PROTO);
 static int      ixv_xmit(struct tx_ring *, struct mbuf **);  
 static int      ixv_sysctl_stats(SYSCTL_HANDLER_ARGS);  
 static int      ixv_sysctl_debug(SYSCTL_HANDLER_ARGS);  
 static int      ixv_set_flowcntl(SYSCTL_HANDLER_ARGS);  
 static int      ixv_dma_malloc(struct adapter *, bus_size_t,  
                     struct ixv_dma_alloc *, int);  
 static void     ixv_dma_free(struct adapter *, struct ixv_dma_alloc *);  
 static void     ixv_add_rx_process_limit(struct adapter *, const char *,  
                     const char *, int *, int);  
 static bool     ixv_tx_ctx_setup(struct tx_ring *, struct mbuf *);  
 static bool     ixv_tso_setup(struct tx_ring *, struct mbuf *, u32 *);  
 static void     ixv_set_ivar(struct adapter *, u8, u8, s8);  static void     ixv_set_ivar(struct adapter *, u8, u8, s8);
 static void     ixv_configure_ivars(struct adapter *);  static void     ixv_configure_ivars(struct adapter *);
 static u8 *     ixv_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);  static u8 *     ixv_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
   
 static void     ixv_setup_vlan_support(struct adapter *);  static void     ixv_setup_vlan_support(struct adapter *);
   #if 0
 static void     ixv_register_vlan(void *, struct ifnet *, u16);  static void     ixv_register_vlan(void *, struct ifnet *, u16);
 static void     ixv_unregister_vlan(void *, struct ifnet *, u16);  static void     ixv_unregister_vlan(void *, struct ifnet *, u16);
   #endif
   
 static void     ixv_save_stats(struct adapter *);  static void     ixv_save_stats(struct adapter *);
 static void     ixv_init_stats(struct adapter *);  static void     ixv_init_stats(struct adapter *);
 static void     ixv_update_stats(struct adapter *);  static void     ixv_update_stats(struct adapter *);
   static void     ixv_add_stats_sysctls(struct adapter *);
 static __inline void ixv_rx_discard(struct rx_ring *, int);  static void     ixv_set_sysctl_value(struct adapter *, const char *,
 static __inline void ixv_rx_input(struct rx_ring *, struct ifnet *,                      const char *, int *, int);
                     struct mbuf *, u32);  
   
 /* The MSI/X Interrupt handlers */  /* The MSI/X Interrupt handlers */
 static void     ixv_msix_que(void *);  static int      ixv_msix_que(void *);
 static void     ixv_msix_mbx(void *);  static int      ixv_msix_mbx(void *);
   
 /* Deferred interrupt tasklets */  /* Deferred interrupt tasklets */
 static void     ixv_handle_que(void *, int);  static void     ixv_handle_que(void *);
 static void     ixv_handle_mbx(void *, int);  static void     ixv_handle_mbx(void *);
   
   const struct sysctlnode *ixv_sysctl_instance(struct adapter *);
   static ixgbe_vendor_info_t *ixv_lookup(const struct pci_attach_args *);
   
   #ifdef DEV_NETMAP
   /*
    * This is defined in <dev/netmap/ixgbe_netmap.h>, which is included by
    * if_ix.c.
    */
   extern void ixgbe_netmap_attach(struct adapter *adapter);
   
   #include <net/netmap.h>
   #include <sys/selinfo.h>
   #include <dev/netmap/netmap_kern.h>
   #endif /* DEV_NETMAP */
   
 /*********************************************************************  /*********************************************************************
  *  FreeBSD Device Interface Entry Points   *  FreeBSD Device Interface Entry Points
  *********************************************************************/   *********************************************************************/
   
   CFATTACH_DECL3_NEW(ixv, sizeof(struct adapter),
       ixv_probe, ixv_attach, ixv_detach, NULL, NULL, NULL,
       DVF_DETACH_SHUTDOWN);
   
   # if 0
 static device_method_t ixv_methods[] = {  static device_method_t ixv_methods[] = {
         /* Device interface */          /* Device interface */
         DEVMETHOD(device_probe, ixv_probe),          DEVMETHOD(device_probe, ixv_probe),
         DEVMETHOD(device_attach, ixv_attach),          DEVMETHOD(device_attach, ixv_attach),
         DEVMETHOD(device_detach, ixv_detach),          DEVMETHOD(device_detach, ixv_detach),
         DEVMETHOD(device_shutdown, ixv_shutdown),          DEVMETHOD(device_shutdown, ixv_shutdown),
         {0, 0}          DEVMETHOD_END
 };  };
   #endif
   
 #if 0  #if 0
 static driver_t ixv_driver = {  static driver_t ixv_driver = {
         "ix", ixv_methods, sizeof(struct adapter),          "ixv", ixv_methods, sizeof(struct adapter),
 };  };
   
 extern devclass_t ixgbe_devclass;  devclass_t ixv_devclass;
 DRIVER_MODULE(ixv, pci, ixv_driver, ixgbe_devclass, 0, 0);  DRIVER_MODULE(ixv, pci, ixv_driver, ixv_devclass, 0, 0);
 MODULE_DEPEND(ixv, pci, 1, 1, 1);  MODULE_DEPEND(ixv, pci, 1, 1, 1);
 MODULE_DEPEND(ixv, ether, 1, 1, 1);  MODULE_DEPEND(ixv, ether, 1, 1, 1);
   #ifdef DEV_NETMAP
   MODULE_DEPEND(ix, netmap, 1, 1, 1);
   #endif /* DEV_NETMAP */
   /* XXX depend on 'ix' ? */
 #endif  #endif
   
 /*  /*
 ** TUNEABLE PARAMETERS:  ** TUNEABLE PARAMETERS:
 */  */
   
   /* Number of Queues - do not exceed MSIX vectors - 1 */
   static int ixv_num_queues = 1;
   #define TUNABLE_INT(__x, __y)
   TUNABLE_INT("hw.ixv.num_queues", &ixv_num_queues);
   
 /*  /*
 ** AIM: Adaptive Interrupt Moderation  ** AIM: Adaptive Interrupt Moderation
 ** which means that the interrupt rate  ** which means that the interrupt rate
Line 191  MODULE_DEPEND(ixv, ether, 1, 1, 1);
Line 197  MODULE_DEPEND(ixv, ether, 1, 1, 1);
 ** traffic for that interrupt vector  ** traffic for that interrupt vector
 */  */
 static int ixv_enable_aim = FALSE;  static int ixv_enable_aim = FALSE;
 #define TUNABLE_INT(__x, __y)  
 TUNABLE_INT("hw.ixv.enable_aim", &ixv_enable_aim);  TUNABLE_INT("hw.ixv.enable_aim", &ixv_enable_aim);
   
 /* How many packets rxeof tries to clean at a time */  /* How many packets rxeof tries to clean at a time */
 static int ixv_rx_process_limit = 128;  static int ixv_rx_process_limit = 256;
 TUNABLE_INT("hw.ixv.rx_process_limit", &ixv_rx_process_limit);  TUNABLE_INT("hw.ixv.rx_process_limit", &ixv_rx_process_limit);
   
 /* Flow control setting, default to full */  /* How many packets txeof tries to clean at a time */
 static int ixv_flow_control = ixgbe_fc_full;  static int ixv_tx_process_limit = 256;
 TUNABLE_INT("hw.ixv.flow_control", &ixv_flow_control);  TUNABLE_INT("hw.ixv.tx_process_limit", &ixv_tx_process_limit);
   
 /*  
  * Header split: this causes the hardware to DMA  
  * the header into a seperate mbuf from the payload,  
  * it can be a performance win in some workloads, but  
  * in others it actually hurts, its off by default.  
  */  
 static bool ixv_header_split = FALSE;  
 TUNABLE_INT("hw.ixv.hdr_split", &ixv_header_split);  
   
 /*  /*
 ** Number of TX descriptors per ring,  ** Number of TX descriptors per ring,
Line 228  TUNABLE_INT("hw.ixv.rxd", &ixv_rxd);
Line 224  TUNABLE_INT("hw.ixv.rxd", &ixv_rxd);
 ** the real filter table gets cleared during  ** the real filter table gets cleared during
 ** a soft reset and we need to repopulate it.  ** a soft reset and we need to repopulate it.
 */  */
 static u32 ixv_shadow_vfta[VFTA_SIZE];  static u32 ixv_shadow_vfta[IXGBE_VFTA_SIZE];
   
 /*********************************************************************  /*********************************************************************
  *  Device identification routine   *  Device identification routine
Line 236  static u32 ixv_shadow_vfta[VFTA_SIZE];
Line 232  static u32 ixv_shadow_vfta[VFTA_SIZE];
  *  ixv_probe determines if the driver should be loaded on   *  ixv_probe determines if the driver should be loaded on
  *  adapter based on PCI vendor/device id of the adapter.   *  adapter based on PCI vendor/device id of the adapter.
  *   *
  *  return 0 on success, positive on failure   *  return 1 on success, 0 on failure
  *********************************************************************/   *********************************************************************/
   
 static int  static int
 ixv_probe(device_t dev)  ixv_probe(device_t dev, cfdata_t cf, void *aux)
   {
   #ifdef __HAVE_PCI_MSI_MSIX
           const struct pci_attach_args *pa = aux;
   
           return (ixv_lookup(pa) != NULL) ? 1 : 0;
   #else
           return 0;
   #endif
   }
   
   static ixgbe_vendor_info_t *
   ixv_lookup(const struct pci_attach_args *pa)
 {  {
         ixv_vendor_info_t *ent;          pcireg_t subid;
           ixgbe_vendor_info_t *ent;
   
         u16     pci_vendor_id = 0;          INIT_DEBUGOUT("ixv_lookup: begin");
         u16     pci_device_id = 0;  
         u16     pci_subvendor_id = 0;  
         u16     pci_subdevice_id = 0;  
         char    adapter_name[256];  
   
           if (PCI_VENDOR(pa->pa_id) != IXGBE_INTEL_VENDOR_ID)
                   return NULL;
   
         pci_vendor_id = pci_get_vendor(dev);          subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
         if (pci_vendor_id != IXGBE_INTEL_VENDOR_ID)  
                 return (ENXIO);  
   
         pci_device_id = pci_get_device(dev);          for (ent = ixv_vendor_info_array; ent->vendor_id != 0; ent++) {
         pci_subvendor_id = pci_get_subvendor(dev);                  if ((PCI_VENDOR(pa->pa_id) == ent->vendor_id) &&
         pci_subdevice_id = pci_get_subdevice(dev);                      (PCI_PRODUCT(pa->pa_id) == ent->device_id) &&
   
         ent = ixv_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) ||                      ((PCI_SUBSYS_VENDOR(subid) == ent->subvendor_id) ||
                      (ent->subvendor_id == 0)) &&                       (ent->subvendor_id == 0)) &&
   
                     ((pci_subdevice_id == ent->subdevice_id) ||                      ((PCI_SUBSYS_ID(subid) == ent->subdevice_id) ||
                      (ent->subdevice_id == 0))) {                       (ent->subdevice_id == 0))) {
                         snprintf(adapter_name, sizeof(adapter_name),                          return ent;
                             "%s, Version - %s", ixv_strings[ent->index],  
                             ixv_driver_version);  
                         device_set_desc_copy(dev, adapter_name);  
                         return (0);  
                 }                  }
                 ent++;  
         }          }
         return (ENXIO);          return NULL;
   }
   
   
   static void
   ixv_sysctl_attach(struct adapter *adapter)
   {
           struct sysctllog **log;
           const struct sysctlnode *rnode, *cnode;
           device_t dev;
   
           dev = adapter->dev;
           log = &adapter->sysctllog;
   
           if ((rnode = ixv_sysctl_instance(adapter)) == NULL) {
                   aprint_error_dev(dev, "could not create sysctl root\n");
                   return;
           }
   
           if (sysctl_createv(log, 0, &rnode, &cnode,
               CTLFLAG_READWRITE, CTLTYPE_INT,
               "debug", SYSCTL_DESCR("Debug Info"),
               ixv_sysctl_debug, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL) != 0)
                   aprint_error_dev(dev, "could not create sysctl\n");
   
           /* XXX This is an *instance* sysctl controlling a *global* variable.
            * XXX It's that way in the FreeBSD driver that this derives from.
            */
           if (sysctl_createv(log, 0, &rnode, &cnode,
               CTLFLAG_READWRITE, CTLTYPE_INT,
               "enable_aim", SYSCTL_DESCR("Interrupt Moderation"),
               NULL, 0, &ixv_enable_aim, 0, CTL_CREATE, CTL_EOL) != 0)
                   aprint_error_dev(dev, "could not create sysctl\n");
 }  }
   
 /*********************************************************************  /*********************************************************************
Line 290  ixv_probe(device_t dev)
Line 317  ixv_probe(device_t dev)
  *  return 0 on success, positive on failure   *  return 0 on success, positive on failure
  *********************************************************************/   *********************************************************************/
   
 static int  static void
 ixv_attach(device_t dev)  ixv_attach(device_t parent, device_t dev, void *aux)
 {  {
         struct adapter *adapter;          struct adapter *adapter;
         struct ixgbe_hw *hw;          struct ixgbe_hw *hw;
         int             error = 0;          int             error = 0;
           ixgbe_vendor_info_t *ent;
           const struct pci_attach_args *pa = aux;
   
         INIT_DEBUGOUT("ixv_attach: begin");          INIT_DEBUGOUT("ixv_attach: begin");
   
         /* Allocate, clear, and link in our adapter structure */          /* Allocate, clear, and link in our adapter structure */
         adapter = device_get_softc(dev);          adapter = device_private(dev);
         adapter->dev = adapter->osdep.dev = dev;          adapter->dev = dev;
         hw = &adapter->hw;          hw = &adapter->hw;
   
   #ifdef DEV_NETMAP
           adapter->init_locked = ixv_init_locked;
           adapter->stop_locked = ixv_stop;
   #endif
   
           adapter->osdep.pc = pa->pa_pc;
           adapter->osdep.tag = pa->pa_tag;
           adapter->osdep.dmat = pa->pa_dmat;
           adapter->osdep.attached = false;
   
           ent = ixv_lookup(pa);
   
           KASSERT(ent != NULL);
   
           aprint_normal(": %s, Version - %s\n",
               ixv_strings[ent->index], ixv_driver_version);
   
         /* Core Lock Init*/          /* Core Lock Init*/
         IXV_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));          IXGBE_CORE_LOCK_INIT(adapter, device_xname(dev));
   
         /* SYSCTL APIs */          /* SYSCTL APIs */
         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),          ixv_sysctl_attach(adapter);
                         SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),  
                         OID_AUTO, "stats", CTLTYPE_INT | CTLFLAG_RW,  
                         adapter, 0, ixv_sysctl_stats, "I", "Statistics");  
   
         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),  
                         SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),  
                         OID_AUTO, "debug", CTLTYPE_INT | CTLFLAG_RW,  
                         adapter, 0, ixv_sysctl_debug, "I", "Debug Info");  
   
         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),  
                         SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),  
                         OID_AUTO, "flow_control", CTLTYPE_INT | CTLFLAG_RW,  
                         adapter, 0, ixv_set_flowcntl, "I", "Flow Control");  
   
         SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),  
                         SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),  
                         OID_AUTO, "enable_aim", CTLTYPE_INT|CTLFLAG_RW,  
                         &ixv_enable_aim, 1, "Interrupt Moderation");  
   
         /* Set up the timer callout */          /* Set up the timer callout */
         callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0);          callout_init(&adapter->timer, 0);
   
         /* Determine hardware revision */          /* Determine hardware revision */
         ixv_identify_hardware(adapter);          ixv_identify_hardware(adapter);
   
         /* Do base PCI setup - map BAR0 */          /* Do base PCI setup - map BAR0 */
         if (ixv_allocate_pci_resources(adapter)) {          if (ixv_allocate_pci_resources(adapter, pa)) {
                 device_printf(dev, "Allocation of PCI resources failed\n");                  aprint_error_dev(dev, "ixv_allocate_pci_resources() failed!\n");
                 error = ENXIO;                  error = ENXIO;
                 goto err_out;                  goto err_out;
         }          }
   
           /* Sysctls for limiting the amount of work done in the taskqueues */
           ixv_set_sysctl_value(adapter, "rx_processing_limit",
               "max number of rx packets to process",
               &adapter->rx_process_limit, ixv_rx_process_limit);
   
           ixv_set_sysctl_value(adapter, "tx_processing_limit",
               "max number of tx packets to process",
               &adapter->tx_process_limit, ixv_tx_process_limit);
   
         /* Do descriptor calc and sanity checks */          /* Do descriptor calc and sanity checks */
         if (((ixv_txd * sizeof(union ixgbe_adv_tx_desc)) % DBA_ALIGN) != 0 ||          if (((ixv_txd * sizeof(union ixgbe_adv_tx_desc)) % DBA_ALIGN) != 0 ||
             ixv_txd < MIN_TXD || ixv_txd > MAX_TXD) {              ixv_txd < MIN_TXD || ixv_txd > MAX_TXD) {
                 device_printf(dev, "TXD config issue, using default!\n");                  aprint_error_dev(dev, "TXD config issue, using default!\n");
                 adapter->num_tx_desc = DEFAULT_TXD;                  adapter->num_tx_desc = DEFAULT_TXD;
         } else          } else
                 adapter->num_tx_desc = ixv_txd;                  adapter->num_tx_desc = ixv_txd;
   
         if (((ixv_rxd * sizeof(union ixgbe_adv_rx_desc)) % DBA_ALIGN) != 0 ||          if (((ixv_rxd * sizeof(union ixgbe_adv_rx_desc)) % DBA_ALIGN) != 0 ||
             ixv_rxd < MIN_TXD || ixv_rxd > MAX_TXD) {              ixv_rxd < MIN_RXD || ixv_rxd > MAX_RXD) {
                 device_printf(dev, "RXD config issue, using default!\n");                  aprint_error_dev(dev, "RXD config issue, using default!\n");
                 adapter->num_rx_desc = DEFAULT_RXD;                  adapter->num_rx_desc = DEFAULT_RXD;
         } else          } else
                 adapter->num_rx_desc = ixv_rxd;                  adapter->num_rx_desc = ixv_rxd;
   
         /* Allocate our TX/RX Queues */          /* Allocate our TX/RX Queues */
         if (ixv_allocate_queues(adapter)) {          if (ixgbe_allocate_queues(adapter)) {
                   aprint_error_dev(dev, "ixgbe_allocate_queues() failed!\n");
                 error = ENOMEM;                  error = ENOMEM;
                 goto err_out;                  goto err_out;
         }          }
Line 368  ixv_attach(device_t dev)
Line 406  ixv_attach(device_t dev)
         */          */
         error = ixgbe_init_shared_code(hw);          error = ixgbe_init_shared_code(hw);
         if (error) {          if (error) {
                 device_printf(dev,"Shared Code Initialization Failure\n");                  aprint_error_dev(dev, "ixgbe_init_shared_code() failed!\n");
                 error = EIO;                  error = EIO;
                 goto err_late;                  goto err_late;
         }          }
Line 376  ixv_attach(device_t dev)
Line 414  ixv_attach(device_t dev)
         /* Setup the mailbox */          /* Setup the mailbox */
         ixgbe_init_mbx_params_vf(hw);          ixgbe_init_mbx_params_vf(hw);
   
         ixgbe_reset_hw(hw);          /* Reset mbox api to 1.0 */
           error = ixgbe_reset_hw(hw);
           if (error == IXGBE_ERR_RESET_FAILED)
                   aprint_error_dev(dev, "ixgbe_reset_hw() failure: Reset Failed!\n");
           else if (error)
                   aprint_error_dev(dev, "ixgbe_reset_hw() failed with error %d\n", error);
           if (error) {
                   error = EIO;
                   goto err_late;
           }
   
         /* Get Hardware Flow Control setting */          /* Negotiate mailbox API version */
         hw->fc.requested_mode = ixgbe_fc_full;          error = ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_11);
         hw->fc.pause_time = IXV_FC_PAUSE;          if (error) {
         hw->fc.low_water = IXV_FC_LO;                  device_printf(dev, "MBX API 1.1 negotiation failed! Error %d\n", error);
         hw->fc.high_water = IXV_FC_HI;                  error = EIO;
         hw->fc.send_xon = TRUE;                  goto err_late;
           }
   
         error = ixgbe_init_hw(hw);          error = ixgbe_init_hw(hw);
         if (error) {          if (error) {
                 device_printf(dev,"Hardware Initialization Failure\n");                  aprint_error_dev(dev, "ixgbe_init_hw() failed!\n");
                 error = EIO;                  error = EIO;
                 goto err_late;                  goto err_late;
         }          }
   
         error = ixv_allocate_msix(adapter);          error = ixv_allocate_msix(adapter, pa);
         if (error)          if (error) {
                   device_printf(dev, "ixv_allocate_msix() failed!\n");
                 goto err_late;                  goto err_late;
           }
   
           /* If no mac address was assigned, make a random one */
           if (!ixv_check_ether_addr(hw->mac.addr)) {
                   u8 addr[ETHER_ADDR_LEN];
                   uint64_t rndval = cprng_fast64();
   
                   memcpy(addr, &rndval, sizeof(addr));
                   addr[0] &= 0xFE;
                   addr[0] |= 0x02;
                   bcopy(addr, hw->mac.addr, sizeof(addr));
           }
   
         /* Setup OS specific network interface */          /* Setup OS specific network interface */
         ixv_setup_interface(dev, adapter);          ixv_setup_interface(dev, adapter);
   
         /* Sysctl for limiting the amount of work done in the taskqueue */  
         ixv_add_rx_process_limit(adapter, "rx_processing_limit",  
             "max number of rx packets to process", &adapter->rx_process_limit,  
             ixv_rx_process_limit);  
   
         /* Do the stats setup */          /* Do the stats setup */
         ixv_save_stats(adapter);          ixv_save_stats(adapter);
         ixv_init_stats(adapter);          ixv_init_stats(adapter);
           ixv_add_stats_sysctls(adapter);
   
         /* Register for VLAN events */          /* Register for VLAN events */
   #if 0 /* XXX delete after write? */
         adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,          adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
             ixv_register_vlan, adapter, EVENTHANDLER_PRI_FIRST);              ixv_register_vlan, adapter, EVENTHANDLER_PRI_FIRST);
         adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,          adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
             ixv_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);              ixv_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);
   #endif
   
   #ifdef DEV_NETMAP
           ixgbe_netmap_attach(adapter);
   #endif /* DEV_NETMAP */
         INIT_DEBUGOUT("ixv_attach: end");          INIT_DEBUGOUT("ixv_attach: end");
         return (0);          adapter->osdep.attached = true;
           return;
   
 err_late:  err_late:
         ixv_free_transmit_structures(adapter);          ixgbe_free_transmit_structures(adapter);
         ixv_free_receive_structures(adapter);          ixgbe_free_receive_structures(adapter);
 err_out:  err_out:
         ixv_free_pci_resources(adapter);          ixv_free_pci_resources(adapter);
         return (error);          return;
   
 }  }
   
Line 437  err_out:
Line 500  err_out:
  *********************************************************************/   *********************************************************************/
   
 static int  static int
 ixv_detach(device_t dev)  ixv_detach(device_t dev, int flags)
 {  {
         struct adapter *adapter = device_get_softc(dev);          struct adapter *adapter = device_private(dev);
         struct ix_queue *que = adapter->queues;          struct ix_queue *que = adapter->queues;
   
         INIT_DEBUGOUT("ixv_detach: begin");          INIT_DEBUGOUT("ixv_detach: begin");
           if (adapter->osdep.attached == false)
                   return 0;
   
   #if NVLAN > 0
         /* Make sure VLANS are not using driver */          /* Make sure VLANS are not using driver */
         if (adapter->ifp->if_vlantrunk != NULL) {          if (!VLAN_ATTACHED(&adapter->osdep.ec))
                 device_printf(dev,"Vlan in use, detach first\n");                  ;       /* nothing to do: no VLANs */
                 return (EBUSY);          else if ((flags & (DETACH_SHUTDOWN|DETACH_FORCE)) != 0)
                   vlan_ifdetach(adapter->ifp);
           else {
                   aprint_error_dev(dev, "VLANs in use, detach first\n");
                   return EBUSY;
         }          }
   #endif
   
         IXV_CORE_LOCK(adapter);          IXGBE_CORE_LOCK(adapter);
         ixv_stop(adapter);          ixv_stop(adapter);
         IXV_CORE_UNLOCK(adapter);          IXGBE_CORE_UNLOCK(adapter);
   
         for (int i = 0; i < adapter->num_queues; i++, que++) {          for (int i = 0; i < adapter->num_queues; i++, que++) {
                 if (que->tq) {  #ifndef IXGBE_LEGACY_TX
                         taskqueue_drain(que->tq, &que->que_task);                  struct tx_ring *txr = adapter->tx_rings;
                         taskqueue_free(que->tq);  
                 }  
         }  
   
         /* Drain the Link queue */                  softint_disestablish(txr->txr_si);
         if (adapter->tq) {  #endif
                 taskqueue_drain(adapter->tq, &adapter->mbx_task);                  softint_disestablish(que->que_si);
                 taskqueue_free(adapter->tq);  
         }          }
   
           /* Drain the Mailbox(link) queue */
           softint_disestablish(adapter->link_si);
   
         /* Unregister VLAN events */          /* Unregister VLAN events */
   #if 0 /* XXX msaitoh delete after write? */
         if (adapter->vlan_attach != NULL)          if (adapter->vlan_attach != NULL)
                 EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach);                  EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach);
         if (adapter->vlan_detach != NULL)          if (adapter->vlan_detach != NULL)
                 EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach);                  EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach);
   #endif
   
         ether_ifdetach(adapter->ifp);          ether_ifdetach(adapter->ifp);
         callout_drain(&adapter->timer);          callout_halt(&adapter->timer, NULL);
   #ifdef DEV_NETMAP
           netmap_detach(adapter->ifp);
   #endif /* DEV_NETMAP */
         ixv_free_pci_resources(adapter);          ixv_free_pci_resources(adapter);
   #if 0 /* XXX the NetBSD port is probably missing something here */
         bus_generic_detach(dev);          bus_generic_detach(dev);
         if_free(adapter->ifp);  #endif
           if_detach(adapter->ifp);
   
         ixv_free_transmit_structures(adapter);          ixgbe_free_transmit_structures(adapter);
         ixv_free_receive_structures(adapter);          ixgbe_free_receive_structures(adapter);
   
         IXV_CORE_LOCK_DESTROY(adapter);          IXGBE_CORE_LOCK_DESTROY(adapter);
         return (0);          return (0);
 }  }
   
Line 491  ixv_detach(device_t dev)
Line 568  ixv_detach(device_t dev)
  *  Shutdown entry point   *  Shutdown entry point
  *   *
  **********************************************************************/   **********************************************************************/
   #if 0 /* XXX NetBSD ought to register something like this through pmf(9) */
 static int  static int
 ixv_shutdown(device_t dev)  ixv_shutdown(device_t dev)
 {  {
         struct adapter *adapter = device_get_softc(dev);          struct adapter *adapter = device_private(dev);
         IXV_CORE_LOCK(adapter);          IXGBE_CORE_LOCK(adapter);
         ixv_stop(adapter);          ixv_stop(adapter);
         IXV_CORE_UNLOCK(adapter);          IXGBE_CORE_UNLOCK(adapter);
         return (0);          return (0);
 }  }
   #endif
 #if __FreeBSD_version < 800000  
 /*********************************************************************  
  *  Transmit entry point  
  *  
  *  ixv_start is called by the stack to initiate a transmit.  
  *  The driver will remain in this routine as long as there are  
  *  packets to transmit and transmit resources are available.  
  *  In case resources are not available stack is notified and  
  *  the packet is requeued.  
  **********************************************************************/  
 static void  
 ixv_start_locked(struct tx_ring *txr, struct ifnet * ifp)  
 {  
         struct mbuf    *m_head;  
         struct adapter *adapter = txr->adapter;  
   
         IXV_TX_LOCK_ASSERT(txr);  
   
         if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) !=  
             IFF_DRV_RUNNING)  
                 return;  
         if (!adapter->link_active)  
                 return;  
   
         while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {  
   
                 IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);  
                 if (m_head == NULL)  
                         break;  
   
                 if (ixv_xmit(txr, &m_head)) {  
                         if (m_head == NULL)  
                                 break;  
                         ifp->if_drv_flags |= IFF_DRV_OACTIVE;  
                         IFQ_DRV_PREPEND(&ifp->if_snd, m_head);  
                         break;  
                 }  
                 /* Send a copy of the frame to the BPF listener */  
                 ETHER_BPF_MTAP(ifp, m_head);  
   
                 /* Set watchdog on */  
                 txr->watchdog_check = TRUE;  
                 txr->watchdog_time = ticks;  
   
         }  
         return;  
 }  
   
 /*  
  * Legacy TX start - called by the stack, this  
  * always uses the first tx ring, and should  
  * not be used with multiqueue tx enabled.  
  */  
 static void  
 ixv_start(struct ifnet *ifp)  
 {  
         struct adapter *adapter = ifp->if_softc;  
         struct tx_ring  *txr = adapter->tx_rings;  
   
         if (ifp->if_drv_flags & IFF_DRV_RUNNING) {  
                 IXV_TX_LOCK(txr);  
                 ixv_start_locked(txr, ifp);  
                 IXV_TX_UNLOCK(txr);  
         }  
         return;  
 }  
   
 #else  
   
 /*  
 ** Multiqueue Transmit driver  
 **  
 */  
 static int  
 ixv_mq_start(struct ifnet *ifp, struct mbuf *m)  
 {  
         struct adapter  *adapter = ifp->if_softc;  
         struct ix_queue *que;  
         struct tx_ring  *txr;  
         int             i = 0, err = 0;  
   
         /* Which queue to use */  
         if ((m->m_flags & M_FLOWID) != 0)  
                 i = m->m_pkthdr.flowid % adapter->num_queues;  
   
         txr = &adapter->tx_rings[i];  
         que = &adapter->queues[i];  
   
         if (IXV_TX_TRYLOCK(txr)) {  
                 err = ixv_mq_start_locked(ifp, txr, m);  
                 IXV_TX_UNLOCK(txr);  
         } else {  
                 err = drbr_enqueue(ifp, txr->br, m);  
                 taskqueue_enqueue(que->tq, &que->que_task);  
         }  
   
         return (err);  
 }  
   
 static int  static int
 ixv_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)  ixv_ifflags_cb(struct ethercom *ec)
 {  {
         struct adapter  *adapter = txr->adapter;          struct ifnet *ifp = &ec->ec_if;
         struct mbuf     *next;          struct adapter *adapter = ifp->if_softc;
         int             enqueued, err = 0;          int change = ifp->if_flags ^ adapter->if_flags, rc = 0;
   
         if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=  
             IFF_DRV_RUNNING || adapter->link_active == 0) {  
                 if (m != NULL)  
                         err = drbr_enqueue(ifp, txr->br, m);  
                 return (err);  
         }  
   
         /* Do a clean if descriptors are low */  
         if (txr->tx_avail <= IXV_TX_CLEANUP_THRESHOLD)  
                 ixv_txeof(txr);  
   
         enqueued = 0;  
         if (m == NULL) {  
                 next = drbr_dequeue(ifp, txr->br);  
         } else if (drbr_needs_enqueue(ifp, txr->br)) {  
                 if ((err = drbr_enqueue(ifp, txr->br, m)) != 0)  
                         return (err);  
                 next = drbr_dequeue(ifp, txr->br);  
         } else  
                 next = m;  
   
         /* Process the queue */          IXGBE_CORE_LOCK(adapter);
         while (next != NULL) {  
                 if ((err = ixv_xmit(txr, &next)) != 0) {  
                         if (next != NULL)  
                                 err = drbr_enqueue(ifp, txr->br, next);  
                         break;  
                 }  
                 enqueued++;  
                 drbr_stats_update(ifp, next->m_pkthdr.len, next->m_flags);  
                 /* Send a copy of the frame to the BPF listener */  
                 ETHER_BPF_MTAP(ifp, next);  
                 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)  
                         break;  
                 if (txr->tx_avail <= IXV_TX_OP_THRESHOLD) {  
                         ifp->if_drv_flags |= IFF_DRV_OACTIVE;  
                         break;  
                 }  
                 next = drbr_dequeue(ifp, txr->br);  
         }  
   
         if (enqueued > 0) {          if (change != 0)
                 /* Set watchdog on */                  adapter->if_flags = ifp->if_flags;
                 txr->watchdog_check = TRUE;  
                 txr->watchdog_time = ticks;  
         }  
   
         return (err);          if ((change & ~(IFF_CANTCHANGE|IFF_DEBUG)) != 0)
 }                  rc = ENETRESET;
   
 /*          IXGBE_CORE_UNLOCK(adapter);
 ** Flush all ring buffers  
 */  
 static void  
 ixv_qflush(struct ifnet *ifp)  
 {  
         struct adapter  *adapter = ifp->if_softc;  
         struct tx_ring  *txr = adapter->tx_rings;  
         struct mbuf     *m;  
   
         for (int i = 0; i < adapter->num_queues; i++, txr++) {          return rc;
                 IXV_TX_LOCK(txr);  
                 while ((m = buf_ring_dequeue_sc(txr->br)) != NULL)  
                         m_freem(m);  
                 IXV_TX_UNLOCK(txr);  
         }  
         if_qflush(ifp);  
 }  }
   
 #endif  
   
 /*********************************************************************  /*********************************************************************
  *  Ioctl entry point   *  Ioctl entry point
  *   *
Line 688  ixv_qflush(struct ifnet *ifp)
Line 610  ixv_qflush(struct ifnet *ifp)
  **********************************************************************/   **********************************************************************/
   
 static int  static int
 ixv_ioctl(struct ifnet * ifp, u_long command, caddr_t data)  ixv_ioctl(struct ifnet * ifp, u_long command, void *data)
 {  {
         struct adapter  *adapter = ifp->if_softc;          struct adapter  *adapter = ifp->if_softc;
           struct ifcapreq *ifcr = data;
         struct ifreq    *ifr = (struct ifreq *) data;          struct ifreq    *ifr = (struct ifreq *) data;
         int             error = 0;          int             error = 0;
           int l4csum_en;
           const int l4csum = IFCAP_CSUM_TCPv4_Rx|IFCAP_CSUM_UDPv4_Rx|
                IFCAP_CSUM_TCPv6_Rx|IFCAP_CSUM_UDPv6_Rx;
   
         switch (command) {          switch (command) {
   
         case SIOCSIFMTU:  
                 IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");  
                 if (ifr->ifr_mtu > IXV_MAX_FRAME_SIZE - ETHER_HDR_LEN) {  
                         error = EINVAL;  
                 } else {  
                         IXV_CORE_LOCK(adapter);  
                         ifp->if_mtu = ifr->ifr_mtu;  
                         adapter->max_frame_size =  
                                 ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;  
                         ixv_init_locked(adapter);  
                         IXV_CORE_UNLOCK(adapter);  
                 }  
                 break;  
         case SIOCSIFFLAGS:          case SIOCSIFFLAGS:
                 IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)");                  IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)");
                 IXV_CORE_LOCK(adapter);  
                 if (ifp->if_flags & IFF_UP) {  
                         if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)  
                                 ixv_init_locked(adapter);  
                 } else  
                         if (ifp->if_drv_flags & IFF_DRV_RUNNING)  
                                 ixv_stop(adapter);  
                 adapter->if_flags = ifp->if_flags;  
                 IXV_CORE_UNLOCK(adapter);  
                 break;                  break;
         case SIOCADDMULTI:          case SIOCADDMULTI:
         case SIOCDELMULTI:          case SIOCDELMULTI:
                 IOCTL_DEBUGOUT("ioctl: SIOC(ADD|DEL)MULTI");                  IOCTL_DEBUGOUT("ioctl: SIOC(ADD|DEL)MULTI");
                 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {  
                         IXV_CORE_LOCK(adapter);  
                         ixv_disable_intr(adapter);  
                         ixv_set_multi(adapter);  
                         ixv_enable_intr(adapter);  
                         IXV_CORE_UNLOCK(adapter);  
                 }  
                 break;                  break;
         case SIOCSIFMEDIA:          case SIOCSIFMEDIA:
         case SIOCGIFMEDIA:          case SIOCGIFMEDIA:
                 IOCTL_DEBUGOUT("ioctl: SIOCxIFMEDIA (Get/Set Interface Media)");                  IOCTL_DEBUGOUT("ioctl: SIOCxIFMEDIA (Get/Set Interface Media)");
                 error = ifmedia_ioctl(ifp, ifr, &adapter->media, command);  
                 break;                  break;
         case SIOCSIFCAP:          case SIOCSIFCAP:
         {  
                 int mask = ifr->ifr_reqcap ^ ifp->if_capenable;  
                 IOCTL_DEBUGOUT("ioctl: SIOCSIFCAP (Set Capabilities)");                  IOCTL_DEBUGOUT("ioctl: SIOCSIFCAP (Set Capabilities)");
                 if (mask & IFCAP_HWCSUM)  
                         ifp->if_capenable ^= IFCAP_HWCSUM;  
                 if (mask & IFCAP_TSO4)  
                         ifp->if_capenable ^= IFCAP_TSO4;  
                 if (mask & IFCAP_LRO)  
                         ifp->if_capenable ^= IFCAP_LRO;  
                 if (mask & IFCAP_VLAN_HWTAGGING)  
                         ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;  
                 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {  
                         IXV_CORE_LOCK(adapter);  
                         ixv_init_locked(adapter);  
                         IXV_CORE_UNLOCK(adapter);  
                 }  
                 VLAN_CAPABILITIES(ifp);  
                 break;                  break;
         }          case SIOCSIFMTU:
                   IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
                   break;
         default:          default:
                 IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)\n", (int)command);                  IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)", (int)command);
                 error = ether_ioctl(ifp, command, data);  
                 break;                  break;
         }          }
   
         return (error);          switch (command) {
           case SIOCSIFMEDIA:
           case SIOCGIFMEDIA:
                   return ifmedia_ioctl(ifp, ifr, &adapter->media, command);
           case SIOCSIFCAP:
                   /* Layer-4 Rx checksum offload has to be turned on and
                    * off as a unit.
                    */
                   l4csum_en = ifcr->ifcr_capenable & l4csum;
                   if (l4csum_en != l4csum && l4csum_en != 0)
                           return EINVAL;
                   /*FALLTHROUGH*/
           case SIOCADDMULTI:
           case SIOCDELMULTI:
           case SIOCSIFFLAGS:
           case SIOCSIFMTU:
           default:
                   if ((error = ether_ioctl(ifp, command, data)) != ENETRESET)
                           return error;
                   if ((ifp->if_flags & IFF_RUNNING) == 0)
                           ;
                   else if (command == SIOCSIFCAP || command == SIOCSIFMTU) {
                           IXGBE_CORE_LOCK(adapter);
                           ixv_init_locked(adapter);
                           IXGBE_CORE_UNLOCK(adapter);
                   } else if (command == SIOCADDMULTI || command == SIOCDELMULTI) {
                           /*
                            * Multicast list has changed; set the hardware filter
                            * accordingly.
                            */
                           IXGBE_CORE_LOCK(adapter);
                           ixv_disable_intr(adapter);
                           ixv_set_multi(adapter);
                           ixv_enable_intr(adapter);
                           IXGBE_CORE_UNLOCK(adapter);
                   }
                   return 0;
           }
 }  }
   
 /*********************************************************************  /*********************************************************************
Line 785  ixv_init_locked(struct adapter *adapter)
Line 701  ixv_init_locked(struct adapter *adapter)
         struct ifnet    *ifp = adapter->ifp;          struct ifnet    *ifp = adapter->ifp;
         device_t        dev = adapter->dev;          device_t        dev = adapter->dev;
         struct ixgbe_hw *hw = &adapter->hw;          struct ixgbe_hw *hw = &adapter->hw;
         u32             mhadd, gpie;          int error = 0;
   
         INIT_DEBUGOUT("ixv_init: begin");          INIT_DEBUGOUT("ixv_init_locked: begin");
         mtx_assert(&adapter->core_mtx, MA_OWNED);          KASSERT(mutex_owned(&adapter->core_mtx));
         hw->adapter_stopped = FALSE;          hw->adapter_stopped = FALSE;
         ixgbe_stop_adapter(hw);          ixgbe_stop_adapter(hw);
         callout_stop(&adapter->timer);          callout_stop(&adapter->timer);
Line 797  ixv_init_locked(struct adapter *adapter)
Line 713  ixv_init_locked(struct adapter *adapter)
         ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);          ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
   
         /* Get the latest mac address, User can use a LAA */          /* Get the latest mac address, User can use a LAA */
         bcopy(IF_LLADDR(adapter->ifp), hw->mac.addr,          memcpy(hw->mac.addr, CLLADDR(adapter->ifp->if_sadl),
              IXGBE_ETH_LENGTH_OF_ADDRESS);               IXGBE_ETH_LENGTH_OF_ADDRESS);
         ixgbe_set_rar(hw, 0, hw->mac.addr, 0, 1);          ixgbe_set_rar(hw, 0, hw->mac.addr, 0, 1);
         hw->addr_ctrl.rar_used_count = 1;          hw->addr_ctrl.rar_used_count = 1;
   
         /* Prepare transmit descriptors and buffers */          /* Prepare transmit descriptors and buffers */
         if (ixv_setup_transmit_structures(adapter)) {          if (ixgbe_setup_transmit_structures(adapter)) {
                 device_printf(dev,"Could not setup transmit structures\n");                  aprint_error_dev(dev, "Could not setup transmit structures\n");
                 ixv_stop(adapter);                  ixv_stop(adapter);
                 return;                  return;
         }          }
   
           /* Reset VF and renegotiate mailbox API version */
         ixgbe_reset_hw(hw);          ixgbe_reset_hw(hw);
           error = ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_11);
           if (error)
                   device_printf(dev, "MBX API 1.1 negotiation failed! Error %d\n", error);
   
         ixv_initialize_transmit_units(adapter);          ixv_initialize_transmit_units(adapter);
   
         /* Setup Multicast table */          /* Setup Multicast table */
Line 825  ixv_init_locked(struct adapter *adapter)
Line 746  ixv_init_locked(struct adapter *adapter)
                 adapter->rx_mbuf_sz = MCLBYTES;                  adapter->rx_mbuf_sz = MCLBYTES;
   
         /* Prepare receive descriptors and buffers */          /* Prepare receive descriptors and buffers */
         if (ixv_setup_receive_structures(adapter)) {          if (ixgbe_setup_receive_structures(adapter)) {
                 device_printf(dev,"Could not setup receive structures\n");                  device_printf(dev, "Could not setup receive structures\n");
                 ixv_stop(adapter);                  ixv_stop(adapter);
                 return;                  return;
         }          }
Line 834  ixv_init_locked(struct adapter *adapter)
Line 755  ixv_init_locked(struct adapter *adapter)
         /* Configure RX settings */          /* Configure RX settings */
         ixv_initialize_receive_units(adapter);          ixv_initialize_receive_units(adapter);
   
         /* Enable Enhanced MSIX mode */  #if 0 /* XXX isn't it required? -- msaitoh  */
         gpie = IXGBE_READ_REG(&adapter->hw, IXGBE_GPIE);  
         gpie |= IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_EIAME;  
         gpie |= IXGBE_GPIE_PBA_SUPPORT | IXGBE_GPIE_OCD;  
         IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);  
   
         /* Set the various hardware offload abilities */          /* Set the various hardware offload abilities */
         ifp->if_hwassist = 0;          ifp->if_hwassist = 0;
         if (ifp->if_capenable & IFCAP_TSO4)          if (ifp->if_capenable & IFCAP_TSO4)
Line 850  ixv_init_locked(struct adapter *adapter)
Line 766  ixv_init_locked(struct adapter *adapter)
                 ifp->if_hwassist |= CSUM_SCTP;                  ifp->if_hwassist |= CSUM_SCTP;
 #endif  #endif
         }          }
   #endif
   
         /* Set MTU size */  
         if (ifp->if_mtu > ETHERMTU) {  
                 mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);  
                 mhadd &= ~IXGBE_MHADD_MFS_MASK;  
                 mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;  
                 IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);  
         }  
   
         /* Set up VLAN offload and filter */          /* Set up VLAN offload and filter */
         ixv_setup_vlan_support(adapter);          ixv_setup_vlan_support(adapter);
   
         callout_reset(&adapter->timer, hz, ixv_local_timer, adapter);  
   
         /* Set up MSI/X routing */          /* Set up MSI/X routing */
         ixv_configure_ivars(adapter);          ixv_configure_ivars(adapter);
   
Line 871  ixv_init_locked(struct adapter *adapter)
Line 778  ixv_init_locked(struct adapter *adapter)
         IXGBE_WRITE_REG(hw, IXGBE_VTEIAM, IXGBE_EICS_RTX_QUEUE);          IXGBE_WRITE_REG(hw, IXGBE_VTEIAM, IXGBE_EICS_RTX_QUEUE);
   
         /* Set moderation on the Link interrupt */          /* Set moderation on the Link interrupt */
         IXGBE_WRITE_REG(hw, IXGBE_VTEITR(adapter->mbxvec), IXV_LINK_ITR);          IXGBE_WRITE_REG(hw, IXGBE_VTEITR(adapter->vector), IXGBE_LINK_ITR);
   
         /* Stats init */          /* Stats init */
         ixv_init_stats(adapter);          ixv_init_stats(adapter);
Line 879  ixv_init_locked(struct adapter *adapter)
Line 786  ixv_init_locked(struct adapter *adapter)
         /* Config/Enable Link */          /* Config/Enable Link */
         ixv_config_link(adapter);          ixv_config_link(adapter);
   
           /* Start watchdog */
           callout_reset(&adapter->timer, hz, ixv_local_timer, adapter);
   
         /* And now turn on interrupts */          /* And now turn on interrupts */
         ixv_enable_intr(adapter);          ixv_enable_intr(adapter);
   
         /* Now inform the stack we're ready */          /* Now inform the stack we're ready */
         ifp->if_drv_flags |= IFF_DRV_RUNNING;          ifp->if_flags |= IFF_RUNNING;
         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;          ifp->if_flags &= ~IFF_OACTIVE;
   
         return;          return;
 }  }
   
 static void  static int
 ixv_init(void *arg)  ixv_init(struct ifnet *ifp)
 {  {
         struct adapter *adapter = arg;          struct adapter *adapter = ifp->if_softc;
   
         IXV_CORE_LOCK(adapter);          IXGBE_CORE_LOCK(adapter);
         ixv_init_locked(adapter);          ixv_init_locked(adapter);
         IXV_CORE_UNLOCK(adapter);          IXGBE_CORE_UNLOCK(adapter);
         return;          return 0;
 }  }
   
   
Line 942  ixv_handle_que(void *context)
Line 852  ixv_handle_que(void *context)
 {  {
         struct ix_queue *que = context;          struct ix_queue *que = context;
         struct adapter  *adapter = que->adapter;          struct adapter  *adapter = que->adapter;
         struct tx_ring  *txr = que->txr;          struct tx_ring  *txr = que->txr;
         struct ifnet    *ifp = adapter->ifp;          struct ifnet    *ifp = adapter->ifp;
         bool            more;          bool            more;
   
         if (ifp->if_drv_flags & IFF_DRV_RUNNING) {          if (ifp->if_flags & IFF_RUNNING) {
                 more = ixv_rxeof(que, adapter->rx_process_limit);                  more = ixgbe_rxeof(que);
                 IXV_TX_LOCK(txr);                  IXGBE_TX_LOCK(txr);
                 ixv_txeof(txr);                  ixgbe_txeof(txr);
 #if __FreeBSD_version >= 800000  #ifndef IXGBE_LEGACY_TX
                 if (!drbr_empty(ifp, txr->br))                  if (pcq_peek(txr->txr_interq) != NULL)
                         ixv_mq_start_locked(ifp, txr, NULL);                          ixgbe_mq_start_locked(ifp, txr);
 #else  #else
                 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))                  if (!IFQ_IS_EMPTY(&ifp->if_snd))
                         ixv_start_locked(txr, ifp);                          ixgbe_start_locked(txr, ifp);
 #endif  #endif
                 IXV_TX_UNLOCK(txr);                  IXGBE_TX_UNLOCK(txr);
                 if (more) {                  if (more) {
                         taskqueue_enqueue(que->tq, &que->que_task);                          adapter->req.ev_count++;
                           softint_schedule(que->que_si);
                         return;                          return;
                 }                  }
         }          }
Line 974  ixv_handle_que(void *context)
Line 885  ixv_handle_que(void *context)
  *  MSI Queue Interrupt Service routine   *  MSI Queue Interrupt Service routine
  *   *
  **********************************************************************/   **********************************************************************/
 void  int
 ixv_msix_que(void *arg)  ixv_msix_que(void *arg)
 {  {
         struct ix_queue *que = arg;          struct ix_queue *que = arg;
         struct adapter  *adapter = que->adapter;          struct adapter  *adapter = que->adapter;
           struct ifnet    *ifp = adapter->ifp;
         struct tx_ring  *txr = que->txr;          struct tx_ring  *txr = que->txr;
         struct rx_ring  *rxr = que->rxr;          struct rx_ring  *rxr = que->rxr;
         bool            more_tx, more_rx;          bool            more;
         u32             newitr = 0;          u32             newitr = 0;
   
         ixv_disable_queue(adapter, que->msix);          ixv_disable_queue(adapter, que->msix);
         ++que->irqs;          ++que->irqs.ev_count;
   
         more_rx = ixv_rxeof(que, adapter->rx_process_limit);  #ifdef __NetBSD__
           /* Don't run ixgbe_rxeof in interrupt context */
         IXV_TX_LOCK(txr);          more = true;
         more_tx = ixv_txeof(txr);  #else
         IXV_TX_UNLOCK(txr);          more = ixgbe_rxeof(que);
   #endif
   
         more_rx = ixv_rxeof(que, adapter->rx_process_limit);          IXGBE_TX_LOCK(txr);
           ixgbe_txeof(txr);
           /*
           ** Make certain that if the stack
           ** has anything queued the task gets
           ** scheduled to handle it.
           */
   #ifdef IXGBE_LEGACY_TX
           if (!IFQ_IS_EMPTY(&adapter->ifp->if_snd))
                   ixgbe_start_locked(txr, ifp);
   #else
           if (pcq_peek(txr->txr_interq) != NULL)
                   ixgbe_mq_start_locked(ifp, txr);
   #endif
           IXGBE_TX_UNLOCK(txr);
   
         /* Do AIM now? */          /* Do AIM now? */
   
Line 1044  ixv_msix_que(void *arg)
Line 971  ixv_msix_que(void *arg)
         rxr->packets = 0;          rxr->packets = 0;
   
 no_calc:  no_calc:
         if (more_tx || more_rx)          if (more)
                 taskqueue_enqueue(que->tq, &que->que_task);                  softint_schedule(que->que_si);
         else /* Reenable this interrupt */          else /* Reenable this interrupt */
                 ixv_enable_queue(adapter, que->msix);                  ixv_enable_queue(adapter, que->msix);
         return;          return 1;
 }  }
   
 static void  static int
 ixv_msix_mbx(void *arg)  ixv_msix_mbx(void *arg)
 {  {
         struct adapter  *adapter = arg;          struct adapter  *adapter = arg;
         struct ixgbe_hw *hw = &adapter->hw;          struct ixgbe_hw *hw = &adapter->hw;
         u32             reg;          u32             reg;
   
         ++adapter->mbx_irq;          ++adapter->link_irq.ev_count;
   
         /* First get the cause */          /* First get the cause */
         reg = IXGBE_READ_REG(hw, IXGBE_VTEICS);          reg = IXGBE_READ_REG(hw, IXGBE_VTEICS);
Line 1067  ixv_msix_mbx(void *arg)
Line 994  ixv_msix_mbx(void *arg)
   
         /* Link status change */          /* Link status change */
         if (reg & IXGBE_EICR_LSC)          if (reg & IXGBE_EICR_LSC)
                 taskqueue_enqueue(adapter->tq, &adapter->mbx_task);                  softint_schedule(adapter->link_si);
   
         IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, IXGBE_EIMS_OTHER);          IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, IXGBE_EIMS_OTHER);
         return;          return 1;
 }  }
   
 /*********************************************************************  /*********************************************************************
Line 1087  ixv_media_status(struct ifnet * ifp, str
Line 1014  ixv_media_status(struct ifnet * ifp, str
         struct adapter *adapter = ifp->if_softc;          struct adapter *adapter = ifp->if_softc;
   
         INIT_DEBUGOUT("ixv_media_status: begin");          INIT_DEBUGOUT("ixv_media_status: begin");
         IXV_CORE_LOCK(adapter);          IXGBE_CORE_LOCK(adapter);
         ixv_update_link_status(adapter);          ixv_update_link_status(adapter);
   
         ifmr->ifm_status = IFM_AVALID;          ifmr->ifm_status = IFM_AVALID;
         ifmr->ifm_active = IFM_ETHER;          ifmr->ifm_active = IFM_ETHER;
   
         if (!adapter->link_active) {          if (!adapter->link_active) {
                 IXV_CORE_UNLOCK(adapter);                  IXGBE_CORE_UNLOCK(adapter);
                 return;                  return;
         }          }
   
Line 1109  ixv_media_status(struct ifnet * ifp, str
Line 1036  ixv_media_status(struct ifnet * ifp, str
                         break;                          break;
         }          }
   
         IXV_CORE_UNLOCK(adapter);          IXGBE_CORE_UNLOCK(adapter);
   
         return;          return;
 }  }
Line 1144  ixv_media_change(struct ifnet * ifp)
Line 1071  ixv_media_change(struct ifnet * ifp)
         return (0);          return (0);
 }  }
   
 /*********************************************************************  
  *  
  *  This routine maps the mbufs to tx descriptors, allowing the  
  *  TX engine to transmit the packets.  
  *      - return 0 on success, positive on failure  
  *  
  **********************************************************************/  
   
 static int  
 ixv_xmit(struct tx_ring *txr, struct mbuf **m_headp)  
 {  
         struct adapter  *adapter = txr->adapter;  
         u32             olinfo_status = 0, cmd_type_len;  
         u32             paylen = 0;  
         int             i, j, error, nsegs;  
         int             first, last = 0;  
         struct mbuf     *m_head;  
         bus_dma_segment_t segs[32];  
         bus_dmamap_t    map;  
         struct ixv_tx_buf *txbuf, *txbuf_mapped;  
         union ixgbe_adv_tx_desc *txd = NULL;  
   
         m_head = *m_headp;  
   
         /* Basic descriptor defines */  
         cmd_type_len = (IXGBE_ADVTXD_DTYP_DATA |  
             IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT);  
   
         if (m_head->m_flags & M_VLANTAG)  
                 cmd_type_len |= IXGBE_ADVTXD_DCMD_VLE;  
   
         /*  
          * Important to capture the first descriptor  
          * used because it will contain the index of  
          * the one we tell the hardware to report back  
          */  
         first = txr->next_avail_desc;  
         txbuf = &txr->tx_buffers[first];  
         txbuf_mapped = txbuf;  
         map = txbuf->map;  
   
         /*  
          * Map the packet for DMA.  
          */  
         error = bus_dmamap_load_mbuf_sg(txr->txtag, map,  
             *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);  
   
         if (error == EFBIG) {  
                 struct mbuf *m;  
   
                 m = m_defrag(*m_headp, M_DONTWAIT);  
                 if (m == NULL) {  
                         adapter->mbuf_defrag_failed++;  
                         m_freem(*m_headp);  
                         *m_headp = NULL;  
                         return (ENOBUFS);  
                 }  
                 *m_headp = m;  
   
                 /* Try it again */  
                 error = bus_dmamap_load_mbuf_sg(txr->txtag, map,  
                     *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);  
   
                 if (error == ENOMEM) {  
                         adapter->no_tx_dma_setup++;  
                         return (error);  
                 } else if (error != 0) {  
                         adapter->no_tx_dma_setup++;  
                         m_freem(*m_headp);  
                         *m_headp = NULL;  
                         return (error);  
                 }  
         } else if (error == ENOMEM) {  
                 adapter->no_tx_dma_setup++;  
                 return (error);  
         } else if (error != 0) {  
                 adapter->no_tx_dma_setup++;  
                 m_freem(*m_headp);  
                 *m_headp = NULL;  
                 return (error);  
         }  
   
         /* Make certain there are enough descriptors */  
         if (nsegs > txr->tx_avail - 2) {  
                 txr->no_desc_avail++;  
                 error = ENOBUFS;  
                 goto xmit_fail;  
         }  
         m_head = *m_headp;  
   
         /*  
         ** Set up the appropriate offload context  
         ** this becomes the first descriptor of  
         ** a packet.  
         */  
         if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {  
                 if (ixv_tso_setup(txr, m_head, &paylen)) {  
                         cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;  
                         olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;  
                         olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;  
                         olinfo_status |= paylen << IXGBE_ADVTXD_PAYLEN_SHIFT;  
                         ++adapter->tso_tx;  
                 } else  
                         return (ENXIO);  
         } else if (ixv_tx_ctx_setup(txr, m_head))  
                 olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;  
   
         /* Record payload length */  
         if (paylen == 0)  
                 olinfo_status |= m_head->m_pkthdr.len <<  
                     IXGBE_ADVTXD_PAYLEN_SHIFT;  
   
         i = txr->next_avail_desc;  
         for (j = 0; j < nsegs; j++) {  
                 bus_size_t seglen;  
                 bus_addr_t segaddr;  
   
                 txbuf = &txr->tx_buffers[i];  
                 txd = &txr->tx_base[i];  
                 seglen = segs[j].ds_len;  
                 segaddr = htole64(segs[j].ds_addr);  
   
                 txd->read.buffer_addr = segaddr;  
                 txd->read.cmd_type_len = htole32(txr->txd_cmd |  
                     cmd_type_len |seglen);  
                 txd->read.olinfo_status = htole32(olinfo_status);  
                 last = i; /* descriptor that will get completion IRQ */  
   
                 if (++i == adapter->num_tx_desc)  
                         i = 0;  
   
                 txbuf->m_head = NULL;  
                 txbuf->eop_index = -1;  
         }  
   
         txd->read.cmd_type_len |=  
             htole32(IXGBE_TXD_CMD_EOP | IXGBE_TXD_CMD_RS);  
         txr->tx_avail -= nsegs;  
         txr->next_avail_desc = i;  
   
         txbuf->m_head = m_head;  
         txbuf->map = map;  
         bus_dmamap_sync(txr->txtag, map, BUS_DMASYNC_PREWRITE);  
   
         /* Set the index of the descriptor that will be marked done */  
         txbuf = &txr->tx_buffers[first];  
         txbuf->eop_index = last;  
   
         bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,  
             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);  
         /*  
          * Advance the Transmit Descriptor Tail (Tdt), this tells the  
          * hardware that this frame is available to transmit.  
          */  
         ++txr->total_packets;  
         IXGBE_WRITE_REG(&adapter->hw, IXGBE_VFTDT(txr->me), i);  
   
         return (0);  
   
 xmit_fail:  
         bus_dmamap_unload(txr->txtag, txbuf->map);  
         return (error);  
   
 }  
   
   
 /*********************************************************************  /*********************************************************************
  *  Multicast Update   *  Multicast Update
Line 1321  xmit_fail:
Line 1083  xmit_fail:
 static void  static void
 ixv_set_multi(struct adapter *adapter)  ixv_set_multi(struct adapter *adapter)
 {  {
           struct ether_multi *enm;
           struct ether_multistep step;
         u8      mta[MAX_NUM_MULTICAST_ADDRESSES * IXGBE_ETH_LENGTH_OF_ADDRESS];          u8      mta[MAX_NUM_MULTICAST_ADDRESSES * IXGBE_ETH_LENGTH_OF_ADDRESS];
         u8      *update_ptr;          u8      *update_ptr;
         struct  ifmultiaddr *ifma;  
         int     mcnt = 0;          int     mcnt = 0;
         struct ifnet   *ifp = adapter->ifp;          struct ethercom *ec = &adapter->osdep.ec;
   
         IOCTL_DEBUGOUT("ixv_set_multi: begin");          IOCTL_DEBUGOUT("ixv_set_multi: begin");
   
 #if __FreeBSD_version < 800000          ETHER_FIRST_MULTI(step, ec, enm);
         IF_ADDR_LOCK(ifp);          while (enm != NULL) {
 #else                  bcopy(enm->enm_addrlo,
         if_maddr_rlock(ifp);  
 #endif  
         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {  
                 if (ifma->ifma_addr->sa_family != AF_LINK)  
                         continue;  
                 bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),  
                     &mta[mcnt * IXGBE_ETH_LENGTH_OF_ADDRESS],                      &mta[mcnt * IXGBE_ETH_LENGTH_OF_ADDRESS],
                     IXGBE_ETH_LENGTH_OF_ADDRESS);                      IXGBE_ETH_LENGTH_OF_ADDRESS);
                 mcnt++;                  mcnt++;
                   /* XXX This might be required --msaitoh */
                   if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES)
                           break;
                   ETHER_NEXT_MULTI(step, enm);
         }          }
 #if __FreeBSD_version < 800000  
         IF_ADDR_UNLOCK(ifp);  
 #else  
         if_maddr_runlock(ifp);  
 #endif  
   
         update_ptr = mta;          update_ptr = mta;
   
         ixgbe_update_mc_addr_list(&adapter->hw,          ixgbe_update_mc_addr_list(&adapter->hw,
             update_ptr, mcnt, ixv_mc_array_itr);              update_ptr, mcnt, ixv_mc_array_itr, TRUE);
   
         return;          return;
 }  }
Line 1384  ixv_mc_array_itr(struct ixgbe_hw *hw, u8
Line 1140  ixv_mc_array_itr(struct ixgbe_hw *hw, u8
 static void  static void
 ixv_local_timer(void *arg)  ixv_local_timer(void *arg)
 {  {
           struct adapter *adapter = arg;
   
           IXGBE_CORE_LOCK(adapter);
           ixv_local_timer_locked(adapter);
           IXGBE_CORE_UNLOCK(adapter);
   }
   
   static void
   ixv_local_timer_locked(void *arg)
   {
         struct adapter  *adapter = arg;          struct adapter  *adapter = arg;
         device_t        dev = adapter->dev;          device_t        dev = adapter->dev;
         struct tx_ring  *txr = adapter->tx_rings;          struct ix_queue *que = adapter->queues;
         int             i;          u64             queues = 0;
           int             hung = 0;
   
         mtx_assert(&adapter->core_mtx, MA_OWNED);          KASSERT(mutex_owned(&adapter->core_mtx));
   
         ixv_update_link_status(adapter);          ixv_update_link_status(adapter);
   
Line 1397  ixv_local_timer(void *arg)
Line 1164  ixv_local_timer(void *arg)
         ixv_update_stats(adapter);          ixv_update_stats(adapter);
   
         /*          /*
          * If the interface has been paused          ** Check the TX queues status
          * then don't do the watchdog check          **      - mark hung queues so we don't schedule on them
          */          **      - watchdog only if all queues show hung
         if (IXGBE_READ_REG(&adapter->hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF)  
                 goto out;  
         /*  
         ** Check for time since any descriptor was cleaned  
         */          */
         for (i = 0; i < adapter->num_queues; i++, txr++) {          for (int i = 0; i < adapter->num_queues; i++, que++) {
                 IXV_TX_LOCK(txr);                  /* Keep track of queues with work for soft irq */
                 if (txr->watchdog_check == FALSE) {                  if (que->txr->busy)
                         IXV_TX_UNLOCK(txr);                          queues |= ((u64)1 << que->me);
                         continue;                  /*
                   ** Each time txeof runs without cleaning, but there
                   ** are uncleaned descriptors it increments busy. If
                   ** we get to the MAX we declare it hung.
                   */
                   if (que->busy == IXGBE_QUEUE_HUNG) {
                           ++hung;
                           /* Mark the queue as inactive */
                           adapter->active_queues &= ~((u64)1 << que->me);
                           continue;
                   } else {
                           /* Check if we've come back from hung */
                           if ((adapter->active_queues & ((u64)1 << que->me)) == 0)
                                   adapter->active_queues |= ((u64)1 << que->me);
                   }
                   if (que->busy >= IXGBE_MAX_TX_BUSY) {
                           device_printf(dev,"Warning queue %d "
                               "appears to be hung!\n", i);
                           que->txr->busy = IXGBE_QUEUE_HUNG;
                           ++hung;
                 }                  }
                 if ((ticks - txr->watchdog_time) > IXV_WATCHDOG)  
                         goto hung;          }
                 IXV_TX_UNLOCK(txr);  
           /* Only truly watchdog if all queues show hung */
           if (hung == adapter->num_queues)
                   goto watchdog;
           else if (queues != 0) { /* Force an IRQ on queues with work */
                   ixv_rearm_queues(adapter, queues);
         }          }
 out:  
         ixv_rearm_queues(adapter, adapter->que_mask);  
         callout_reset(&adapter->timer, hz, ixv_local_timer, adapter);          callout_reset(&adapter->timer, hz, ixv_local_timer, adapter);
         return;          return;
   
 hung:  watchdog:
         device_printf(adapter->dev, "Watchdog timeout -- resetting\n");          device_printf(adapter->dev, "Watchdog timeout -- resetting\n");
         device_printf(dev,"Queue(%d) tdh = %d, hw tdt = %d\n", txr->me,          adapter->ifp->if_flags &= ~IFF_RUNNING;
             IXGBE_READ_REG(&adapter->hw, IXGBE_VFTDH(i)),          adapter->watchdog_events.ev_count++;
             IXGBE_READ_REG(&adapter->hw, IXGBE_VFTDT(i)));  
         device_printf(dev,"TX(%d) desc avail = %d,"  
             "Next TX to Clean = %d\n",  
             txr->me, txr->tx_avail, txr->next_to_clean);  
         adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;  
         adapter->watchdog_events++;  
         IXV_TX_UNLOCK(txr);  
         ixv_init_locked(adapter);          ixv_init_locked(adapter);
 }  }
   
Line 1443  static void
Line 1222  static void
 ixv_update_link_status(struct adapter *adapter)  ixv_update_link_status(struct adapter *adapter)
 {  {
         struct ifnet    *ifp = adapter->ifp;          struct ifnet    *ifp = adapter->ifp;
         struct tx_ring *txr = adapter->tx_rings;  
         device_t dev = adapter->dev;          device_t dev = adapter->dev;
   
   
         if (adapter->link_up){          if (adapter->link_up){
                 if (adapter->link_active == FALSE) {                  if (adapter->link_active == FALSE) {
                         if (bootverbose)                          if (bootverbose)
Line 1462  ixv_update_link_status(struct adapter *a
Line 1239  ixv_update_link_status(struct adapter *a
                                 device_printf(dev,"Link is Down\n");                                  device_printf(dev,"Link is Down\n");
                         if_link_state_change(ifp, LINK_STATE_DOWN);                          if_link_state_change(ifp, LINK_STATE_DOWN);
                         adapter->link_active = FALSE;                          adapter->link_active = FALSE;
                         for (int i = 0; i < adapter->num_queues;  
                             i++, txr++)  
                                 txr->watchdog_check = FALSE;  
                 }                  }
         }          }
   
Line 1472  ixv_update_link_status(struct adapter *a
Line 1246  ixv_update_link_status(struct adapter *a
 }  }
   
   
   static void
   ixv_ifstop(struct ifnet *ifp, int disable)
   {
           struct adapter *adapter = ifp->if_softc;
   
           IXGBE_CORE_LOCK(adapter);
           ixv_stop(adapter);
           IXGBE_CORE_UNLOCK(adapter);
   }
   
 /*********************************************************************  /*********************************************************************
  *   *
  *  This routine disables all traffic on the adapter by issuing a   *  This routine disables all traffic on the adapter by issuing a
Line 1487  ixv_stop(void *arg)
Line 1271  ixv_stop(void *arg)
         struct ixgbe_hw *hw = &adapter->hw;          struct ixgbe_hw *hw = &adapter->hw;
         ifp = adapter->ifp;          ifp = adapter->ifp;
   
         mtx_assert(&adapter->core_mtx, MA_OWNED);          KASSERT(mutex_owned(&adapter->core_mtx));
   
         INIT_DEBUGOUT("ixv_stop: begin\n");          INIT_DEBUGOUT("ixv_stop: begin\n");
         ixv_disable_intr(adapter);          ixv_disable_intr(adapter);
   
         /* Tell the stack that the interface is no longer active */          /* Tell the stack that the interface is no longer active */
         ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);          ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
   
         ixgbe_reset_hw(hw);          ixgbe_reset_hw(hw);
         adapter->hw.adapter_stopped = FALSE;          adapter->hw.adapter_stopped = FALSE;
Line 1515  ixv_stop(void *arg)
Line 1299  ixv_stop(void *arg)
 static void  static void
 ixv_identify_hardware(struct adapter *adapter)  ixv_identify_hardware(struct adapter *adapter)
 {  {
         device_t        dev = adapter->dev;          pcitag_t tag;
         u16             pci_cmd_word;          pci_chipset_tag_t pc;
           pcireg_t subid, id;
           struct ixgbe_hw *hw = &adapter->hw;
   
           pc = adapter->osdep.pc;
           tag = adapter->osdep.tag;
   
         /*          /*
         ** Make sure BUSMASTER is set, on a VM under          ** Make sure BUSMASTER is set, on a VM under
         ** KVM it may not be and will break things.          ** KVM it may not be and will break things.
         */          */
         pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2);          ixgbe_pci_enable_busmaster(pc, tag);
         if (!((pci_cmd_word & PCIM_CMD_BUSMASTEREN) &&  
             (pci_cmd_word & PCIM_CMD_MEMEN))) {          id = pci_conf_read(pc, tag, PCI_ID_REG);
                 INIT_DEBUGOUT("Memory Access and/or Bus Master "          subid = pci_conf_read(pc, tag, PCI_SUBSYS_ID_REG);
                     "bits were not set!\n");  
                 pci_cmd_word |= (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN);  
                 pci_write_config(dev, PCIR_COMMAND, pci_cmd_word, 2);  
         }  
   
         /* Save off the information about this board */          /* Save off the information about this board */
         adapter->hw.vendor_id = pci_get_vendor(dev);          hw->vendor_id = PCI_VENDOR(id);
         adapter->hw.device_id = pci_get_device(dev);          hw->device_id = PCI_PRODUCT(id);
         adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1);          hw->revision_id = PCI_REVISION(pci_conf_read(pc, tag, PCI_CLASS_REG));
         adapter->hw.subsystem_vendor_id =          hw->subsystem_vendor_id = PCI_SUBSYS_VENDOR(subid);
             pci_read_config(dev, PCIR_SUBVEND_0, 2);          hw->subsystem_device_id = PCI_SUBSYS_ID(subid);
         adapter->hw.subsystem_device_id =  
             pci_read_config(dev, PCIR_SUBDEV_0, 2);          /* We need this to determine device-specific things */
           ixgbe_set_mac_type(hw);
   
           /* Set the right number of segments */
           adapter->num_segs = IXGBE_82599_SCATTER;
   
         return;          return;
 }  }
Line 1549  ixv_identify_hardware(struct adapter *ad
Line 1338  ixv_identify_hardware(struct adapter *ad
  *   *
  **********************************************************************/   **********************************************************************/
 static int  static int
 ixv_allocate_msix(struct adapter *adapter)  ixv_allocate_msix(struct adapter *adapter, const struct pci_attach_args *pa)
 {  {
         device_t        dev = adapter->dev;          device_t        dev = adapter->dev;
         struct          ix_queue *que = adapter->queues;          struct ix_queue *que = adapter->queues;
           struct          tx_ring *txr = adapter->tx_rings;
         int             error, rid, vector = 0;          int             error, rid, vector = 0;
           pci_chipset_tag_t pc;
           pcitag_t        tag;
           char intrbuf[PCI_INTRSTR_LEN];
           const char      *intrstr = NULL;
           kcpuset_t       *affinity;
           int             cpu_id = 0;
   
         for (int i = 0; i < adapter->num_queues; i++, vector++, que++) {          pc = adapter->osdep.pc;
                 rid = vector + 1;          tag = adapter->osdep.tag;
                 que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,  
                     RF_SHAREABLE | RF_ACTIVE);          if (pci_msix_alloc_exact(pa,
                 if (que->res == NULL) {                  &adapter->osdep.intrs, IXG_MAX_NINTR) != 0)
                         device_printf(dev,"Unable to allocate"                  return (ENXIO);
                             " bus resource: que interrupt [%d]\n", vector);  
                         return (ENXIO);          kcpuset_create(&affinity, false);
                 }          for (int i = 0; i < adapter->num_queues; i++, vector++, que++, txr++) {
                   intrstr = pci_intr_string(pc, adapter->osdep.intrs[i], intrbuf,
                       sizeof(intrbuf));
   #ifdef IXV_MPSAFE
                   pci_intr_setattr(pc, adapter->osdep.intrs[i], PCI_INTR_MPSAFE,
                       true);
   #endif
                 /* Set the handler function */                  /* Set the handler function */
                 error = bus_setup_intr(dev, que->res,                  adapter->osdep.ihs[i] = pci_intr_establish(pc,
                     INTR_TYPE_NET | INTR_MPSAFE, NULL,                      adapter->osdep.intrs[i], IPL_NET, ixv_msix_que, que);
                     ixv_msix_que, que, &que->tag);                  if (adapter->osdep.ihs[i] == NULL) {
                 if (error) {  
                         que->res = NULL;                          que->res = NULL;
                         device_printf(dev, "Failed to register QUE handler");                          aprint_error_dev(dev,
                         return (error);                              "Failed to register QUE handler");
                           kcpuset_destroy(affinity);
                           return (ENXIO);
                 }                  }
 #if __FreeBSD_version >= 800504  
                 bus_describe_intr(dev, que->res, que->tag, "que %d", i);  
 #endif  
                 que->msix = vector;                  que->msix = vector;
                 adapter->que_mask |= (u64)(1 << que->msix);                  adapter->active_queues |= (u64)(1 << que->msix);
                 /*  
                 ** Bind the msix vector, and thus the  
                 ** ring to the corresponding cpu.  
                 */  
                 if (adapter->num_queues > 1)  
                         bus_bind_intr(dev, que->res, i);  
   
                 ixgbe_task_init(&que->que_task, ixv_handle_que, que);                  cpu_id = i;
                 que->tq = taskqueue_create_fast("ixv_que", M_NOWAIT,                  /* Round-robin affinity */
                     taskqueue_thread_enqueue, &que->tq);                  kcpuset_zero(affinity);
                 taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que",                  kcpuset_set(affinity, cpu_id % ncpu);
                     device_get_nameunit(adapter->dev));                  error = interrupt_distribute(adapter->osdep.ihs[i], affinity,
                       NULL);
                   aprint_normal_dev(dev, "for TX/RX, interrupting at %s",
                       intrstr);
                   if (error == 0)
                           aprint_normal(", bound queue %d to cpu %d\n",
                               i, cpu_id);
                   else
                           aprint_normal("\n");
   
   #ifndef IXGBE_LEGACY_TX
                   txr->txr_si = softint_establish(SOFTINT_NET,
                       ixgbe_deferred_mq_start, txr);
   #endif
                   que->que_si = softint_establish(SOFTINT_NET, ixv_handle_que,
                       que);
                   if (que->que_si == NULL) {
                           aprint_error_dev(dev,
                               "could not establish software interrupt\n");
                   }
         }          }
   
         /* and Mailbox */          /* and Mailbox */
         rid = vector + 1;          cpu_id++;
         adapter->res = bus_alloc_resource_any(dev,          intrstr = pci_intr_string(pc, adapter->osdep.intrs[vector], intrbuf,
             SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);              sizeof(intrbuf));
         if (!adapter->res) {  #ifdef IXG_MPSAFE
                 device_printf(dev,"Unable to allocate"          pci_intr_setattr(pc, &adapter->osdep.intrs[vector], PCI_INTR_MPSAFE, true);
             " bus resource: MBX interrupt [%d]\n", rid);  #endif
                 return (ENXIO);  
         }  
         /* Set the mbx handler function */          /* Set the mbx handler function */
         error = bus_setup_intr(dev, adapter->res,          adapter->osdep.ihs[vector] = pci_intr_establish(pc,
             INTR_TYPE_NET | INTR_MPSAFE, NULL,              adapter->osdep.intrs[vector], IPL_NET, ixv_msix_mbx, adapter);
             ixv_msix_mbx, adapter, &adapter->tag);          if (adapter->osdep.ihs[vector] == NULL) {
         if (error) {  
                 adapter->res = NULL;                  adapter->res = NULL;
                 device_printf(dev, "Failed to register LINK handler");                  aprint_error_dev(dev, "Failed to register LINK handler\n");
                 return (error);                  kcpuset_destroy(affinity);
                   return (ENXIO);
         }          }
 #if __FreeBSD_version >= 800504          /* Round-robin affinity */
         bus_describe_intr(dev, adapter->res, adapter->tag, "mbx");          kcpuset_zero(affinity);
 #endif          kcpuset_set(affinity, cpu_id % ncpu);
         adapter->mbxvec = vector;          error = interrupt_distribute(adapter->osdep.ihs[vector], affinity,NULL);
   
           aprint_normal_dev(dev,
               "for link, interrupting at %s, ", intrstr);
           if (error == 0) {
                   aprint_normal("affinity to cpu %d\n", cpu_id);
           }
           adapter->vector = vector;
         /* Tasklets for Mailbox */          /* Tasklets for Mailbox */
         ixgbe_task_init(&adapter->mbx_task, ixv_handle_mbx, adapter);          adapter->link_si = softint_establish(SOFTINT_NET, ixv_handle_mbx,
         adapter->tq = taskqueue_create_fast("ixv_mbx", M_NOWAIT,              adapter);
             taskqueue_thread_enqueue, &adapter->tq);  
         taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s mbxq",  
             device_get_nameunit(adapter->dev));  
         /*          /*
         ** Due to a broken design QEMU will fail to properly          ** Due to a broken design QEMU will fail to properly
         ** enable the guest for MSIX unless the vectors in          ** enable the guest for MSIX unless the vectors in
Line 1629  ixv_allocate_msix(struct adapter *adapte
Line 1444  ixv_allocate_msix(struct adapter *adapte
         */          */
         if (adapter->hw.mac.type == ixgbe_mac_82599_vf) {          if (adapter->hw.mac.type == ixgbe_mac_82599_vf) {
                 int msix_ctrl;                  int msix_ctrl;
                 pci_find_cap(dev, PCIY_MSIX, &rid);                  pci_get_capability(pc, tag, PCI_CAP_MSIX, &rid, NULL);
                 rid += PCIR_MSIX_CTRL;                  rid += PCI_MSIX_CTL;
                 msix_ctrl = pci_read_config(dev, rid, 2);                  msix_ctrl = pci_conf_read(pc, tag, rid);
                 msix_ctrl |= PCIM_MSIXCTRL_MSIX_ENABLE;                  msix_ctrl |= PCI_MSIX_CTL_ENABLE;
                 pci_write_config(dev, rid, msix_ctrl, 2);                  pci_conf_write(pc, tag, rid, msix_ctrl);
         }          }
   
         return (0);          return (0);
Line 1647  static int
Line 1462  static int
 ixv_setup_msix(struct adapter *adapter)  ixv_setup_msix(struct adapter *adapter)
 {  {
         device_t dev = adapter->dev;          device_t dev = adapter->dev;
         int rid, vectors, want = 2;          int want, msgs;
   
   
         /* First try MSI/X */          /* Must have at least 2 MSIX vectors */
         rid = PCIR_BAR(3);          msgs = pci_msix_count(adapter->osdep.pc, adapter->osdep.tag);
         adapter->msix_mem = bus_alloc_resource_any(dev,          if (msgs < 2) {
             SYS_RES_MEMORY, &rid, RF_ACTIVE);                  aprint_error_dev(dev,"MSIX config error\n");
         if (!adapter->msix_mem) {                  return (ENXIO);
                 device_printf(adapter->dev,  
                     "Unable to map MSIX table \n");  
                 goto out;  
         }  
   
         vectors = pci_msix_count(dev);  
         if (vectors < 2) {  
                 bus_release_resource(dev, SYS_RES_MEMORY,  
                     rid, adapter->msix_mem);  
                 adapter->msix_mem = NULL;  
                 goto out;  
         }          }
           msgs = MIN(msgs, IXG_MAX_NINTR);
   
         /*          /*
         ** Want two vectors: one for a queue,          ** Want vectors for the queues,
         ** plus an additional for mailbox.          ** plus an additional for mailbox.
         */          */
         if (pci_alloc_msix(dev, &want) == 0) {          want = adapter->num_queues + 1;
                 device_printf(adapter->dev,          if (want > msgs) {
                     "Using MSIX interrupts with %d vectors\n", want);                  want = msgs;
                 return (want);                  adapter->num_queues = msgs - 1;
         }          } else
 out:                  msgs = want;
         device_printf(adapter->dev,"MSIX config error\n");  
         return (ENXIO);          adapter->msix_mem = (void *)1; /* XXX */
           aprint_normal_dev(dev,
               "Using MSIX interrupts with %d vectors\n", msgs);
           return (want);
 }  }
   
   
 static int  static int
 ixv_allocate_pci_resources(struct adapter *adapter)  ixv_allocate_pci_resources(struct adapter *adapter,
       const struct pci_attach_args *pa)
 {  {
         int             rid;          pcireg_t        memtype;
         device_t        dev = adapter->dev;          device_t        dev = adapter->dev;
           bus_addr_t addr;
           int flags;
   
         rid = PCIR_BAR(0);          memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_BAR(0));
         adapter->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,  
             &rid, RF_ACTIVE);  
   
         if (!(adapter->pci_mem)) {          switch (memtype) {
                 device_printf(dev,"Unable to allocate bus resource: memory\n");          case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
                 return (ENXIO);          case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
                   adapter->osdep.mem_bus_space_tag = pa->pa_memt;
                   if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PCI_BAR(0),
                         memtype, &addr, &adapter->osdep.mem_size, &flags) != 0)
                           goto map_err;
                   if ((flags & BUS_SPACE_MAP_PREFETCHABLE) != 0) {
                           aprint_normal_dev(dev, "clearing prefetchable bit\n");
                           flags &= ~BUS_SPACE_MAP_PREFETCHABLE;
                   }
                   if (bus_space_map(adapter->osdep.mem_bus_space_tag, addr,
                        adapter->osdep.mem_size, flags,
                        &adapter->osdep.mem_bus_space_handle) != 0) {
   map_err:
                           adapter->osdep.mem_size = 0;
                           aprint_error_dev(dev, "unable to map BAR0\n");
                           return ENXIO;
                   }
                   break;
           default:
                   aprint_error_dev(dev, "unexpected type on BAR0\n");
                   return ENXIO;
         }          }
   
         adapter->osdep.mem_bus_space_tag =          /* Pick up the tuneable queues */
                 rman_get_bustag(adapter->pci_mem);          adapter->num_queues = ixv_num_queues;
         adapter->osdep.mem_bus_space_handle =          adapter->hw.back = adapter;
                 rman_get_bushandle(adapter->pci_mem);  
         adapter->hw.hw_addr = (u8 *) &adapter->osdep.mem_bus_space_handle;  
   
         adapter->num_queues = 1;  
         adapter->hw.back = &adapter->osdep;  
   
         /*          /*
         ** Now setup MSI/X, should          ** Now setup MSI/X, should
Line 1723  static void
Line 1546  static void
 ixv_free_pci_resources(struct adapter * adapter)  ixv_free_pci_resources(struct adapter * adapter)
 {  {
         struct          ix_queue *que = adapter->queues;          struct          ix_queue *que = adapter->queues;
         device_t        dev = adapter->dev;          int             rid;
         int             rid, memrid;  
   
         memrid = PCIR_BAR(MSIX_BAR);  
   
         /*  
         ** There is a slight possibility of a failure mode  
         ** in attach that will result in entering this function  
         ** before interrupt resources have been initialized, and  
         ** in that case we do not want to execute the loops below  
         ** We can detect this reliably by the state of the adapter  
         ** res pointer.  
         */  
         if (adapter->res == NULL)  
                 goto mem;  
   
         /*          /*
         **  Release all msix queue resources:          **  Release all msix queue resources:
         */          */
         for (int i = 0; i < adapter->num_queues; i++, que++) {          for (int i = 0; i < adapter->num_queues; i++, que++) {
                 rid = que->msix + 1;                  rid = que->msix + 1;
                 if (que->tag != NULL) {  
                         bus_teardown_intr(dev, que->res, que->tag);  
                         que->tag = NULL;  
                 }  
                 if (que->res != NULL)                  if (que->res != NULL)
                         bus_release_resource(dev, SYS_RES_IRQ, rid, que->res);                          pci_intr_disestablish(adapter->osdep.pc,
                               adapter->osdep.ihs[i]);
         }          }
   
   
         /* Clean the Legacy or Link interrupt last */          /* Clean the Legacy or Link interrupt last */
         if (adapter->mbxvec) /* we are doing MSIX */          if (adapter->vector) /* we are doing MSIX */
                 rid = adapter->mbxvec + 1;                  rid = adapter->vector + 1;
         else          else
                 (adapter->msix != 0) ? (rid = 1):(rid = 0);                  (adapter->msix != 0) ? (rid = 1):(rid = 0);
   
         if (adapter->tag != NULL) {          if (adapter->osdep.ihs[rid] != NULL)
                 bus_teardown_intr(dev, adapter->res, adapter->tag);                  pci_intr_disestablish(adapter->osdep.pc,
                 adapter->tag = NULL;                      adapter->osdep.ihs[rid]);
         }          adapter->osdep.ihs[rid] = NULL;
         if (adapter->res != NULL)  
                 bus_release_resource(dev, SYS_RES_IRQ, rid, adapter->res);  #if defined(NETBSD_MSI_OR_MSIX)
           pci_intr_release(adapter->osdep.pc, adapter->osdep.intrs,
 mem:              adapter->osdep.nintrs);
         if (adapter->msix)  #endif
                 pci_release_msi(dev);  
           if (adapter->osdep.mem_size != 0) {
         if (adapter->msix_mem != NULL)                  bus_space_unmap(adapter->osdep.mem_bus_space_tag,
                 bus_release_resource(dev, SYS_RES_MEMORY,                      adapter->osdep.mem_bus_space_handle,
                     memrid, adapter->msix_mem);                      adapter->osdep.mem_size);
           }
         if (adapter->pci_mem != NULL)  
                 bus_release_resource(dev, SYS_RES_MEMORY,  
                     PCIR_BAR(0), adapter->pci_mem);  
   
         return;          return;
 }  }
Line 1789  mem:
Line 1592  mem:
 static void  static void
 ixv_setup_interface(device_t dev, struct adapter *adapter)  ixv_setup_interface(device_t dev, struct adapter *adapter)
 {  {
           struct ethercom *ec = &adapter->osdep.ec;
         struct ifnet   *ifp;          struct ifnet   *ifp;
   
         INIT_DEBUGOUT("ixv_setup_interface: begin");          INIT_DEBUGOUT("ixv_setup_interface: begin");
   
         ifp = adapter->ifp = if_alloc(IFT_ETHER);          ifp = adapter->ifp = &ec->ec_if;
         if (ifp == NULL)          strlcpy(ifp->if_xname, device_xname(dev), IFNAMSIZ);
                 panic("%s: can not if_alloc()\n", device_get_nameunit(dev));  
         if_initname(ifp, device_get_name(dev), device_get_unit(dev));  
         ifp->if_mtu = ETHERMTU;  
         ifp->if_baudrate = 1000000000;          ifp->if_baudrate = 1000000000;
         ifp->if_init = ixv_init;          ifp->if_init = ixv_init;
           ifp->if_stop = ixv_ifstop;
         ifp->if_softc = adapter;          ifp->if_softc = adapter;
         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;          ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
         ifp->if_ioctl = ixv_ioctl;          ifp->if_ioctl = ixv_ioctl;
 #if __FreeBSD_version >= 800000  #ifndef IXGBE_LEGACY_TX
         ifp->if_transmit = ixv_mq_start;          ifp->if_transmit = ixgbe_mq_start;
         ifp->if_qflush = ixv_qflush;  
 #else  
         ifp->if_start = ixv_start;  
 #endif  #endif
           ifp->if_start = ixgbe_start;
         ifp->if_snd.ifq_maxlen = adapter->num_tx_desc - 2;          ifp->if_snd.ifq_maxlen = adapter->num_tx_desc - 2;
   
           if_initialize(ifp);
         ether_ifattach(ifp, adapter->hw.mac.addr);          ether_ifattach(ifp, adapter->hw.mac.addr);
   #ifndef IXGBE_LEGACY_TX
   #if 0   /* We use per TX queue softint */
           if_deferred_start_init(ifp, ixgbe_deferred_mq_start);
   #endif
   #endif
           if_register(ifp);
           ether_set_ifflags_cb(ec, ixv_ifflags_cb);
   
         adapter->max_frame_size =          adapter->max_frame_size =
             ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;              ifp->if_mtu + IXGBE_MTU_HDR_VLAN;
   
         /*          /*
          * Tell the upper layer(s) we support long frames.           * Tell the upper layer(s) we support long frames.
          */           */
         ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);          ifp->if_hdrlen = sizeof(struct ether_vlan_header);
   
         ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO4 | IFCAP_VLAN_HWCSUM;          ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSOv4;
         ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;          ifp->if_capenable = 0;
         ifp->if_capabilities |= IFCAP_JUMBO_MTU | IFCAP_LRO;  
   
           ec->ec_capabilities |= ETHERCAP_VLAN_HWCSUM;
           ec->ec_capabilities |= ETHERCAP_JUMBO_MTU;
           ec->ec_capabilities |= ETHERCAP_VLAN_HWTAGGING
                           | ETHERCAP_VLAN_MTU;
           ec->ec_capenable = ec->ec_capabilities;
   
           /* Don't enable LRO by default */
           ifp->if_capabilities |= IFCAP_LRO;
   #if 0
         ifp->if_capenable = ifp->if_capabilities;          ifp->if_capenable = ifp->if_capabilities;
   #endif
   
           /*
           ** Dont turn this on by default, if vlans are
           ** created on another pseudo device (eg. lagg)
           ** then vlan events are not passed thru, breaking
           ** operation, but with HW FILTER off it works. If
           ** using vlans directly on the em driver you can
           ** enable this and get full hardware tag filtering.
           */
           ec->ec_capabilities |= ETHERCAP_VLAN_HWFILTER;
   
         /*          /*
          * Specify the media types supported by this adapter and register           * Specify the media types supported by this adapter and register
Line 1833  ixv_setup_interface(device_t dev, struct
Line 1660  ixv_setup_interface(device_t dev, struct
          */           */
         ifmedia_init(&adapter->media, IFM_IMASK, ixv_media_change,          ifmedia_init(&adapter->media, IFM_IMASK, ixv_media_change,
                      ixv_media_status);                       ixv_media_status);
         ifmedia_add(&adapter->media, IFM_ETHER | IFM_FDX, 0, NULL);  
         ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);          ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
         ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);          ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
   
Line 1842  ixv_setup_interface(device_t dev, struct
Line 1668  ixv_setup_interface(device_t dev, struct
   
 static void  static void
 ixv_config_link(struct adapter *adapter)  ixv_config_link(struct adapter *adapter)
 {  {
         struct ixgbe_hw *hw = &adapter->hw;          struct ixgbe_hw *hw = &adapter->hw;
         u32     autoneg, err = 0;          u32     autoneg;
         bool    negotiate = TRUE;  
   
         if (hw->mac.ops.check_link)  
                 err = hw->mac.ops.check_link(hw, &autoneg,  
                     &adapter->link_up, FALSE);  
         if (err)  
                 goto out;  
   
         if (hw->mac.ops.setup_link)  
                 err = hw->mac.ops.setup_link(hw, autoneg,  
                     negotiate, adapter->link_up);  
 out:  
         return;  
 }  
   
 /********************************************************************  
  * Manage DMA'able memory.  
  *******************************************************************/  
 static void  
 ixv_dmamap_cb(void *arg, bus_dma_segment_t * segs, int nseg, int error)  
 {  
         if (error)  
                 return;  
         *(bus_addr_t *) arg = segs->ds_addr;  
         return;  
 }  
   
 static int  
 ixv_dma_malloc(struct adapter *adapter, bus_size_t size,  
                 struct ixv_dma_alloc *dma, int mapflags)  
 {  
         device_t dev = adapter->dev;  
         int             r;  
   
         r = bus_dma_tag_create(bus_get_dma_tag(adapter->dev),   /* parent */  
                                DBA_ALIGN, 0,    /* alignment, bounds */  
                                BUS_SPACE_MAXADDR,       /* lowaddr */  
                                BUS_SPACE_MAXADDR,       /* highaddr */  
                                NULL, NULL,      /* filter, filterarg */  
                                size,    /* maxsize */  
                                1,       /* nsegments */  
                                size,    /* maxsegsize */  
                                BUS_DMA_ALLOCNOW,        /* flags */  
                                NULL,    /* lockfunc */  
                                NULL,    /* lockfuncarg */  
                                &dma->dma_tag);  
         if (r != 0) {  
                 device_printf(dev,"ixv_dma_malloc: bus_dma_tag_create failed; "  
                        "error %u\n", r);  
                 goto fail_0;  
         }  
         r = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr,  
                              BUS_DMA_NOWAIT, &dma->dma_map);  
         if (r != 0) {  
                 device_printf(dev,"ixv_dma_malloc: bus_dmamem_alloc failed; "  
                        "error %u\n", r);  
                 goto fail_1;  
         }  
         r = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,  
                             size,  
                             ixv_dmamap_cb,  
                             &dma->dma_paddr,  
                             mapflags | BUS_DMA_NOWAIT);  
         if (r != 0) {  
                 device_printf(dev,"ixv_dma_malloc: bus_dmamap_load failed; "  
                        "error %u\n", r);  
                 goto fail_2;  
         }  
         dma->dma_size = size;  
         return (0);  
 fail_2:  
         bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);  
 fail_1:  
         bus_dma_tag_destroy(dma->dma_tag);  
 fail_0:  
         dma->dma_map = NULL;  
         dma->dma_tag = NULL;  
         return (r);  
 }  
   
 static void  
 ixv_dma_free(struct adapter *adapter, struct ixv_dma_alloc *dma)  
 {  
         bus_dmamap_sync(dma->dma_tag, dma->dma_map,  
             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);  
         bus_dmamap_unload(dma->dma_tag, dma->dma_map);  
         bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);  
         bus_dma_tag_destroy(dma->dma_tag);  
 }  
   
   
 /*********************************************************************  
  *  
  *  Allocate memory for the transmit and receive rings, and then  
  *  the descriptors associated with each, called only once at attach.  
  *  
  **********************************************************************/  
 static int  
 ixv_allocate_queues(struct adapter *adapter)  
 {  
         device_t        dev = adapter->dev;  
         struct ix_queue *que;  
         struct tx_ring  *txr;  
         struct rx_ring  *rxr;  
         int rsize, tsize, error = 0;  
         int txconf = 0, rxconf = 0;  
   
         /* First allocate the top level queue structs */  
         if (!(adapter->queues =  
             (struct ix_queue *) malloc(sizeof(struct ix_queue) *  
             adapter->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {  
                 device_printf(dev, "Unable to allocate queue memory\n");  
                 error = ENOMEM;  
                 goto fail;  
         }  
   
         /* First allocate the TX ring struct memory */  
         if (!(adapter->tx_rings =  
             (struct tx_ring *) malloc(sizeof(struct tx_ring) *  
             adapter->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {  
                 device_printf(dev, "Unable to allocate TX ring memory\n");  
                 error = ENOMEM;  
                 goto tx_fail;  
         }  
   
         /* Next allocate the RX */  
         if (!(adapter->rx_rings =  
             (struct rx_ring *) malloc(sizeof(struct rx_ring) *  
             adapter->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {  
                 device_printf(dev, "Unable to allocate RX ring memory\n");  
                 error = ENOMEM;  
                 goto rx_fail;  
         }  
   
         /* For the ring itself */  
         tsize = roundup2(adapter->num_tx_desc *  
             sizeof(union ixgbe_adv_tx_desc), DBA_ALIGN);  
   
         /*  
          * Now set up the TX queues, txconf is needed to handle the  
          * possibility that things fail midcourse and we need to  
          * undo memory gracefully  
          */  
         for (int i = 0; i < adapter->num_queues; i++, txconf++) {  
                 /* Set up some basics */  
                 txr = &adapter->tx_rings[i];  
                 txr->adapter = adapter;  
                 txr->me = i;  
   
                 /* Initialize the TX side lock */  
                 snprintf(txr->mtx_name, sizeof(txr->mtx_name), "%s:tx(%d)",  
                     device_get_nameunit(dev), txr->me);  
                 mtx_init(&txr->tx_mtx, txr->mtx_name, NULL, MTX_DEF);  
   
                 if (ixv_dma_malloc(adapter, tsize,  
                         &txr->txdma, BUS_DMA_NOWAIT)) {  
                         device_printf(dev,  
                             "Unable to allocate TX Descriptor memory\n");  
                         error = ENOMEM;  
                         goto err_tx_desc;  
                 }  
                 txr->tx_base = (union ixgbe_adv_tx_desc *)txr->txdma.dma_vaddr;  
                 bzero((void *)txr->tx_base, tsize);  
   
                 /* Now allocate transmit buffers for the ring */  
                 if (ixv_allocate_transmit_buffers(txr)) {  
                         device_printf(dev,  
                             "Critical Failure setting up transmit buffers\n");  
                         error = ENOMEM;  
                         goto err_tx_desc;  
                 }  
 #if __FreeBSD_version >= 800000  
                 /* Allocate a buf ring */  
                 txr->br = buf_ring_alloc(IXV_BR_SIZE, M_DEVBUF,  
                     M_WAITOK, &txr->tx_mtx);  
                 if (txr->br == NULL) {  
                         device_printf(dev,  
                             "Critical Failure setting up buf ring\n");  
                         error = ENOMEM;  
                         goto err_tx_desc;  
                 }  
 #endif  
         }  
   
         /*  
          * Next the RX queues...  
          */  
         rsize = roundup2(adapter->num_rx_desc *  
             sizeof(union ixgbe_adv_rx_desc), DBA_ALIGN);  
         for (int i = 0; i < adapter->num_queues; i++, rxconf++) {  
                 rxr = &adapter->rx_rings[i];  
                 /* Set up some basics */  
                 rxr->adapter = adapter;  
                 rxr->me = i;  
   
                 /* Initialize the RX side lock */  
                 snprintf(rxr->mtx_name, sizeof(rxr->mtx_name), "%s:rx(%d)",  
                     device_get_nameunit(dev), rxr->me);  
                 mtx_init(&rxr->rx_mtx, rxr->mtx_name, NULL, MTX_DEF);  
   
                 if (ixv_dma_malloc(adapter, rsize,  
                         &rxr->rxdma, BUS_DMA_NOWAIT)) {  
                         device_printf(dev,  
                             "Unable to allocate RxDescriptor memory\n");  
                         error = ENOMEM;  
                         goto err_rx_desc;  
                 }  
                 rxr->rx_base = (union ixgbe_adv_rx_desc *)rxr->rxdma.dma_vaddr;  
                 bzero((void *)rxr->rx_base, rsize);  
   
                 /* Allocate receive buffers for the ring*/  
                 if (ixv_allocate_receive_buffers(rxr)) {  
                         device_printf(dev,  
                             "Critical Failure setting up receive buffers\n");  
                         error = ENOMEM;  
                         goto err_rx_desc;  
                 }  
         }  
   
         /*  
         ** Finally set up the queue holding structs  
         */  
         for (int i = 0; i < adapter->num_queues; i++) {  
                 que = &adapter->queues[i];  
                 que->adapter = adapter;  
                 que->txr = &adapter->tx_rings[i];  
                 que->rxr = &adapter->rx_rings[i];  
         }  
   
         return (0);  
   
 err_rx_desc:  
         for (rxr = adapter->rx_rings; rxconf > 0; rxr++, rxconf--)  
                 ixv_dma_free(adapter, &rxr->rxdma);  
 err_tx_desc:  
         for (txr = adapter->tx_rings; txconf > 0; txr++, txconf--)  
                 ixv_dma_free(adapter, &txr->txdma);  
         free(adapter->rx_rings, M_DEVBUF);  
 rx_fail:  
         free(adapter->tx_rings, M_DEVBUF);  
 tx_fail:  
         free(adapter->queues, M_DEVBUF);  
 fail:  
         return (error);  
 }  
   
   
 /*********************************************************************  
  *  
  *  Allocate memory for tx_buffer structures. The tx_buffer stores all  
  *  the information needed to transmit a packet on the wire. This is  
  *  called only once at attach, setup is done every reset.  
  *  
  **********************************************************************/  
 static int  
 ixv_allocate_transmit_buffers(struct tx_ring *txr)  
 {  
         struct adapter *adapter = txr->adapter;  
         device_t dev = adapter->dev;  
         struct ixv_tx_buf *txbuf;  
         int error, i;  
   
         /*  
          * Setup DMA descriptor areas.  
          */  
         if ((error = bus_dma_tag_create(NULL,           /* parent */  
                                1, 0,            /* alignment, bounds */  
                                BUS_SPACE_MAXADDR,       /* lowaddr */  
                                BUS_SPACE_MAXADDR,       /* highaddr */  
                                NULL, NULL,              /* filter, filterarg */  
                                IXV_TSO_SIZE,            /* maxsize */  
                                32,                      /* nsegments */  
                                PAGE_SIZE,               /* maxsegsize */  
                                0,                       /* flags */  
                                NULL,                    /* lockfunc */  
                                NULL,                    /* lockfuncarg */  
                                &txr->txtag))) {  
                 device_printf(dev,"Unable to allocate TX DMA tag\n");  
                 goto fail;  
         }  
   
         if (!(txr->tx_buffers =  
             (struct ixv_tx_buf *) malloc(sizeof(struct ixv_tx_buf) *  
             adapter->num_tx_desc, M_DEVBUF, M_NOWAIT | M_ZERO))) {  
                 device_printf(dev, "Unable to allocate tx_buffer memory\n");  
                 error = ENOMEM;  
                 goto fail;  
         }  
   
         /* Create the descriptor buffer dma maps */  
         txbuf = txr->tx_buffers;  
         for (i = 0; i < adapter->num_tx_desc; i++, txbuf++) {  
                 error = bus_dmamap_create(txr->txtag, 0, &txbuf->map);  
                 if (error != 0) {  
                         device_printf(dev, "Unable to create TX DMA map\n");  
                         goto fail;  
                 }  
         }  
   
         return 0;  
 fail:  
         /* We free all, it handles case where we are in the middle */  
         ixv_free_transmit_structures(adapter);  
         return (error);  
 }  
   
 /*********************************************************************  
  *  
  *  Initialize a transmit ring.  
  *  
  **********************************************************************/  
 static void  
 ixv_setup_transmit_ring(struct tx_ring *txr)  
 {  
         struct adapter *adapter = txr->adapter;  
         struct ixv_tx_buf *txbuf;  
         int i;  
   
         /* Clear the old ring contents */  
         IXV_TX_LOCK(txr);  
         bzero((void *)txr->tx_base,  
               (sizeof(union ixgbe_adv_tx_desc)) * adapter->num_tx_desc);  
         /* Reset indices */  
         txr->next_avail_desc = 0;  
         txr->next_to_clean = 0;  
   
         /* Free any existing tx buffers. */  
         txbuf = txr->tx_buffers;  
         for (i = 0; i < adapter->num_tx_desc; i++, txbuf++) {  
                 if (txbuf->m_head != NULL) {  
                         bus_dmamap_sync(txr->txtag, txbuf->map,  
                             BUS_DMASYNC_POSTWRITE);  
                         bus_dmamap_unload(txr->txtag, txbuf->map);  
                         m_freem(txbuf->m_head);  
                         txbuf->m_head = NULL;  
                 }  
                 /* Clear the EOP index */  
                 txbuf->eop_index = -1;  
         }  
   
         /* Set number of descriptors available */  
         txr->tx_avail = adapter->num_tx_desc;  
   
         bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,  
             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);  
         IXV_TX_UNLOCK(txr);  
 }  
   
 /*********************************************************************  
  *  
  *  Initialize all transmit rings.  
  *  
  **********************************************************************/  
 static int  
 ixv_setup_transmit_structures(struct adapter *adapter)  
 {  
         struct tx_ring *txr = adapter->tx_rings;  
   
         for (int i = 0; i < adapter->num_queues; i++, txr++)  
                 ixv_setup_transmit_ring(txr);  
   
         return (0);  
 }  
   
 /*********************************************************************  
  *  
  *  Enable transmit unit.  
  *  
  **********************************************************************/  
 static void  
 ixv_initialize_transmit_units(struct adapter *adapter)  
 {  
         struct tx_ring  *txr = adapter->tx_rings;  
         struct ixgbe_hw *hw = &adapter->hw;  
   
   
         for (int i = 0; i < adapter->num_queues; i++, txr++) {  
                 u64     tdba = txr->txdma.dma_paddr;  
                 u32     txctrl, txdctl;  
   
                 /* Set WTHRESH to 8, burst writeback */  
                 txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i));  
                 txdctl |= (8 << 16);  
                 IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(i), txdctl);  
                 /* Now enable */  
                 txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i));  
                 txdctl |= IXGBE_TXDCTL_ENABLE;  
                 IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(i), txdctl);  
   
                 /* Set the HW Tx Head and Tail indices */  
                 IXGBE_WRITE_REG(&adapter->hw, IXGBE_VFTDH(i), 0);  
                 IXGBE_WRITE_REG(&adapter->hw, IXGBE_VFTDT(i), 0);  
   
                 /* Setup Transmit Descriptor Cmd Settings */  
                 txr->txd_cmd = IXGBE_TXD_CMD_IFCS;  
                 txr->watchdog_check = FALSE;  
   
                 /* Set Ring parameters */  
                 IXGBE_WRITE_REG(hw, IXGBE_VFTDBAL(i),  
                        (tdba & 0x00000000ffffffffULL));  
                 IXGBE_WRITE_REG(hw, IXGBE_VFTDBAH(i), (tdba >> 32));  
                 IXGBE_WRITE_REG(hw, IXGBE_VFTDLEN(i),  
                     adapter->num_tx_desc *  
                     sizeof(struct ixgbe_legacy_tx_desc));  
                 txctrl = IXGBE_READ_REG(hw, IXGBE_VFDCA_TXCTRL(i));  
                 txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;  
                 IXGBE_WRITE_REG(hw, IXGBE_VFDCA_TXCTRL(i), txctrl);  
                 break;  
         }  
   
         return;  
 }  
   
 /*********************************************************************  
  *  
  *  Free all transmit rings.  
  *  
  **********************************************************************/  
 static void  
 ixv_free_transmit_structures(struct adapter *adapter)  
 {  
         struct tx_ring *txr = adapter->tx_rings;  
   
         for (int i = 0; i < adapter->num_queues; i++, txr++) {  
                 IXV_TX_LOCK(txr);  
                 ixv_free_transmit_buffers(txr);  
                 ixv_dma_free(adapter, &txr->txdma);  
                 IXV_TX_UNLOCK(txr);  
                 IXV_TX_LOCK_DESTROY(txr);  
         }  
         free(adapter->tx_rings, M_DEVBUF);  
 }  
   
 /*********************************************************************  
  *  
  *  Free transmit ring related data structures.  
  *  
  **********************************************************************/  
 static void  
 ixv_free_transmit_buffers(struct tx_ring *txr)  
 {  
         struct adapter *adapter = txr->adapter;  
         struct ixv_tx_buf *tx_buffer;  
         int             i;  
   
         INIT_DEBUGOUT("free_transmit_ring: begin");  
   
         if (txr->tx_buffers == NULL)  
                 return;  
   
         tx_buffer = txr->tx_buffers;  
         for (i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) {  
                 if (tx_buffer->m_head != NULL) {  
                         bus_dmamap_sync(txr->txtag, tx_buffer->map,  
                             BUS_DMASYNC_POSTWRITE);  
                         bus_dmamap_unload(txr->txtag,  
                             tx_buffer->map);  
                         m_freem(tx_buffer->m_head);  
                         tx_buffer->m_head = NULL;  
                         if (tx_buffer->map != NULL) {  
                                 bus_dmamap_destroy(txr->txtag,  
                                     tx_buffer->map);  
                                 tx_buffer->map = NULL;  
                         }  
                 } else if (tx_buffer->map != NULL) {  
                         bus_dmamap_unload(txr->txtag,  
                             tx_buffer->map);  
                         bus_dmamap_destroy(txr->txtag,  
                             tx_buffer->map);  
                         tx_buffer->map = NULL;  
                 }  
         }  
 #if __FreeBSD_version >= 800000  
         if (txr->br != NULL)  
                 buf_ring_free(txr->br, M_DEVBUF);  
 #endif  
         if (txr->tx_buffers != NULL) {  
                 free(txr->tx_buffers, M_DEVBUF);  
                 txr->tx_buffers = NULL;  
         }  
         if (txr->txtag != NULL) {  
                 bus_dma_tag_destroy(txr->txtag);  
                 txr->txtag = NULL;  
         }  
         return;  
 }  
   
 /*********************************************************************  
  *  
  *  Advanced Context Descriptor setup for VLAN or CSUM  
  *  
  **********************************************************************/  
   
 static boolean_t  
 ixv_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)  
 {  
         struct adapter *adapter = txr->adapter;  
         struct ixgbe_adv_tx_context_desc *TXD;  
         struct ixv_tx_buf        *tx_buffer;  
         u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;  
         struct ether_vlan_header *eh;  
         struct ip *ip;  
         struct ip6_hdr *ip6;  
         int  ehdrlen, ip_hlen = 0;  
         u16     etype;  
         u8      ipproto = 0;  
         bool    offload = TRUE;  
         int ctxd = txr->next_avail_desc;  
         u16 vtag = 0;  
   
   
         if ((mp->m_pkthdr.csum_flags & CSUM_OFFLOAD) == 0)  
                 offload = FALSE;  
   
   
         tx_buffer = &txr->tx_buffers[ctxd];  
         TXD = (struct ixgbe_adv_tx_context_desc *) &txr->tx_base[ctxd];  
   
         /*  
         ** In advanced descriptors the vlan tag must  
         ** be placed into the descriptor itself.  
         */  
         if (mp->m_flags & M_VLANTAG) {  
                 vtag = htole16(mp->m_pkthdr.ether_vtag);  
                 vlan_macip_lens |= (vtag << IXGBE_ADVTXD_VLAN_SHIFT);  
         } else if (offload == FALSE)  
                 return FALSE;  
   
         /*  
          * Determine where frame payload starts.  
          * Jump over vlan headers if already present,  
          * helpful for QinQ too.  
          */  
         eh = mtod(mp, struct ether_vlan_header *);  
         if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {  
                 etype = ntohs(eh->evl_proto);  
                 ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;  
         } else {  
                 etype = ntohs(eh->evl_encap_proto);  
                 ehdrlen = ETHER_HDR_LEN;  
         }  
   
         /* Set the ether header length */  
         vlan_macip_lens |= ehdrlen << IXGBE_ADVTXD_MACLEN_SHIFT;  
   
         switch (etype) {  
                 case ETHERTYPE_IP:  
                         ip = (struct ip *)(mp->m_data + ehdrlen);  
                         ip_hlen = ip->ip_hl << 2;  
                         if (mp->m_len < ehdrlen + ip_hlen)  
                                 return (FALSE);  
                         ipproto = ip->ip_p;  
                         type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;  
                         break;  
                 case ETHERTYPE_IPV6:  
                         ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);  
                         ip_hlen = sizeof(struct ip6_hdr);  
                         if (mp->m_len < ehdrlen + ip_hlen)  
                                 return (FALSE);  
                         ipproto = ip6->ip6_nxt;  
                         type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;  
                         break;  
                 default:  
                         offload = FALSE;  
                         break;  
         }  
   
         vlan_macip_lens |= ip_hlen;  
         type_tucmd_mlhl |= IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;  
   
         switch (ipproto) {  
                 case IPPROTO_TCP:  
                         if (mp->m_pkthdr.csum_flags & CSUM_TCP)  
                                 type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;  
                         break;  
   
                 case IPPROTO_UDP:  
                         if (mp->m_pkthdr.csum_flags & CSUM_UDP)  
                                 type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_UDP;  
                         break;  
   
 #if __FreeBSD_version >= 800000  
                 case IPPROTO_SCTP:  
                         if (mp->m_pkthdr.csum_flags & CSUM_SCTP)  
                                 type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;  
                         break;  
 #endif  
                 default:  
                         offload = FALSE;  
                         break;  
         }  
   
         /* Now copy bits into descriptor */  
         TXD->vlan_macip_lens |= htole32(vlan_macip_lens);  
         TXD->type_tucmd_mlhl |= htole32(type_tucmd_mlhl);  
         TXD->seqnum_seed = htole32(0);  
         TXD->mss_l4len_idx = htole32(0);  
   
         tx_buffer->m_head = NULL;  
         tx_buffer->eop_index = -1;  
   
         /* We've consumed the first desc, adjust counters */  
         if (++ctxd == adapter->num_tx_desc)  
                 ctxd = 0;  
         txr->next_avail_desc = ctxd;  
         --txr->tx_avail;  
   
         return (offload);  
 }  
   
 /**********************************************************************  
  *  
  *  Setup work for hardware segmentation offload (TSO) on  
  *  adapters using advanced tx descriptors  
  *  
  **********************************************************************/  
 static boolean_t  
 ixv_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen)  
 {  
         struct adapter *adapter = txr->adapter;  
         struct ixgbe_adv_tx_context_desc *TXD;  
         struct ixv_tx_buf        *tx_buffer;  
         u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;  
         u32 mss_l4len_idx = 0;  
         u16 vtag = 0;  
         int ctxd, ehdrlen,  hdrlen, ip_hlen, tcp_hlen;  
         struct ether_vlan_header *eh;  
         struct ip *ip;  
         struct tcphdr *th;  
   
   
         /*  
          * Determine where frame payload starts.  
          * Jump over vlan headers if already present  
          */  
         eh = mtod(mp, struct ether_vlan_header *);  
         if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN))  
                 ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;  
         else  
                 ehdrlen = ETHER_HDR_LEN;  
   
         /* Ensure we have at least the IP+TCP header in the first mbuf. */  
         if (mp->m_len < ehdrlen + sizeof(struct ip) + sizeof(struct tcphdr))  
                 return FALSE;  
   
         ctxd = txr->next_avail_desc;  
         tx_buffer = &txr->tx_buffers[ctxd];  
         TXD = (struct ixgbe_adv_tx_context_desc *) &txr->tx_base[ctxd];  
   
         ip = (struct ip *)(mp->m_data + ehdrlen);  
         if (ip->ip_p != IPPROTO_TCP)  
                 return FALSE;   /* 0 */  
         ip->ip_sum = 0;  
         ip_hlen = ip->ip_hl << 2;  
         th = (struct tcphdr *)((caddr_t)ip + ip_hlen);  
         th->th_sum = in_pseudo(ip->ip_src.s_addr,  
             ip->ip_dst.s_addr, htons(IPPROTO_TCP));  
         tcp_hlen = th->th_off << 2;  
         hdrlen = ehdrlen + ip_hlen + tcp_hlen;  
   
         /* This is used in the transmit desc in encap */  
         *paylen = mp->m_pkthdr.len - hdrlen;  
   
         /* VLAN MACLEN IPLEN */  
         if (mp->m_flags & M_VLANTAG) {  
                 vtag = htole16(mp->m_pkthdr.ether_vtag);  
                 vlan_macip_lens |= (vtag << IXGBE_ADVTXD_VLAN_SHIFT);  
         }  
   
         vlan_macip_lens |= ehdrlen << IXGBE_ADVTXD_MACLEN_SHIFT;  
         vlan_macip_lens |= ip_hlen;  
         TXD->vlan_macip_lens |= htole32(vlan_macip_lens);  
   
         /* ADV DTYPE TUCMD */  
         type_tucmd_mlhl |= IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;  
         type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;  
         type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;  
         TXD->type_tucmd_mlhl |= htole32(type_tucmd_mlhl);  
   
   
         /* MSS L4LEN IDX */  
         mss_l4len_idx |= (mp->m_pkthdr.tso_segsz << IXGBE_ADVTXD_MSS_SHIFT);  
         mss_l4len_idx |= (tcp_hlen << IXGBE_ADVTXD_L4LEN_SHIFT);  
         TXD->mss_l4len_idx = htole32(mss_l4len_idx);  
   
         TXD->seqnum_seed = htole32(0);  
         tx_buffer->m_head = NULL;  
         tx_buffer->eop_index = -1;  
   
         if (++ctxd == adapter->num_tx_desc)  
                 ctxd = 0;  
   
         txr->tx_avail--;  
         txr->next_avail_desc = ctxd;  
         return TRUE;  
 }  
   
   
 /**********************************************************************  
  *  
  *  Examine each tx_buffer in the used queue. If the hardware is done  
  *  processing the packet then free associated resources. The  
  *  tx_buffer is put back on the free queue.  
  *  
  **********************************************************************/  
 static boolean_t  
 ixv_txeof(struct tx_ring *txr)  
 {  
         struct adapter  *adapter = txr->adapter;  
         struct ifnet    *ifp = adapter->ifp;  
         u32     first, last, done;  
         struct ixv_tx_buf *tx_buffer;  
         struct ixgbe_legacy_tx_desc *tx_desc, *eop_desc;  
   
         mtx_assert(&txr->tx_mtx, MA_OWNED);  
   
         if (txr->tx_avail == adapter->num_tx_desc)  
                 return FALSE;  
   
         first = txr->next_to_clean;  
         tx_buffer = &txr->tx_buffers[first];  
         /* For cleanup we just use legacy struct */  
         tx_desc = (struct ixgbe_legacy_tx_desc *)&txr->tx_base[first];  
         last = tx_buffer->eop_index;  
         if (last == -1)  
                 return FALSE;  
         eop_desc = (struct ixgbe_legacy_tx_desc *)&txr->tx_base[last];  
   
         /*  
         ** Get the index of the first descriptor  
         ** BEYOND the EOP and call that 'done'.  
         ** I do this so the comparison in the  
         ** inner while loop below can be simple  
         */  
         if (++last == adapter->num_tx_desc) last = 0;  
         done = last;  
   
         bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,  
             BUS_DMASYNC_POSTREAD);  
         /*  
         ** Only the EOP descriptor of a packet now has the DD  
         ** bit set, this is what we look for...  
         */  
         while (eop_desc->upper.fields.status & IXGBE_TXD_STAT_DD) {  
                 /* We clean the range of the packet */  
                 while (first != done) {  
                         tx_desc->upper.data = 0;  
                         tx_desc->lower.data = 0;  
                         tx_desc->buffer_addr = 0;  
                         ++txr->tx_avail;  
   
                         if (tx_buffer->m_head) {  
                                 bus_dmamap_sync(txr->txtag,  
                                     tx_buffer->map,  
                                     BUS_DMASYNC_POSTWRITE);  
                                 bus_dmamap_unload(txr->txtag,  
                                     tx_buffer->map);  
                                 m_freem(tx_buffer->m_head);  
                                 tx_buffer->m_head = NULL;  
                                 tx_buffer->map = NULL;  
                         }  
                         tx_buffer->eop_index = -1;  
                         txr->watchdog_time = ticks;  
   
                         if (++first == adapter->num_tx_desc)  
                                 first = 0;  
   
                         tx_buffer = &txr->tx_buffers[first];  
                         tx_desc =  
                             (struct ixgbe_legacy_tx_desc *)&txr->tx_base[first];  
                 }  
                 ++ifp->if_opackets;  
                 /* See if there is more work now */  
                 last = tx_buffer->eop_index;  
                 if (last != -1) {  
                         eop_desc =  
                             (struct ixgbe_legacy_tx_desc *)&txr->tx_base[last];  
                         /* Get next done point */  
                         if (++last == adapter->num_tx_desc) last = 0;  
                         done = last;  
                 } else  
                         break;  
         }  
         bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,  
             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);  
   
         txr->next_to_clean = first;  
   
         /*  
          * If we have enough room, clear IFF_DRV_OACTIVE to tell the stack that  
          * it is OK to send packets. If there are no pending descriptors,  
          * clear the timeout. Otherwise, if some descriptors have been freed,  
          * restart the timeout.  
          */  
         if (txr->tx_avail > IXV_TX_CLEANUP_THRESHOLD) {  
                 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;  
                 if (txr->tx_avail == adapter->num_tx_desc) {  
                         txr->watchdog_check = FALSE;  
                         return FALSE;  
                 }  
         }  
   
         return TRUE;  
 }  
   
 /*********************************************************************  
  *  
  *  Refresh mbuf buffers for RX descriptor rings  
  *   - now keeps its own state so discards due to resource  
  *     exhaustion are unnecessary, if an mbuf cannot be obtained  
  *     it just returns, keeping its placeholder, thus it can simply  
  *     be recalled to try again.  
  *  
  **********************************************************************/  
 static void  
 ixv_refresh_mbufs(struct rx_ring *rxr, int limit)  
 {  
         struct adapter          *adapter = rxr->adapter;  
         bus_dma_segment_t       hseg[1];  
         bus_dma_segment_t       pseg[1];  
         struct ixv_rx_buf       *rxbuf;  
         struct mbuf             *mh, *mp;  
         int                     i, nsegs, error, cleaned;  
   
         i = rxr->next_to_refresh;  
         cleaned = -1; /* Signify no completions */  
         while (i != limit) {  
                 rxbuf = &rxr->rx_buffers[i];  
                 if ((rxbuf->m_head == NULL) && (rxr->hdr_split)) {  
                         mh = m_gethdr(M_DONTWAIT, MT_DATA);  
                         if (mh == NULL)  
                                 goto update;  
                         mh->m_pkthdr.len = mh->m_len = MHLEN;  
                         mh->m_len = MHLEN;  
                         mh->m_flags |= M_PKTHDR;  
                         m_adj(mh, ETHER_ALIGN);  
                         /* Get the memory mapping */  
                         error = bus_dmamap_load_mbuf_sg(rxr->htag,  
                             rxbuf->hmap, mh, hseg, &nsegs, BUS_DMA_NOWAIT);  
                         if (error != 0) {  
                                 printf("GET BUF: dmamap load"  
                                     " failure - %d\n", error);  
                                 m_free(mh);  
                                 goto update;  
                         }  
                         rxbuf->m_head = mh;  
                         bus_dmamap_sync(rxr->htag, rxbuf->hmap,  
                             BUS_DMASYNC_PREREAD);  
                         rxr->rx_base[i].read.hdr_addr =  
                             htole64(hseg[0].ds_addr);  
                 }  
   
                 if (rxbuf->m_pack == NULL) {  
                         mp = m_getjcl(M_DONTWAIT, MT_DATA,  
                             M_PKTHDR, adapter->rx_mbuf_sz);  
                         if (mp == NULL)  
                                 goto update;  
                         mp->m_pkthdr.len = mp->m_len = adapter->rx_mbuf_sz;  
                         /* Get the memory mapping */  
                         error = bus_dmamap_load_mbuf_sg(rxr->ptag,  
                             rxbuf->pmap, mp, pseg, &nsegs, BUS_DMA_NOWAIT);  
                         if (error != 0) {  
                                 printf("GET BUF: dmamap load"  
                                     " failure - %d\n", error);  
                                 m_free(mp);  
                                 goto update;  
                         }  
                         rxbuf->m_pack = mp;  
                         bus_dmamap_sync(rxr->ptag, rxbuf->pmap,  
                             BUS_DMASYNC_PREREAD);  
                         rxr->rx_base[i].read.pkt_addr =  
                             htole64(pseg[0].ds_addr);  
                 }  
   
                 cleaned = i;  
                 /* Calculate next index */  
                 if (++i == adapter->num_rx_desc)  
                         i = 0;  
                 /* This is the work marker for refresh */  
                 rxr->next_to_refresh = i;  
         }  
 update:  
         if (cleaned != -1) /* If we refreshed some, bump tail */  
                 IXGBE_WRITE_REG(&adapter->hw,  
                     IXGBE_VFRDT(rxr->me), cleaned);  
         return;  
 }  
   
 /*********************************************************************  
  *  
  *  Allocate memory for rx_buffer structures. Since we use one  
  *  rx_buffer per received packet, the maximum number of rx_buffer's  
  *  that we'll need is equal to the number of receive descriptors  
  *  that we've allocated.  
  *  
  **********************************************************************/  
 static int  
 ixv_allocate_receive_buffers(struct rx_ring *rxr)  
 {  
         struct  adapter         *adapter = rxr->adapter;  
         device_t                dev = adapter->dev;  
         struct ixv_rx_buf       *rxbuf;  
         int                     i, bsize, error;  
   
         bsize = sizeof(struct ixv_rx_buf) * adapter->num_rx_desc;  
         if (!(rxr->rx_buffers =  
             (struct ixv_rx_buf *) malloc(bsize,  
             M_DEVBUF, M_NOWAIT | M_ZERO))) {  
                 device_printf(dev, "Unable to allocate rx_buffer memory\n");  
                 error = ENOMEM;  
                 goto fail;  
         }  
   
         if ((error = bus_dma_tag_create(bus_get_dma_tag(dev),   /* parent */  
                                    1, 0,        /* alignment, bounds */  
                                    BUS_SPACE_MAXADDR,   /* lowaddr */  
                                    BUS_SPACE_MAXADDR,   /* highaddr */  
                                    NULL, NULL,          /* filter, filterarg */  
                                    MSIZE,               /* maxsize */  
                                    1,                   /* nsegments */  
                                    MSIZE,               /* maxsegsize */  
                                    0,                   /* flags */  
                                    NULL,                /* lockfunc */  
                                    NULL,                /* lockfuncarg */  
                                    &rxr->htag))) {  
                 device_printf(dev, "Unable to create RX DMA tag\n");  
                 goto fail;  
         }  
   
         if ((error = bus_dma_tag_create(bus_get_dma_tag(dev),   /* parent */  
                                    1, 0,        /* alignment, bounds */  
                                    BUS_SPACE_MAXADDR,   /* lowaddr */  
                                    BUS_SPACE_MAXADDR,   /* highaddr */  
                                    NULL, NULL,          /* filter, filterarg */  
                                    MJUMPAGESIZE,        /* maxsize */  
                                    1,                   /* nsegments */  
                                    MJUMPAGESIZE,        /* maxsegsize */  
                                    0,                   /* flags */  
                                    NULL,                /* lockfunc */  
                                    NULL,                /* lockfuncarg */  
                                    &rxr->ptag))) {  
                 device_printf(dev, "Unable to create RX DMA tag\n");  
                 goto fail;  
         }  
   
         for (i = 0; i < adapter->num_rx_desc; i++, rxbuf++) {  
                 rxbuf = &rxr->rx_buffers[i];  
                 error = bus_dmamap_create(rxr->htag,  
                     BUS_DMA_NOWAIT, &rxbuf->hmap);  
                 if (error) {  
                         device_printf(dev, "Unable to create RX head map\n");  
                         goto fail;  
                 }  
                 error = bus_dmamap_create(rxr->ptag,  
                     BUS_DMA_NOWAIT, &rxbuf->pmap);  
                 if (error) {  
                         device_printf(dev, "Unable to create RX pkt map\n");  
                         goto fail;  
                 }  
         }  
   
         return (0);  
   
 fail:          if (hw->mac.ops.check_link)
         /* Frees all, but can handle partial completion */                  hw->mac.ops.check_link(hw, &autoneg,
         ixv_free_receive_structures(adapter);                      &adapter->link_up, FALSE);
         return (error);  
 }  
   
 static void  
 ixv_free_receive_ring(struct rx_ring *rxr)  
 {  
         struct  adapter         *adapter;  
         struct ixv_rx_buf       *rxbuf;  
         int i;  
   
         adapter = rxr->adapter;  
         for (i = 0; i < adapter->num_rx_desc; i++) {  
                 rxbuf = &rxr->rx_buffers[i];  
                 if (rxbuf->m_head != NULL) {  
                         bus_dmamap_sync(rxr->htag, rxbuf->hmap,  
                             BUS_DMASYNC_POSTREAD);  
                         bus_dmamap_unload(rxr->htag, rxbuf->hmap);  
                         rxbuf->m_head->m_flags |= M_PKTHDR;  
                         m_freem(rxbuf->m_head);  
                 }  
                 if (rxbuf->m_pack != NULL) {  
                         bus_dmamap_sync(rxr->ptag, rxbuf->pmap,  
                             BUS_DMASYNC_POSTREAD);  
                         bus_dmamap_unload(rxr->ptag, rxbuf->pmap);  
                         rxbuf->m_pack->m_flags |= M_PKTHDR;  
                         m_freem(rxbuf->m_pack);  
                 }  
                 rxbuf->m_head = NULL;  
                 rxbuf->m_pack = NULL;  
         }  
 }  }
   
   
 /*********************************************************************  /*********************************************************************
  *   *
  *  Initialize a receive ring and its buffers.   *  Enable transmit unit.
  *   *
  **********************************************************************/   **********************************************************************/
 static int  static void
 ixv_setup_receive_ring(struct rx_ring *rxr)  ixv_initialize_transmit_units(struct adapter *adapter)
 {  {
         struct  adapter         *adapter;          struct tx_ring  *txr = adapter->tx_rings;
         struct ifnet            *ifp;          struct ixgbe_hw *hw = &adapter->hw;
         device_t                dev;  
         struct ixv_rx_buf       *rxbuf;  
         bus_dma_segment_t       pseg[1], hseg[1];  
         struct lro_ctrl         *lro = &rxr->lro;  
         int                     rsize, nsegs, error = 0;  
   
         adapter = rxr->adapter;  
         ifp = adapter->ifp;  
         dev = adapter->dev;  
   
         /* Clear the ring contents */          for (int i = 0; i < adapter->num_queues; i++, txr++) {
         IXV_RX_LOCK(rxr);                  u64     tdba = txr->txdma.dma_paddr;
         rsize = roundup2(adapter->num_rx_desc *                  u32     txctrl, txdctl;
             sizeof(union ixgbe_adv_rx_desc), DBA_ALIGN);  
         bzero((void *)rxr->rx_base, rsize);  
   
         /* Free current RX buffer structs and their mbufs */  
         ixv_free_receive_ring(rxr);  
   
         /* Configure header split? */  
         if (ixv_header_split)  
                 rxr->hdr_split = TRUE;  
   
         /* Now replenish the mbufs */  
         for (int j = 0; j != adapter->num_rx_desc; ++j) {  
                 struct mbuf     *mh, *mp;  
   
                 rxbuf = &rxr->rx_buffers[j];                  /* Set WTHRESH to 8, burst writeback */
                 /*                  txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i));
                 ** Dont allocate mbufs if not                  txdctl |= (8 << 16);
                 ** doing header split, its wasteful                  IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(i), txdctl);
                 */  
                 if (rxr->hdr_split == FALSE)  
                         goto skip_head;  
   
                 /* First the header */  
                 rxbuf->m_head = m_gethdr(M_NOWAIT, MT_DATA);  
                 if (rxbuf->m_head == NULL) {  
                         error = ENOBUFS;  
                         goto fail;  
                 }  
                 m_adj(rxbuf->m_head, ETHER_ALIGN);  
                 mh = rxbuf->m_head;  
                 mh->m_len = mh->m_pkthdr.len = MHLEN;  
                 mh->m_flags |= M_PKTHDR;  
                 /* Get the memory mapping */  
                 error = bus_dmamap_load_mbuf_sg(rxr->htag,  
                     rxbuf->hmap, rxbuf->m_head, hseg,  
                     &nsegs, BUS_DMA_NOWAIT);  
                 if (error != 0) /* Nothing elegant to do here */  
                         goto fail;  
                 bus_dmamap_sync(rxr->htag,  
                     rxbuf->hmap, BUS_DMASYNC_PREREAD);  
                 /* Update descriptor */  
                 rxr->rx_base[j].read.hdr_addr = htole64(hseg[0].ds_addr);  
   
 skip_head:  
                 /* Now the payload cluster */  
                 rxbuf->m_pack = m_getjcl(M_NOWAIT, MT_DATA,  
                     M_PKTHDR, adapter->rx_mbuf_sz);  
                 if (rxbuf->m_pack == NULL) {  
                         error = ENOBUFS;  
                         goto fail;  
                 }  
                 mp = rxbuf->m_pack;  
                 mp->m_pkthdr.len = mp->m_len = adapter->rx_mbuf_sz;  
                 /* Get the memory mapping */  
                 error = bus_dmamap_load_mbuf_sg(rxr->ptag,  
                     rxbuf->pmap, mp, pseg,  
                     &nsegs, BUS_DMA_NOWAIT);  
                 if (error != 0)  
                         goto fail;  
                 bus_dmamap_sync(rxr->ptag,  
                     rxbuf->pmap, BUS_DMASYNC_PREREAD);  
                 /* Update descriptor */  
                 rxr->rx_base[j].read.pkt_addr = htole64(pseg[0].ds_addr);  
         }  
   
                   /* Set the HW Tx Head and Tail indices */
                   IXGBE_WRITE_REG(&adapter->hw, IXGBE_VFTDH(i), 0);
                   IXGBE_WRITE_REG(&adapter->hw, IXGBE_VFTDT(i), 0);
   
         /* Setup our descriptor indices */                  /* Set Tx Tail register */
         rxr->next_to_check = 0;                  txr->tail = IXGBE_VFTDT(i);
         rxr->next_to_refresh = 0;  
         rxr->lro_enabled = FALSE;  
         rxr->rx_split_packets = 0;  
         rxr->rx_bytes = 0;  
   
         bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,                  /* Set Ring parameters */
             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);                  IXGBE_WRITE_REG(hw, IXGBE_VFTDBAL(i),
                          (tdba & 0x00000000ffffffffULL));
                   IXGBE_WRITE_REG(hw, IXGBE_VFTDBAH(i), (tdba >> 32));
                   IXGBE_WRITE_REG(hw, IXGBE_VFTDLEN(i),
                       adapter->num_tx_desc *
                       sizeof(struct ixgbe_legacy_tx_desc));
                   txctrl = IXGBE_READ_REG(hw, IXGBE_VFDCA_TXCTRL(i));
                   txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
                   IXGBE_WRITE_REG(hw, IXGBE_VFDCA_TXCTRL(i), txctrl);
   
         /*                  /* Now enable */
         ** Now set up the LRO interface:                  txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i));
         */                  txdctl |= IXGBE_TXDCTL_ENABLE;
         if (ifp->if_capenable & IFCAP_LRO) {                  IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(i), txdctl);
                 int err = tcp_lro_init(lro);  
                 if (err) {  
                         device_printf(dev, "LRO Initialization failed!\n");  
                         goto fail;  
                 }  
                 INIT_DEBUGOUT("RX Soft LRO Initialized\n");  
                 rxr->lro_enabled = TRUE;  
                 lro->ifp = adapter->ifp;  
         }          }
   
         IXV_RX_UNLOCK(rxr);          return;
         return (0);  
   
 fail:  
         ixv_free_receive_ring(rxr);  
         IXV_RX_UNLOCK(rxr);  
         return (error);  
 }  }
   
 /*********************************************************************  
  *  
  *  Initialize all receive rings.  
  *  
  **********************************************************************/  
 static int  
 ixv_setup_receive_structures(struct adapter *adapter)  
 {  
         struct rx_ring *rxr = adapter->rx_rings;  
         int j;  
   
         for (j = 0; j < adapter->num_queues; j++, rxr++)  
                 if (ixv_setup_receive_ring(rxr))  
                         goto fail;  
   
         return (0);  
 fail:  
         /*  
          * Free RX buffers allocated so far, we will only handle  
          * the rings that completed, the failing case will have  
          * cleaned up for itself. 'j' failed, so its the terminus.  
          */  
         for (int i = 0; i < j; ++i) {  
                 rxr = &adapter->rx_rings[i];  
                 ixv_free_receive_ring(rxr);  
         }  
   
         return (ENOBUFS);  
 }  
   
 /*********************************************************************  /*********************************************************************
  *   *
Line 3008  ixv_initialize_receive_units(struct adap
Line 1739  ixv_initialize_receive_units(struct adap
 {  {
         struct  rx_ring *rxr = adapter->rx_rings;          struct  rx_ring *rxr = adapter->rx_rings;
         struct ixgbe_hw *hw = &adapter->hw;          struct ixgbe_hw *hw = &adapter->hw;
         struct ifnet   *ifp = adapter->ifp;          struct ifnet    *ifp = adapter->ifp;
         u32             bufsz, fctrl, rxcsum, hlreg;          u32             bufsz, rxcsum, psrtype;
   
   
         /* Enable broadcasts */          if (ifp->if_mtu > ETHERMTU)
         fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);  
         fctrl |= IXGBE_FCTRL_BAM;  
         fctrl |= IXGBE_FCTRL_DPF;  
         fctrl |= IXGBE_FCTRL_PMCF;  
         IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);  
   
         /* Set for Jumbo Frames? */  
         hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0);  
         if (ifp->if_mtu > ETHERMTU) {  
                 hlreg |= IXGBE_HLREG0_JUMBOEN;  
                 bufsz = 4096 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;                  bufsz = 4096 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
         } else {          else
                 hlreg &= ~IXGBE_HLREG0_JUMBOEN;  
                 bufsz = 2048 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;                  bufsz = 2048 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
         }  
         IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg);          psrtype = IXGBE_PSRTYPE_TCPHDR | IXGBE_PSRTYPE_UDPHDR |
               IXGBE_PSRTYPE_IPV4HDR | IXGBE_PSRTYPE_IPV6HDR |
               IXGBE_PSRTYPE_L2HDR;
   
           IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype);
   
           /* Tell PF our max_frame size */
           ixgbevf_rlpml_set_vf(hw, adapter->max_frame_size);
   
         for (int i = 0; i < adapter->num_queues; i++, rxr++) {          for (int i = 0; i < adapter->num_queues; i++, rxr++) {
                 u64 rdba = rxr->rxdma.dma_paddr;                  u64 rdba = rxr->rxdma.dma_paddr;
                 u32 reg, rxdctl;                  u32 reg, rxdctl;
   
                 /* Do the queue enabling first */                  /* Disable the queue */
                 rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i));                  rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i));
                 rxdctl |= IXGBE_RXDCTL_ENABLE;                  rxdctl &= ~IXGBE_RXDCTL_ENABLE;
                 IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), rxdctl);                  IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), rxdctl);
                 for (int k = 0; k < 10; k++) {                  for (int j = 0; j < 10; j++) {
                         if (IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)) &                          if (IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)) &
                             IXGBE_RXDCTL_ENABLE)                              IXGBE_RXDCTL_ENABLE)
                                 break;  
                         else  
                                 msec_delay(1);                                  msec_delay(1);
                           else
                                   break;
                 }                  }
                 wmb();                  wmb();
   
                 /* Setup the Base and Length of the Rx Descriptor Ring */                  /* Setup the Base and Length of the Rx Descriptor Ring */
                 IXGBE_WRITE_REG(hw, IXGBE_VFRDBAL(i),                  IXGBE_WRITE_REG(hw, IXGBE_VFRDBAL(i),
                     (rdba & 0x00000000ffffffffULL));                      (rdba & 0x00000000ffffffffULL));
Line 3055  ixv_initialize_receive_units(struct adap
Line 1780  ixv_initialize_receive_units(struct adap
                 IXGBE_WRITE_REG(hw, IXGBE_VFRDLEN(i),                  IXGBE_WRITE_REG(hw, IXGBE_VFRDLEN(i),
                     adapter->num_rx_desc * sizeof(union ixgbe_adv_rx_desc));                      adapter->num_rx_desc * sizeof(union ixgbe_adv_rx_desc));
   
                   /* Reset the ring indices */
                   IXGBE_WRITE_REG(hw, IXGBE_VFRDH(rxr->me), 0);
                   IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me), 0);
   
                 /* Set up the SRRCTL register */                  /* Set up the SRRCTL register */
                 reg = IXGBE_READ_REG(hw, IXGBE_VFSRRCTL(i));                  reg = IXGBE_READ_REG(hw, IXGBE_VFSRRCTL(i));
                 reg &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;                  reg &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
                 reg &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;                  reg &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
                 reg |= bufsz;                  reg |= bufsz;
                 if (rxr->hdr_split) {                  reg |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
                         /* Use a standard mbuf for the header */  
                         reg |= ((IXV_RX_HDR <<  
                             IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT)  
                             & IXGBE_SRRCTL_BSIZEHDR_MASK);  
                         reg |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;  
                 } else  
                         reg |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;  
                 IXGBE_WRITE_REG(hw, IXGBE_VFSRRCTL(i), reg);                  IXGBE_WRITE_REG(hw, IXGBE_VFSRRCTL(i), reg);
   
                 /* Setup the HW Rx Head and Tail Descriptor Pointers */                  /* Capture Rx Tail index */
                 IXGBE_WRITE_REG(hw, IXGBE_VFRDH(rxr->me), 0);                  rxr->tail = IXGBE_VFRDT(rxr->me);
                 IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me),  
                     adapter->num_rx_desc - 1);  
         }  
   
         rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);  
   
         if (ifp->if_capenable & IFCAP_RXCSUM)  
                 rxcsum |= IXGBE_RXCSUM_PCSD;  
   
         if (!(rxcsum & IXGBE_RXCSUM_PCSD))  
                 rxcsum |= IXGBE_RXCSUM_IPPCSE;  
   
         IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);  
   
         return;  
 }  
   
 /*********************************************************************  
  *  
  *  Free all receive rings.  
  *  
  **********************************************************************/  
 static void  
 ixv_free_receive_structures(struct adapter *adapter)  
 {  
         struct rx_ring *rxr = adapter->rx_rings;  
   
         for (int i = 0; i < adapter->num_queues; i++, rxr++) {  
                 struct lro_ctrl         *lro = &rxr->lro;  
                 ixv_free_receive_buffers(rxr);  
                 /* Free LRO memory */  
                 tcp_lro_free(lro);  
                 /* Free the ring memory as well */  
                 ixv_dma_free(adapter, &rxr->rxdma);  
         }  
   
         free(adapter->rx_rings, M_DEVBUF);  
 }  
   
   
 /*********************************************************************  
  *  
  *  Free receive ring data structures  
  *  
  **********************************************************************/  
 static void  
 ixv_free_receive_buffers(struct rx_ring *rxr)  
 {  
         struct adapter          *adapter = rxr->adapter;  
         struct ixv_rx_buf       *rxbuf;  
   
         INIT_DEBUGOUT("free_receive_structures: begin");  
   
         /* Cleanup any existing buffers */  
         if (rxr->rx_buffers != NULL) {  
                 for (int i = 0; i < adapter->num_rx_desc; i++) {  
                         rxbuf = &rxr->rx_buffers[i];  
                         if (rxbuf->m_head != NULL) {  
                                 bus_dmamap_sync(rxr->htag, rxbuf->hmap,  
                                     BUS_DMASYNC_POSTREAD);  
                                 bus_dmamap_unload(rxr->htag, rxbuf->hmap);  
                                 rxbuf->m_head->m_flags |= M_PKTHDR;  
                                 m_freem(rxbuf->m_head);  
                         }  
                         if (rxbuf->m_pack != NULL) {  
                                 bus_dmamap_sync(rxr->ptag, rxbuf->pmap,  
                                     BUS_DMASYNC_POSTREAD);  
                                 bus_dmamap_unload(rxr->ptag, rxbuf->pmap);  
                                 rxbuf->m_pack->m_flags |= M_PKTHDR;  
                                 m_freem(rxbuf->m_pack);  
                         }  
                         rxbuf->m_head = NULL;  
                         rxbuf->m_pack = NULL;  
                         if (rxbuf->hmap != NULL) {  
                                 bus_dmamap_destroy(rxr->htag, rxbuf->hmap);  
                                 rxbuf->hmap = NULL;  
                         }  
                         if (rxbuf->pmap != NULL) {  
                                 bus_dmamap_destroy(rxr->ptag, rxbuf->pmap);  
                                 rxbuf->pmap = NULL;  
                         }  
                 }  
                 if (rxr->rx_buffers != NULL) {  
                         free(rxr->rx_buffers, M_DEVBUF);  
                         rxr->rx_buffers = NULL;  
                 }  
         }  
   
         if (rxr->htag != NULL) {  
                 bus_dma_tag_destroy(rxr->htag);  
                 rxr->htag = NULL;  
         }  
         if (rxr->ptag != NULL) {  
                 bus_dma_tag_destroy(rxr->ptag);  
                 rxr->ptag = NULL;  
         }  
   
         return;  
 }  
   
 static __inline void  
 ixv_rx_input(struct rx_ring *rxr, struct ifnet *ifp, struct mbuf *m, u32 ptype)  
 {  
   
         /*  
          * ATM LRO is only for IPv4/TCP packets and TCP checksum of the packet  
          * should be computed by hardware. Also it should not have VLAN tag in  
          * ethernet header.  
          */  
         if (rxr->lro_enabled &&  
             (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 &&  
             (ptype & IXGBE_RXDADV_PKTTYPE_ETQF) == 0 &&  
             (ptype & (IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_TCP)) ==  
             (IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_TCP) &&  
             (m->m_pkthdr.csum_flags & (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) ==  
             (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) {  
                 /*  
                  * Send to the stack if:  
                  **  - LRO not enabled, or  
                  **  - no LRO resources, or  
                  **  - lro enqueue fails  
                  */  
                 if (rxr->lro.lro_cnt != 0)  
                         if (tcp_lro_rx(&rxr->lro, m, 0) == 0)  
                                 return;  
         }  
         (*ifp->if_input)(ifp, m);  
 }  
   
 static __inline void  
 ixv_rx_discard(struct rx_ring *rxr, int i)  
 {  
         struct adapter          *adapter = rxr->adapter;  
         struct ixv_rx_buf       *rbuf;  
         struct mbuf             *mh, *mp;  
   
         rbuf = &rxr->rx_buffers[i];  
         if (rbuf->fmp != NULL) /* Partial chain ? */  
                 m_freem(rbuf->fmp);  
   
         mh = rbuf->m_head;  
         mp = rbuf->m_pack;  
   
         /* Reuse loaded DMA map and just update mbuf chain */  
         mh->m_len = MHLEN;  
         mh->m_flags |= M_PKTHDR;  
         mh->m_next = NULL;  
   
         mp->m_len = mp->m_pkthdr.len = adapter->rx_mbuf_sz;  
         mp->m_data = mp->m_ext.ext_buf;  
         mp->m_next = NULL;  
         return;  
 }  
   
   
 /*********************************************************************  
  *  
  *  This routine executes in interrupt context. It replenishes  
  *  the mbufs in the descriptor and sends data which has been  
  *  dma'ed into host memory to upper layer.  
  *  
  *  We loop at most count times if count is > 0, or until done if  
  *  count < 0.  
  *  
  *  Return TRUE for more work, FALSE for all clean.  
  *********************************************************************/  
 static bool  
 ixv_rxeof(struct ix_queue *que, int count)  
 {  
         struct adapter          *adapter = que->adapter;  
         struct rx_ring          *rxr = que->rxr;  
         struct ifnet            *ifp = adapter->ifp;  
         struct lro_ctrl         *lro = &rxr->lro;  
         struct lro_entry        *queued;  
         int                     i, nextp, processed = 0;  
         u32                     staterr = 0;  
         union ixgbe_adv_rx_desc *cur;  
         struct ixv_rx_buf       *rbuf, *nbuf;  
   
         IXV_RX_LOCK(rxr);  
   
         for (i = rxr->next_to_check; count != 0;) {  
                 struct mbuf     *sendmp, *mh, *mp;  
                 u32             rsc, ptype;  
                 u16             hlen, plen, hdr, vtag;  
                 bool            eop;  
   
                 /* Sync the ring. */  
                 bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,  
                     BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);  
   
                 cur = &rxr->rx_base[i];  
                 staterr = le32toh(cur->wb.upper.status_error);  
   
                 if ((staterr & IXGBE_RXD_STAT_DD) == 0)                  /* Do the queue enabling last */
                         break;                  rxdctl |= IXGBE_RXDCTL_ENABLE | IXGBE_RXDCTL_VME;
                 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)                  IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), rxdctl);
                         break;                  for (int k = 0; k < 10; k++) {
                           if (IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)) &
                 count--;                              IXGBE_RXDCTL_ENABLE)
                 sendmp = NULL;                                  break;
                 nbuf = NULL;  
                 rsc = 0;  
                 cur->wb.upper.status_error = 0;  
                 rbuf = &rxr->rx_buffers[i];  
                 mh = rbuf->m_head;  
                 mp = rbuf->m_pack;  
   
                 plen = le16toh(cur->wb.upper.length);  
                 ptype = le32toh(cur->wb.lower.lo_dword.data) &  
                     IXGBE_RXDADV_PKTTYPE_MASK;  
                 hdr = le16toh(cur->wb.lower.lo_dword.hs_rss.hdr_info);  
                 vtag = le16toh(cur->wb.upper.vlan);  
                 eop = ((staterr & IXGBE_RXD_STAT_EOP) != 0);  
   
                 /* Make sure all parts of a bad packet are discarded */  
                 if (((staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) != 0) ||  
                     (rxr->discard)) {  
                         ifp->if_ierrors++;  
                         rxr->rx_discarded++;  
                         if (!eop)  
                                 rxr->discard = TRUE;  
                         else                          else
                                 rxr->discard = FALSE;                                  msec_delay(1);
                         ixv_rx_discard(rxr, i);  
                         goto next_desc;  
                 }                  }
                   wmb();
   
                 if (!eop) {                  /* Set the Tail Pointer */
                         nextp = i + 1;  #ifdef DEV_NETMAP
                         if (nextp == adapter->num_rx_desc)  
                                 nextp = 0;  
                         nbuf = &rxr->rx_buffers[nextp];  
                         prefetch(nbuf);  
                 }  
                 /*                  /*
                 ** The header mbuf is ONLY used when header                   * In netmap mode, we must preserve the buffers made
                 ** split is enabled, otherwise we get normal                   * available to userspace before the if_init()
                 ** behavior, ie, both header and payload                   * (this is true by default on the TX side, because
                 ** are DMA'd into the payload buffer.                   * init makes all buffers available to userspace).
                 **                   *
                 ** Rather than using the fmp/lmp global pointers                   * netmap_reset() and the device specific routines
                 ** we now keep the head of a packet chain in the                   * (e.g. ixgbe_setup_receive_rings()) map these
                 ** buffer struct and pass this along from one                   * buffers at the end of the NIC ring, so here we
                 ** descriptor to the next, until we get EOP.                   * must set the RDT (tail) register to make sure
                 */                   * they are not overwritten.
                 if (rxr->hdr_split && (rbuf->fmp == NULL)) {                   *
                         /* This must be an initial descriptor */                   * In this driver the NIC ring starts at RDH = 0,
                         hlen = (hdr & IXGBE_RXDADV_HDRBUFLEN_MASK) >>                   * RDT points to the last slot available for reception (?),
                             IXGBE_RXDADV_HDRBUFLEN_SHIFT;                   * so RDT = num_rx_desc - 1 means the whole ring is available.
                         if (hlen > IXV_RX_HDR)                   */
                                 hlen = IXV_RX_HDR;                  if (ifp->if_capenable & IFCAP_NETMAP) {
                         mh->m_len = hlen;                          struct netmap_adapter *na = NA(adapter->ifp);
                         mh->m_flags |= M_PKTHDR;                          struct netmap_kring *kring = &na->rx_rings[i];
                         mh->m_next = NULL;                          int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring);
                         mh->m_pkthdr.len = mh->m_len;  
                         /* Null buf pointer so it is refreshed */  
                         rbuf->m_head = NULL;  
                         /*  
                         ** Check the payload length, this  
                         ** could be zero if its a small  
                         ** packet.  
                         */  
                         if (plen > 0) {  
                                 mp->m_len = plen;  
                                 mp->m_next = NULL;  
                                 mp->m_flags &= ~M_PKTHDR;  
                                 mh->m_next = mp;  
                                 mh->m_pkthdr.len += mp->m_len;  
                                 /* Null buf pointer so it is refreshed */  
                                 rbuf->m_pack = NULL;  
                                 rxr->rx_split_packets++;  
                         }  
                         /*  
                         ** Now create the forward  
                         ** chain so when complete  
                         ** we wont have to.  
                         */  
                         if (eop == 0) {  
                                 /* stash the chain head */  
                                 nbuf->fmp = mh;  
                                 /* Make forward chain */  
                                 if (plen)  
                                         mp->m_next = nbuf->m_pack;  
                                 else  
                                         mh->m_next = nbuf->m_pack;  
                         } else {  
                                 /* Singlet, prepare to send */  
                                 sendmp = mh;  
                                 if (staterr & IXGBE_RXD_STAT_VP) {  
                                         sendmp->m_pkthdr.ether_vtag = vtag;  
                                         sendmp->m_flags |= M_VLANTAG;  
                                 }  
                         }  
                 } else {  
                         /*  
                         ** Either no header split, or a  
                         ** secondary piece of a fragmented  
                         ** split packet.  
                         */  
                         mp->m_len = plen;  
                         /*  
                         ** See if there is a stored head  
                         ** that determines what we are  
                         */  
                         sendmp = rbuf->fmp;  
                         rbuf->m_pack = rbuf->fmp = NULL;  
   
                         if (sendmp != NULL) /* secondary frag */  
                                 sendmp->m_pkthdr.len += mp->m_len;  
                         else {  
                                 /* first desc of a non-ps chain */  
                                 sendmp = mp;  
                                 sendmp->m_flags |= M_PKTHDR;  
                                 sendmp->m_pkthdr.len = mp->m_len;  
                                 if (staterr & IXGBE_RXD_STAT_VP) {  
                                         sendmp->m_pkthdr.ether_vtag = vtag;  
                                         sendmp->m_flags |= M_VLANTAG;  
                                 }  
                         }  
                         /* Pass the head pointer on */  
                         if (eop == 0) {  
                                 nbuf->fmp = sendmp;  
                                 sendmp = NULL;  
                                 mp->m_next = nbuf->m_pack;  
                         }  
                 }  
                 ++processed;  
                 /* Sending this frame? */  
                 if (eop) {  
                         sendmp->m_pkthdr.rcvif = ifp;  
                         ifp->if_ipackets++;  
                         rxr->rx_packets++;  
                         /* capture data for AIM */  
                         rxr->bytes += sendmp->m_pkthdr.len;  
                         rxr->rx_bytes += sendmp->m_pkthdr.len;  
                         if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)  
                                 ixv_rx_checksum(staterr, sendmp, ptype);  
 #if __FreeBSD_version >= 800000  
                         sendmp->m_pkthdr.flowid = que->msix;  
                         sendmp->m_flags |= M_FLOWID;  
 #endif  
                 }  
 next_desc:  
                 bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,  
                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);  
   
                 /* Advance our pointers to the next descriptor. */  
                 if (++i == adapter->num_rx_desc)  
                         i = 0;  
   
                 /* Now send to the stack or do LRO */  
                 if (sendmp != NULL)  
                         ixv_rx_input(rxr, ifp, sendmp, ptype);  
   
                /* Every 8 descriptors we go to refresh mbufs */  
                 if (processed == 8) {  
                         ixv_refresh_mbufs(rxr, i);  
                         processed = 0;  
                 }  
         }  
   
         /* Refresh any remaining buf structs */  
         if (processed != 0) {  
                 ixv_refresh_mbufs(rxr, i);  
                 processed = 0;  
         }  
   
         rxr->next_to_check = i;  
   
         /*                          IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me), t);
          * Flush any outstanding LRO work                  } else
          */  #endif /* DEV_NETMAP */
         while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) {                          IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me),
                 SLIST_REMOVE_HEAD(&lro->lro_active, next);                              adapter->num_rx_desc - 1);
                 tcp_lro_flush(lro, queued);  
         }          }
   
         IXV_RX_UNLOCK(rxr);          rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
   
         /*  
         ** We still have cleaning to do?  
         ** Schedule another interrupt if so.  
         */  
         if ((staterr & IXGBE_RXD_STAT_DD) != 0) {  
                 ixv_rearm_queues(adapter, (u64)(1 << que->msix));  
                 return (TRUE);  
         }  
   
         return (FALSE);          if (ifp->if_capenable & IFCAP_RXCSUM)
 }                  rxcsum |= IXGBE_RXCSUM_PCSD;
   
           if (!(rxcsum & IXGBE_RXCSUM_PCSD))
                   rxcsum |= IXGBE_RXCSUM_IPPCSE;
   
 /*********************************************************************          IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
  *  
  *  Verify that the hardware indicated that the checksum is valid.  
  *  Inform the stack about the status of checksum so that stack  
  *  doesn't spend time verifying the checksum.  
  *  
  *********************************************************************/  
 static void  
 ixv_rx_checksum(u32 staterr, struct mbuf * mp, u32 ptype)  
 {  
         u16     status = (u16) staterr;  
         u8      errors = (u8) (staterr >> 24);  
         bool    sctp = FALSE;  
   
         if ((ptype & IXGBE_RXDADV_PKTTYPE_ETQF) == 0 &&  
             (ptype & IXGBE_RXDADV_PKTTYPE_SCTP) != 0)  
                 sctp = TRUE;  
   
         if (status & IXGBE_RXD_STAT_IPCS) {  
                 if (!(errors & IXGBE_RXD_ERR_IPE)) {  
                         /* IP Checksum Good */  
                         mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED;  
                         mp->m_pkthdr.csum_flags |= CSUM_IP_VALID;  
   
                 } else  
                         mp->m_pkthdr.csum_flags = 0;  
         }  
         if (status & IXGBE_RXD_STAT_L4CS) {  
                 u16 type = (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);  
 #if __FreeBSD_version >= 800000  
                 if (sctp)  
                         type = CSUM_SCTP_VALID;  
 #endif  
                 if (!(errors & IXGBE_RXD_ERR_TCPE)) {  
                         mp->m_pkthdr.csum_flags |= type;  
                         if (!sctp)  
                                 mp->m_pkthdr.csum_data = htons(0xffff);  
                 }  
         }  
         return;          return;
 }  }
   
Line 3512  ixv_setup_vlan_support(struct adapter *a
Line 1855  ixv_setup_vlan_support(struct adapter *a
 {  {
         struct ixgbe_hw *hw = &adapter->hw;          struct ixgbe_hw *hw = &adapter->hw;
         u32             ctrl, vid, vfta, retry;          u32             ctrl, vid, vfta, retry;
           struct rx_ring  *rxr;
   
         /*          /*
         ** We get here thru init_locked, meaning          ** We get here thru init_locked, meaning
Line 3520  ixv_setup_vlan_support(struct adapter *a
Line 1863  ixv_setup_vlan_support(struct adapter *a
         ** the VFTA and other state, so if there          ** the VFTA and other state, so if there
         ** have been no vlan's registered do nothing.          ** have been no vlan's registered do nothing.
         */          */
         if (adapter->num_vlans == 0)          if (!VLAN_ATTACHED(&adapter->osdep.ec))
                 return;                  return;
   
         /* Enable the queues */          /* Enable the queues */
Line 3528  ixv_setup_vlan_support(struct adapter *a
Line 1871  ixv_setup_vlan_support(struct adapter *a
                 ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i));                  ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i));
                 ctrl |= IXGBE_RXDCTL_VME;                  ctrl |= IXGBE_RXDCTL_VME;
                 IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), ctrl);                  IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), ctrl);
                   /*
                    * Let Rx path know that it needs to store VLAN tag
                    * as part of extra mbuf info.
                    */
                   rxr = &adapter->rx_rings[i];
                   rxr->vtag_strip = TRUE;
         }          }
   
         /*          /*
         ** A soft reset zero's out the VFTA, so          ** A soft reset zero's out the VFTA, so
         ** we need to repopulate it now.          ** we need to repopulate it now.
         */          */
         for (int i = 0; i < VFTA_SIZE; i++) {          for (int i = 0; i < IXGBE_VFTA_SIZE; i++) {
                 if (ixv_shadow_vfta[i] == 0)                  if (ixv_shadow_vfta[i] == 0)
                         continue;                          continue;
                 vfta = ixv_shadow_vfta[i];                  vfta = ixv_shadow_vfta[i];
Line 3543  ixv_setup_vlan_support(struct adapter *a
Line 1892  ixv_setup_vlan_support(struct adapter *a
                 ** based on the bits set in each                  ** based on the bits set in each
                 ** of the array ints.                  ** of the array ints.
                 */                  */
                 for ( int j = 0; j < 32; j++) {                  for (int j = 0; j < 32; j++) {
                         retry = 0;                          retry = 0;
                         if ((vfta & (1 << j)) == 0)                          if ((vfta & (1 << j)) == 0)
                                 continue;                                  continue;
Line 3557  ixv_setup_vlan_support(struct adapter *a
Line 1906  ixv_setup_vlan_support(struct adapter *a
         }          }
 }  }
   
   #if 0   /* XXX Badly need to overhaul vlan(4) on NetBSD. */
 /*  /*
 ** This routine is run via an vlan config EVENT,  ** This routine is run via an vlan config EVENT,
 ** it enables us to use the HW Filter table since  ** it enables us to use the HW Filter table since
Line 3570  ixv_register_vlan(void *arg, struct ifne
Line 1920  ixv_register_vlan(void *arg, struct ifne
         struct adapter  *adapter = ifp->if_softc;          struct adapter  *adapter = ifp->if_softc;
         u16             index, bit;          u16             index, bit;
   
         if (ifp->if_softc !=  arg)   /* Not our event */          if (ifp->if_softc != arg) /* Not our event */
                 return;                  return;
   
         if ((vtag == 0) || (vtag > 4095))       /* Invalid */          if ((vtag == 0) || (vtag > 4095)) /* Invalid */
                 return;                  return;
   
           IXGBE_CORE_LOCK(adapter);
         index = (vtag >> 5) & 0x7F;          index = (vtag >> 5) & 0x7F;
         bit = vtag & 0x1F;          bit = vtag & 0x1F;
         ixv_shadow_vfta[index] |= (1 << bit);          ixv_shadow_vfta[index] |= (1 << bit);
         ++adapter->num_vlans;  
         /* Re-init to load the changes */          /* Re-init to load the changes */
         ixv_init(adapter);          ixv_init_locked(adapter);
           IXGBE_CORE_UNLOCK(adapter);
 }  }
   
 /*  /*
Line 3601  ixv_unregister_vlan(void *arg, struct if
Line 1952  ixv_unregister_vlan(void *arg, struct if
         if ((vtag == 0) || (vtag > 4095))       /* Invalid */          if ((vtag == 0) || (vtag > 4095))       /* Invalid */
                 return;                  return;
   
           IXGBE_CORE_LOCK(adapter);
         index = (vtag >> 5) & 0x7F;          index = (vtag >> 5) & 0x7F;
         bit = vtag & 0x1F;          bit = vtag & 0x1F;
         ixv_shadow_vfta[index] &= ~(1 << bit);          ixv_shadow_vfta[index] &= ~(1 << bit);
         --adapter->num_vlans;  
         /* Re-init to load the changes */          /* Re-init to load the changes */
         ixv_init(adapter);          ixv_init_locked(adapter);
           IXGBE_CORE_UNLOCK(adapter);
 }  }
   #endif
   
 static void  static void
 ixv_enable_intr(struct adapter *adapter)  ixv_enable_intr(struct adapter *adapter)
Line 3683  ixv_configure_ivars(struct adapter *adap
Line 2036  ixv_configure_ivars(struct adapter *adap
                     IXGBE_VTEITR(que->msix), IXV_EITR_DEFAULT);                      IXGBE_VTEITR(que->msix), IXV_EITR_DEFAULT);
         }          }
   
         /* For the Link interrupt */          /* For the mailbox interrupt */
         ixv_set_ivar(adapter, 1, adapter->mbxvec, -1);          ixv_set_ivar(adapter, 1, adapter->vector, -1);
 }  }
   
   
Line 3703  ixv_handle_mbx(void *context)
Line 2056  ixv_handle_mbx(void *context)
 }  }
   
 /*  /*
 ** The VF stats registers never have a truely virgin  ** The VF stats registers never have a truly virgin
 ** starting point, so this routine tries to make an  ** starting point, so this routine tries to make an
 ** artificial one, marking ground zero on attach as  ** artificial one, marking ground zero on attach as
 ** it were.  ** it were.
Line 3711  ixv_handle_mbx(void *context)
Line 2064  ixv_handle_mbx(void *context)
 static void  static void
 ixv_save_stats(struct adapter *adapter)  ixv_save_stats(struct adapter *adapter)
 {  {
         if (adapter->stats.vfgprc || adapter->stats.vfgptc) {          struct ixgbevf_hw_stats *stats = &adapter->stats.vf;
                 adapter->stats.saved_reset_vfgprc +=  
                     adapter->stats.vfgprc - adapter->stats.base_vfgprc;          if (stats->vfgprc.ev_count || stats->vfgptc.ev_count) {
                 adapter->stats.saved_reset_vfgptc +=                  stats->saved_reset_vfgprc +=
                     adapter->stats.vfgptc - adapter->stats.base_vfgptc;                      stats->vfgprc.ev_count - stats->base_vfgprc;
                 adapter->stats.saved_reset_vfgorc +=                  stats->saved_reset_vfgptc +=
                     adapter->stats.vfgorc - adapter->stats.base_vfgorc;                      stats->vfgptc.ev_count - stats->base_vfgptc;
                 adapter->stats.saved_reset_vfgotc +=                  stats->saved_reset_vfgorc +=
                     adapter->stats.vfgotc - adapter->stats.base_vfgotc;                      stats->vfgorc.ev_count - stats->base_vfgorc;
                 adapter->stats.saved_reset_vfmprc +=                  stats->saved_reset_vfgotc +=
                     adapter->stats.vfmprc - adapter->stats.base_vfmprc;                      stats->vfgotc.ev_count - stats->base_vfgotc;
                   stats->saved_reset_vfmprc +=
                       stats->vfmprc.ev_count - stats->base_vfmprc;
         }          }
 }  }
   
Line 3730  ixv_init_stats(struct adapter *adapter)
Line 2085  ixv_init_stats(struct adapter *adapter)
 {  {
         struct ixgbe_hw *hw = &adapter->hw;          struct ixgbe_hw *hw = &adapter->hw;
   
         adapter->stats.last_vfgprc = IXGBE_READ_REG(hw, IXGBE_VFGPRC);          adapter->stats.vf.last_vfgprc = IXGBE_READ_REG(hw, IXGBE_VFGPRC);
         adapter->stats.last_vfgorc = IXGBE_READ_REG(hw, IXGBE_VFGORC_LSB);          adapter->stats.vf.last_vfgorc = IXGBE_READ_REG(hw, IXGBE_VFGORC_LSB);
         adapter->stats.last_vfgorc |=          adapter->stats.vf.last_vfgorc |=
             (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGORC_MSB))) << 32);              (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGORC_MSB))) << 32);
   
         adapter->stats.last_vfgptc = IXGBE_READ_REG(hw, IXGBE_VFGPTC);          adapter->stats.vf.last_vfgptc = IXGBE_READ_REG(hw, IXGBE_VFGPTC);
         adapter->stats.last_vfgotc = IXGBE_READ_REG(hw, IXGBE_VFGOTC_LSB);          adapter->stats.vf.last_vfgotc = IXGBE_READ_REG(hw, IXGBE_VFGOTC_LSB);
         adapter->stats.last_vfgotc |=          adapter->stats.vf.last_vfgotc |=
             (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGOTC_MSB))) << 32);              (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGOTC_MSB))) << 32);
   
         adapter->stats.last_vfmprc = IXGBE_READ_REG(hw, IXGBE_VFMPRC);          adapter->stats.vf.last_vfmprc = IXGBE_READ_REG(hw, IXGBE_VFMPRC);
   
         adapter->stats.base_vfgprc = adapter->stats.last_vfgprc;          adapter->stats.vf.base_vfgprc = adapter->stats.vf.last_vfgprc;
         adapter->stats.base_vfgorc = adapter->stats.last_vfgorc;          adapter->stats.vf.base_vfgorc = adapter->stats.vf.last_vfgorc;
         adapter->stats.base_vfgptc = adapter->stats.last_vfgptc;          adapter->stats.vf.base_vfgptc = adapter->stats.vf.last_vfgptc;
         adapter->stats.base_vfgotc = adapter->stats.last_vfgotc;          adapter->stats.vf.base_vfgotc = adapter->stats.vf.last_vfgotc;
         adapter->stats.base_vfmprc = adapter->stats.last_vfmprc;          adapter->stats.vf.base_vfmprc = adapter->stats.vf.last_vfmprc;
 }  }
   
 #define UPDATE_STAT_32(reg, last, count)                \  #define UPDATE_STAT_32(reg, last, count)                \
 {                                                       \  {                                                       \
         u32 current = IXGBE_READ_REG(hw, reg);          \          u32 current = IXGBE_READ_REG(hw, reg);          \
         if (current < last)                             \          if (current < last)                             \
                 count += 0x100000000LL;                 \                  count.ev_count += 0x100000000LL;        \
         last = current;                                 \          last = current;                                 \
         count &= 0xFFFFFFFF00000000LL;                  \          count.ev_count &= 0xFFFFFFFF00000000LL;         \
         count |= current;                               \          count.ev_count |= current;                      \
 }  }
   
 #define UPDATE_STAT_36(lsb, msb, last, count)           \  #define UPDATE_STAT_36(lsb, msb, last, count)           \
Line 3765  ixv_init_stats(struct adapter *adapter)
Line 2120  ixv_init_stats(struct adapter *adapter)
         u64 cur_msb = IXGBE_READ_REG(hw, msb);          \          u64 cur_msb = IXGBE_READ_REG(hw, msb);          \
         u64 current = ((cur_msb << 32) | cur_lsb);      \          u64 current = ((cur_msb << 32) | cur_lsb);      \
         if (current < last)                             \          if (current < last)                             \
                 count += 0x1000000000LL;                \                  count.ev_count += 0x1000000000LL;       \
         last = current;                                 \          last = current;                                 \
         count &= 0xFFFFFFF000000000LL;                  \          count.ev_count &= 0xFFFFFFF000000000LL;         \
         count |= current;                               \          count.ev_count |= current;                      \
 }  }
   
 /*  /*
Line 3779  ixv_update_stats(struct adapter *adapter
Line 2134  ixv_update_stats(struct adapter *adapter
 {  {
         struct ixgbe_hw *hw = &adapter->hw;          struct ixgbe_hw *hw = &adapter->hw;
   
         UPDATE_STAT_32(IXGBE_VFGPRC, adapter->stats.last_vfgprc,          UPDATE_STAT_32(IXGBE_VFGPRC, adapter->stats.vf.last_vfgprc,
             adapter->stats.vfgprc);              adapter->stats.vf.vfgprc);
         UPDATE_STAT_32(IXGBE_VFGPTC, adapter->stats.last_vfgptc,          UPDATE_STAT_32(IXGBE_VFGPTC, adapter->stats.vf.last_vfgptc,
             adapter->stats.vfgptc);              adapter->stats.vf.vfgptc);
         UPDATE_STAT_36(IXGBE_VFGORC_LSB, IXGBE_VFGORC_MSB,          UPDATE_STAT_36(IXGBE_VFGORC_LSB, IXGBE_VFGORC_MSB,
             adapter->stats.last_vfgorc, adapter->stats.vfgorc);              adapter->stats.vf.last_vfgorc, adapter->stats.vf.vfgorc);
         UPDATE_STAT_36(IXGBE_VFGOTC_LSB, IXGBE_VFGOTC_MSB,          UPDATE_STAT_36(IXGBE_VFGOTC_LSB, IXGBE_VFGOTC_MSB,
             adapter->stats.last_vfgotc, adapter->stats.vfgotc);              adapter->stats.vf.last_vfgotc, adapter->stats.vf.vfgotc);
         UPDATE_STAT_32(IXGBE_VFMPRC, adapter->stats.last_vfmprc,          UPDATE_STAT_32(IXGBE_VFMPRC, adapter->stats.vf.last_vfmprc,
             adapter->stats.vfmprc);              adapter->stats.vf.vfmprc);
 }  }
   
 /**********************************************************************  /*
  *   * Add statistic sysctls for the VF.
  *  This routine is called only when ixgbe_display_debug_stats is enabled.   */
  *  This routine provides a way to take a look at important statistics  
  *  maintained by the driver and hardware.  
  *  
  **********************************************************************/  
 static void  static void
 ixv_print_hw_stats(struct adapter * adapter)  ixv_add_stats_sysctls(struct adapter *adapter)
 {  {
         device_t dev = adapter->dev;          device_t dev = adapter->dev;
           struct ix_queue *que = &adapter->queues[0];
         device_printf(dev,"Std Mbuf Failed = %lu\n",          struct tx_ring *txr = que->txr;
                adapter->mbuf_defrag_failed);          struct rx_ring *rxr = que->rxr;
         device_printf(dev,"Driver dropped packets = %lu\n",  
                adapter->dropped_pkts);          struct ixgbevf_hw_stats *stats = &adapter->stats.vf;
         device_printf(dev, "watchdog timeouts = %ld\n",  
                adapter->watchdog_events);          const char *xname = device_xname(dev);
   
         device_printf(dev,"Good Packets Rcvd = %llu\n",          /* Driver Statistics */
                (long long)adapter->stats.vfgprc);          evcnt_attach_dynamic(&adapter->dropped_pkts, EVCNT_TYPE_MISC,
         device_printf(dev,"Good Packets Xmtd = %llu\n",              NULL, xname, "Driver dropped packets");
                (long long)adapter->stats.vfgptc);          evcnt_attach_dynamic(&adapter->mbuf_defrag_failed, EVCNT_TYPE_MISC,
         device_printf(dev,"TSO Transmissions = %lu\n",              NULL, xname, "m_defrag() failed");
                adapter->tso_tx);          evcnt_attach_dynamic(&adapter->watchdog_events, EVCNT_TYPE_MISC,
               NULL, xname, "Watchdog timeouts");
   
           evcnt_attach_dynamic(&stats->vfgprc, EVCNT_TYPE_MISC, NULL,
               xname, "Good Packets Received");
           evcnt_attach_dynamic(&stats->vfgorc, EVCNT_TYPE_MISC, NULL,
               xname, "Good Octets Received");
           evcnt_attach_dynamic(&stats->vfmprc, EVCNT_TYPE_MISC, NULL,
               xname, "Multicast Packets Received");
           evcnt_attach_dynamic(&stats->vfgptc, EVCNT_TYPE_MISC, NULL,
               xname, "Good Packets Transmitted");
           evcnt_attach_dynamic(&stats->vfgotc, EVCNT_TYPE_MISC, NULL,
               xname, "Good Octets Transmitted");
           evcnt_attach_dynamic(&que->irqs, EVCNT_TYPE_INTR, NULL,
               xname, "IRQs on queue");
           evcnt_attach_dynamic(&rxr->rx_irq, EVCNT_TYPE_INTR, NULL,
               xname, "RX irqs on queue");
           evcnt_attach_dynamic(&rxr->rx_packets, EVCNT_TYPE_MISC, NULL,
               xname, "RX packets");
           evcnt_attach_dynamic(&rxr->rx_bytes, EVCNT_TYPE_MISC, NULL,
               xname, "RX bytes");
           evcnt_attach_dynamic(&rxr->rx_discarded, EVCNT_TYPE_MISC, NULL,
               xname, "Discarded RX packets");
           evcnt_attach_dynamic(&txr->total_packets, EVCNT_TYPE_MISC, NULL,
               xname, "TX Packets");
           evcnt_attach_dynamic(&txr->no_desc_avail, EVCNT_TYPE_MISC, NULL,
               xname, "# of times not enough descriptors were available during TX");
           evcnt_attach_dynamic(&txr->tso_tx, EVCNT_TYPE_MISC, NULL,
               xname, "TX TSO");
   }
   
   static void
   ixv_set_sysctl_value(struct adapter *adapter, const char *name,
           const char *description, int *limit, int value)
   {
           device_t dev =  adapter->dev;
           struct sysctllog **log;
           const struct sysctlnode *rnode, *cnode;
   
           log = &adapter->sysctllog;
           if ((rnode = ixv_sysctl_instance(adapter)) == NULL) {
                   aprint_error_dev(dev, "could not create sysctl root\n");
                   return;
           }
           if (sysctl_createv(log, 0, &rnode, &cnode,
               CTLFLAG_READWRITE, CTLTYPE_INT,
               name, SYSCTL_DESCR(description),
               NULL, 0, limit, 0, CTL_CREATE, CTL_EOL) != 0)
                   aprint_error_dev(dev, "could not create sysctl\n");
           *limit = value;
 }  }
   
 /**********************************************************************  /**********************************************************************
Line 3834  ixv_print_debug_info(struct adapter *ada
Line 2233  ixv_print_debug_info(struct adapter *ada
         struct ix_queue         *que = adapter->queues;          struct ix_queue         *que = adapter->queues;
         struct rx_ring          *rxr;          struct rx_ring          *rxr;
         struct tx_ring          *txr;          struct tx_ring          *txr;
   #ifdef LRO
         struct lro_ctrl         *lro;          struct lro_ctrl         *lro;
   #endif /* LRO */
   
         device_printf(dev,"Error Byte Count = %u \n",          device_printf(dev,"Error Byte Count = %u \n",
             IXGBE_READ_REG(hw, IXGBE_ERRBC));              IXGBE_READ_REG(hw, IXGBE_ERRBC));
Line 3842  ixv_print_debug_info(struct adapter *ada
Line 2243  ixv_print_debug_info(struct adapter *ada
         for (int i = 0; i < adapter->num_queues; i++, que++) {          for (int i = 0; i < adapter->num_queues; i++, que++) {
                 txr = que->txr;                  txr = que->txr;
                 rxr = que->rxr;                  rxr = que->rxr;
   #ifdef LRO
                 lro = &rxr->lro;                  lro = &rxr->lro;
   #endif /* LRO */
                 device_printf(dev,"QUE(%d) IRQs Handled: %lu\n",                  device_printf(dev,"QUE(%d) IRQs Handled: %lu\n",
                     que->msix, (long)que->irqs);                      que->msix, (long)que->irqs.ev_count);
                 device_printf(dev,"RX(%d) Packets Received: %lld\n",                  device_printf(dev,"RX(%d) Packets Received: %lld\n",
                     rxr->me, (long long)rxr->rx_packets);                      rxr->me, (long long)rxr->rx_packets.ev_count);
                 device_printf(dev,"RX(%d) Split RX Packets: %lld\n",  
                     rxr->me, (long long)rxr->rx_split_packets);  
                 device_printf(dev,"RX(%d) Bytes Received: %lu\n",                  device_printf(dev,"RX(%d) Bytes Received: %lu\n",
                     rxr->me, (long)rxr->rx_bytes);                      rxr->me, (long)rxr->rx_bytes.ev_count);
                 device_printf(dev,"RX(%d) LRO Queued= %d\n",  #ifdef LRO
                     rxr->me, lro->lro_queued);                  device_printf(dev,"RX(%d) LRO Queued= %lld\n",
                 device_printf(dev,"RX(%d) LRO Flushed= %d\n",                      rxr->me, (long long)lro->lro_queued);
                     rxr->me, lro->lro_flushed);                  device_printf(dev,"RX(%d) LRO Flushed= %lld\n",
                       rxr->me, (long long)lro->lro_flushed);
   #endif /* LRO */
                 device_printf(dev,"TX(%d) Packets Sent: %lu\n",                  device_printf(dev,"TX(%d) Packets Sent: %lu\n",
                     txr->me, (long)txr->total_packets);                      txr->me, (long)txr->total_packets.ev_count);
                 device_printf(dev,"TX(%d) NO Desc Avail: %lu\n",                  device_printf(dev,"TX(%d) NO Desc Avail: %lu\n",
                     txr->me, (long)txr->no_desc_avail);                      txr->me, (long)txr->no_desc_avail.ev_count);
         }          }
   
         device_printf(dev,"MBX IRQ Handled: %lu\n",          device_printf(dev,"MBX IRQ Handled: %lu\n",
             (long)adapter->mbx_irq);              (long)adapter->link_irq.ev_count);
         return;          return;
 }  }
   
 static int  static int
 ixv_sysctl_stats(SYSCTL_HANDLER_ARGS)  ixv_sysctl_debug(SYSCTLFN_ARGS)
 {  
         int             error;  
         int             result;  
         struct adapter *adapter;  
   
         result = -1;  
         error = sysctl_handle_int(oidp, &result, 0, req);  
   
         if (error || !req->newptr)  
                 return (error);  
   
         if (result == 1) {  
                 adapter = (struct adapter *) arg1;  
                 ixv_print_hw_stats(adapter);  
         }  
         return error;  
 }  
   
 static int  
 ixv_sysctl_debug(SYSCTL_HANDLER_ARGS)  
 {  {
           struct sysctlnode node;
         int error, result;          int error, result;
         struct adapter *adapter;          struct adapter *adapter;
   
         result = -1;          node = *rnode;
         error = sysctl_handle_int(oidp, &result, 0, req);          adapter = (struct adapter *)node.sysctl_data;
           node.sysctl_data = &result;
         if (error || !req->newptr)          error = sysctl_lookup(SYSCTLFN_CALL(&node));
                 return (error);  
   
         if (result == 1) {  
                 adapter = (struct adapter *) arg1;  
                 ixv_print_debug_info(adapter);  
         }  
         return error;  
 }  
   
 /*  
 ** Set flow control using sysctl:  
 ** Flow control values:  
 **      0 - off  
 **      1 - rx pause  
 **      2 - tx pause  
 **      3 - full  
 */  
 static int  
 ixv_set_flowcntl(SYSCTL_HANDLER_ARGS)  
 {  
         int error;  
         struct adapter *adapter;  
   
         error = sysctl_handle_int(oidp, &ixv_flow_control, 0, req);  
   
         if (error)          if (error)
                 return (error);                  return error;
   
         adapter = (struct adapter *) arg1;          if (result == 1)
         switch (ixv_flow_control) {                  ixv_print_debug_info(adapter);
                 case ixgbe_fc_rx_pause:  
                 case ixgbe_fc_tx_pause:  
                 case ixgbe_fc_full:  
                         adapter->hw.fc.requested_mode = ixv_flow_control;  
                         break;  
                 case ixgbe_fc_none:  
                 default:  
                         adapter->hw.fc.requested_mode = ixgbe_fc_none;  
         }  
   
         ixgbe_fc_enable(&adapter->hw, 0);          return 0;
         return error;  
 }  }
   
 static void  const struct sysctlnode *
 ixv_add_rx_process_limit(struct adapter *adapter, const char *name,  ixv_sysctl_instance(struct adapter *adapter)
         const char *description, int *limit, int value)  
 {  {
         *limit = value;          const char *dvname;
         SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev),          struct sysctllog **log;
             SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),          int rc;
             OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description);          const struct sysctlnode *rnode;
   
           log = &adapter->sysctllog;
           dvname = device_xname(adapter->dev);
   
           if ((rc = sysctl_createv(log, 0, NULL, &rnode,
               0, CTLTYPE_NODE, dvname,
               SYSCTL_DESCR("ixv information and settings"),
               NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0)
                   goto err;
   
           return rnode;
   err:
           printf("%s: sysctl_createv failed, rc = %d\n", __func__, rc);
           return NULL;
 }  }
   

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.2.6.7

CVSweb <webmaster@jp.NetBSD.org>