[BACK]Return to ixgbe.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/ixgbe.c between version 1.14.2.5 and 1.14.2.6

version 1.14.2.5, 2015/05/06 23:29:21 version 1.14.2.6, 2016/06/14 08:42:34
Line 58 
Line 58 
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.   * POSSIBILITY OF SUCH DAMAGE.
  */   */
 /*$FreeBSD: head/sys/dev/ixgbe/ixgbe.c 250108 2013-04-30 16:18:29Z luigi $*/  /*$FreeBSD: head/sys/dev/ixgbe/ixgbe.c 279805 2015-03-09 10:29:15Z araujo $*/
 /*$NetBSD$*/  /*$NetBSD$*/
   
 #include "opt_inet.h"  #include "opt_inet.h"
Line 67 
Line 67 
 #include "ixgbe.h"  #include "ixgbe.h"
 #include "vlan.h"  #include "vlan.h"
   
   #include <sys/cprng.h>
   
 /*********************************************************************  /*********************************************************************
  *  Set this to one to display debug statistics   *  Set this to one to display debug statistics
  *********************************************************************/   *********************************************************************/
Line 75  int             ixgbe_display_debug_stat
Line 77  int             ixgbe_display_debug_stat
 /*********************************************************************  /*********************************************************************
  *  Driver version   *  Driver version
  *********************************************************************/   *********************************************************************/
 char ixgbe_driver_version[] = "2.5.8 - HEAD";  char ixgbe_driver_version[] = "2.5.15";
   
 /*********************************************************************  /*********************************************************************
  *  PCI Device ID Table   *  PCI Device ID Table
Line 134  static int      ixgbe_detach(device_t, i
Line 136  static int      ixgbe_detach(device_t, i
 #if 0  #if 0
 static int      ixgbe_shutdown(device_t);  static int      ixgbe_shutdown(device_t);
 #endif  #endif
 #if IXGBE_LEGACY_TX  #ifdef IXGBE_LEGACY_TX
 static void     ixgbe_start(struct ifnet *);  static void     ixgbe_start(struct ifnet *);
 static void     ixgbe_start_locked(struct tx_ring *, struct ifnet *);  static void     ixgbe_start_locked(struct tx_ring *, struct ifnet *);
 #else  #else /* ! IXGBE_LEGACY_TX */
 static int      ixgbe_mq_start(struct ifnet *, struct mbuf *);  static int      ixgbe_mq_start(struct ifnet *, struct mbuf *);
 static int      ixgbe_mq_start_locked(struct ifnet *,  static int      ixgbe_mq_start_locked(struct ifnet *, struct tx_ring *);
                     struct tx_ring *, struct mbuf *);  
 static void     ixgbe_qflush(struct ifnet *);  static void     ixgbe_qflush(struct ifnet *);
 static void     ixgbe_deferred_mq_start(void *);  static void     ixgbe_deferred_mq_start(void *, int);
 #endif  #endif /* IXGBE_LEGACY_TX */
 static int      ixgbe_ioctl(struct ifnet *, u_long, void *);  static int      ixgbe_ioctl(struct ifnet *, u_long, void *);
 static void     ixgbe_ifstop(struct ifnet *, int);  static void     ixgbe_ifstop(struct ifnet *, int);
 static int      ixgbe_init(struct ifnet *);  static int      ixgbe_init(struct ifnet *);
Line 154  static int      ixgbe_media_change(struc
Line 155  static int      ixgbe_media_change(struc
 static void     ixgbe_identify_hardware(struct adapter *);  static void     ixgbe_identify_hardware(struct adapter *);
 static int      ixgbe_allocate_pci_resources(struct adapter *,  static int      ixgbe_allocate_pci_resources(struct adapter *,
                     const struct pci_attach_args *);                      const struct pci_attach_args *);
   static void     ixgbe_get_slot_info(struct ixgbe_hw *);
 static int      ixgbe_allocate_msix(struct adapter *,  static int      ixgbe_allocate_msix(struct adapter *,
                     const struct pci_attach_args *);                      const struct pci_attach_args *);
 static int      ixgbe_allocate_legacy(struct adapter *,  static int      ixgbe_allocate_legacy(struct adapter *,
Line 183  static void ixgbe_setup_hw_rsc(struct rx
Line 185  static void ixgbe_setup_hw_rsc(struct rx
 static void     ixgbe_enable_intr(struct adapter *);  static void     ixgbe_enable_intr(struct adapter *);
 static void     ixgbe_disable_intr(struct adapter *);  static void     ixgbe_disable_intr(struct adapter *);
 static void     ixgbe_update_stats_counters(struct adapter *);  static void     ixgbe_update_stats_counters(struct adapter *);
 static bool     ixgbe_txeof(struct tx_ring *);  static void     ixgbe_txeof(struct tx_ring *);
 static bool     ixgbe_rxeof(struct ix_queue *);  static bool     ixgbe_rxeof(struct ix_queue *);
 static void     ixgbe_rx_checksum(u32, struct mbuf *, u32,  static void     ixgbe_rx_checksum(u32, struct mbuf *, u32,
                     struct ixgbe_hw_stats *);                      struct ixgbe_hw_stats *);
Line 248  static void ixgbe_atr(struct tx_ring *, 
Line 250  static void ixgbe_atr(struct tx_ring *, 
 static void     ixgbe_reinit_fdir(void *, int);  static void     ixgbe_reinit_fdir(void *, int);
 #endif  #endif
   
   /* Missing shared code prototype */
   extern void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw);
   
 /*********************************************************************  /*********************************************************************
  *  FreeBSD Device Interface Entry Points   *  FreeBSD Device Interface Entry Points
  *********************************************************************/   *********************************************************************/
Line 275  MODULE_DEPEND(ixgbe, ether, 1, 1, 1);
Line 280  MODULE_DEPEND(ixgbe, ether, 1, 1, 1);
 ** traffic for that interrupt vector  ** traffic for that interrupt vector
 */  */
 static int ixgbe_enable_aim = TRUE;  static int ixgbe_enable_aim = TRUE;
 #define TUNABLE_INT(__x, __y)  #define SYSCTL_INT(__x, __y)
 TUNABLE_INT("hw.ixgbe.enable_aim", &ixgbe_enable_aim);  SYSCTL_INT("hw.ixgbe.enable_aim", &ixgbe_enable_aim);
   
 static int ixgbe_max_interrupt_rate = (4000000 / IXGBE_LOW_LATENCY);  static int ixgbe_max_interrupt_rate = (4000000 / IXGBE_LOW_LATENCY);
 TUNABLE_INT("hw.ixgbe.max_interrupt_rate", &ixgbe_max_interrupt_rate);  SYSCTL_INT("hw.ixgbe.max_interrupt_rate", &ixgbe_max_interrupt_rate);
   
 /* How many packets rxeof tries to clean at a time */  /* How many packets rxeof tries to clean at a time */
 static int ixgbe_rx_process_limit = 256;  static int ixgbe_rx_process_limit = 256;
 TUNABLE_INT("hw.ixgbe.rx_process_limit", &ixgbe_rx_process_limit);  SYSCTL_INT("hw.ixgbe.rx_process_limit", &ixgbe_rx_process_limit);
   
 /* How many packets txeof tries to clean at a time */  /* How many packets txeof tries to clean at a time */
 static int ixgbe_tx_process_limit = 256;  static int ixgbe_tx_process_limit = 256;
 TUNABLE_INT("hw.ixgbe.tx_process_limit", &ixgbe_tx_process_limit);  SYSCTL_INT("hw.ixgbe.tx_process_limit", &ixgbe_tx_process_limit);
   
 /*  /*
 ** Smart speed setting, default to on  ** Smart speed setting, default to on
Line 303  static int ixgbe_smart_speed = ixgbe_sma
Line 308  static int ixgbe_smart_speed = ixgbe_sma
  * but this allows it to be forced off for testing.   * but this allows it to be forced off for testing.
  */   */
 static int ixgbe_enable_msix = 1;  static int ixgbe_enable_msix = 1;
 TUNABLE_INT("hw.ixgbe.enable_msix", &ixgbe_enable_msix);  SYSCTL_INT("hw.ixgbe.enable_msix", &ixgbe_enable_msix);
   
 #if defined(NETBSD_MSI_OR_MSIX)  #if defined(NETBSD_MSI_OR_MSIX)
 /*  /*
Line 313  TUNABLE_INT("hw.ixgbe.enable_msix", &ixg
Line 318  TUNABLE_INT("hw.ixgbe.enable_msix", &ixg
  * can be overriden manually here.   * can be overriden manually here.
  */   */
 static int ixgbe_num_queues = 0;  static int ixgbe_num_queues = 0;
 TUNABLE_INT("hw.ixgbe.num_queues", &ixgbe_num_queues);  SYSCTL_INT("hw.ixgbe.num_queues", &ixgbe_num_queues);
 #endif  #endif
   
 /*  /*
Line 322  TUNABLE_INT("hw.ixgbe.num_queues", &ixgb
Line 327  TUNABLE_INT("hw.ixgbe.num_queues", &ixgb
 ** the better performing choice.  ** the better performing choice.
 */  */
 static int ixgbe_txd = PERFORM_TXD;  static int ixgbe_txd = PERFORM_TXD;
 TUNABLE_INT("hw.ixgbe.txd", &ixgbe_txd);  SYSCTL_INT("hw.ixgbe.txd", &ixgbe_txd);
   
 /* Number of RX descriptors per ring */  /* Number of RX descriptors per ring */
 static int ixgbe_rxd = PERFORM_RXD;  static int ixgbe_rxd = PERFORM_RXD;
 TUNABLE_INT("hw.ixgbe.rxd", &ixgbe_rxd);  SYSCTL_INT("hw.ixgbe.rxd", &ixgbe_rxd);
   
   /*
   ** Defining this on will allow the use
   ** of unsupported SFP+ modules, note that
   ** doing so you are on your own :)
   */
   static int allow_unsupported_sfp = false;
   SYSCTL_INT("hw.ix.unsupported_sfp", &allow_unsupported_sfp);
   
 /*  /*
 ** HW RSC control:  ** HW RSC control:
Line 510  ixgbe_attach(device_t parent, device_t d
Line 523  ixgbe_attach(device_t parent, device_t d
         adapter->osdep.pc = pa->pa_pc;          adapter->osdep.pc = pa->pa_pc;
         adapter->osdep.tag = pa->pa_tag;          adapter->osdep.tag = pa->pa_tag;
         adapter->osdep.dmat = pa->pa_dmat;          adapter->osdep.dmat = pa->pa_dmat;
           adapter->osdep.attached = false;
   
         ent = ixgbe_lookup(pa);          ent = ixgbe_lookup(pa);
   
Line 562  ixgbe_attach(device_t parent, device_t d
Line 576  ixgbe_attach(device_t parent, device_t d
         }          }
   
         if (((ixgbe_rxd * sizeof(union ixgbe_adv_rx_desc)) % DBA_ALIGN) != 0 ||          if (((ixgbe_rxd * sizeof(union ixgbe_adv_rx_desc)) % DBA_ALIGN) != 0 ||
             ixgbe_rxd < MIN_TXD || ixgbe_rxd > MAX_TXD) {              ixgbe_rxd < MIN_RXD || ixgbe_rxd > MAX_RXD) {
                 aprint_error_dev(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
Line 584  ixgbe_attach(device_t parent, device_t d
Line 598  ixgbe_attach(device_t parent, device_t d
         }          }
   
         /* Initialize the shared code */          /* Initialize the shared code */
           hw->allow_unsupported_sfp = allow_unsupported_sfp;
         error = ixgbe_init_shared_code(hw);          error = ixgbe_init_shared_code(hw);
         if (error == IXGBE_ERR_SFP_NOT_PRESENT) {          if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
                 /*                  /*
Line 648  ixgbe_attach(device_t parent, device_t d
Line 663  ixgbe_attach(device_t parent, device_t d
         /* Initialize statistics */          /* Initialize statistics */
         ixgbe_update_stats_counters(adapter);          ixgbe_update_stats_counters(adapter);
   
         /* Print PCIE bus type/speed/width info */          /*
         ixgbe_get_bus_info(hw);          ** Check PCIE slot type/speed/width
         aprint_normal_dev(dev,"PCI Express Bus: Speed %s %s\n",          */
             ((hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0Gb/s":          ixgbe_get_slot_info(hw);
             (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5Gb/s":"Unknown"),  
             (hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" :  
             (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" :  
             (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" :  
             ("Unknown"));  
   
         if ((hw->bus.width <= ixgbe_bus_width_pcie_x4) &&  
             (hw->bus.speed == ixgbe_bus_speed_2500)) {  
                 aprint_error_dev(dev, "PCI-Express bandwidth available"  
                     " for this card\n     is not sufficient for"  
                     " optimal performance.\n");  
                 aprint_error_dev(dev, "For optimal performance a x8 "  
                     "PCIE, or x4 PCIE 2 slot is required.\n");  
         }  
   
         /* Set an initial default flow control value */          /* Set an initial default flow control value */
         adapter->fc =  ixgbe_fc_full;          adapter->fc =  ixgbe_fc_full;
Line 681  ixgbe_attach(device_t parent, device_t d
Line 682  ixgbe_attach(device_t parent, device_t d
         ixgbe_netmap_attach(adapter);          ixgbe_netmap_attach(adapter);
 #endif /* DEV_NETMAP */  #endif /* DEV_NETMAP */
         INIT_DEBUGOUT("ixgbe_attach: end");          INIT_DEBUGOUT("ixgbe_attach: end");
           adapter->osdep.attached = true;
         return;          return;
 err_late:  err_late:
         ixgbe_free_transmit_structures(adapter);          ixgbe_free_transmit_structures(adapter);
Line 716  ixgbe_detach(device_t dev, int flags)
Line 718  ixgbe_detach(device_t dev, int flags)
         u32     ctrl_ext;          u32     ctrl_ext;
   
         INIT_DEBUGOUT("ixgbe_detach: begin");          INIT_DEBUGOUT("ixgbe_detach: begin");
           if (adapter->osdep.attached == false)
                   return 0;
   
 #if NVLAN > 0  #if NVLAN > 0
         /* Make sure VLANs are not using driver */          /* Make sure VLANs are not using driver */
Line 807  ixgbe_detach(device_t dev, int flags)
Line 811  ixgbe_detach(device_t dev, int flags)
   
                 evcnt_detach(&rxr->rx_packets);                  evcnt_detach(&rxr->rx_packets);
                 evcnt_detach(&rxr->rx_bytes);                  evcnt_detach(&rxr->rx_bytes);
                   evcnt_detach(&rxr->rx_copies);
                 evcnt_detach(&rxr->no_jmbuf);                  evcnt_detach(&rxr->no_jmbuf);
                 evcnt_detach(&rxr->rx_discarded);                  evcnt_detach(&rxr->rx_discarded);
                 evcnt_detach(&rxr->rx_irq);                  evcnt_detach(&rxr->rx_irq);
Line 985  ixgbe_mq_start(struct ifnet *ifp, struct
Line 990  ixgbe_mq_start(struct ifnet *ifp, struct
         struct adapter  *adapter = ifp->if_softc;          struct adapter  *adapter = ifp->if_softc;
         struct ix_queue *que;          struct ix_queue *que;
         struct tx_ring  *txr;          struct tx_ring  *txr;
         int             i = 0, err = 0;          int             i, err = 0;
   #ifdef  RSS
           uint32_t bucket_id;
   #endif
   
         /* Which queue to use */          /* Which queue to use */
         if ((m->m_flags & M_FLOWID) != 0)          /*
                 i = m->m_pkthdr.flowid % adapter->num_queues;           * When doing RSS, map it to the same outbound queue
         else           * as the incoming flow would be mapped to.
                 i = cpu_index(curcpu()) % adapter->num_queues;           *
            * If everything is setup correctly, it should be the
            * same bucket that the current CPU we're on is.
            */
           if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) {
   #ifdef  RSS
                   if (rss_hash2bucket(m->m_pkthdr.flowid,
                       M_HASHTYPE_GET(m), &bucket_id) == 0) {
                           /* XXX TODO: spit out something if bucket_id > num_queues? */
                           i = bucket_id % adapter->num_queues;
                   } else {
   #endif
                           i = m->m_pkthdr.flowid % adapter->num_queues;
   #ifdef  RSS
                   }
   #endif
           } else {
                   i = curcpu % adapter->num_queues;
           }
   
         txr = &adapter->tx_rings[i];          txr = &adapter->tx_rings[i];
         que = &adapter->queues[i];          que = &adapter->queues[i];
   
           err = drbr_enqueue(ifp, txr->br, m);
           if (err)
                   return (err);
         if (IXGBE_TX_TRYLOCK(txr)) {          if (IXGBE_TX_TRYLOCK(txr)) {
                 err = ixgbe_mq_start_locked(ifp, txr, m);                  ixgbe_mq_start_locked(ifp, txr);
                 IXGBE_TX_UNLOCK(txr);                  IXGBE_TX_UNLOCK(txr);
         } else {          } else
                 err = drbr_enqueue(ifp, txr->br, m);  
                 softint_schedule(txr->txq_si);                  softint_schedule(txr->txq_si);
         }  
   
         return (err);          return (0);
 }  }
   
 static int  static int
 ixgbe_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)  ixgbe_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr)
 {  {
         struct adapter  *adapter = txr->adapter;          struct adapter  *adapter = txr->adapter;
         struct mbuf     *next;          struct mbuf     *next;
         int             enqueued, err = 0;          int             enqueued = 0, err = 0;
   
         if (((ifp->if_flags & IFF_RUNNING) == 0) ||          if (((ifp->if_flags & IFF_RUNNING) == 0) ||
             adapter->link_active == 0) {              adapter->link_active == 0)
                 if (m != NULL)                  return (ENETDOWN);
                         err = drbr_enqueue(ifp, txr->br, m);  
                 return (err);  
         }  
   
         enqueued = 0;  
         if (m != NULL) {  
                 err = drbr_enqueue(ifp, txr->br, m);  
                 if (err) {  
                         return (err);  
                 }  
         }  
   
         /* Process the queue */          /* Process the queue */
   #if __FreeBSD_version < 901504
           next = drbr_dequeue(ifp, txr->br);
           while (next != NULL) {
                   if ((err = ixgbe_xmit(txr, &next)) != 0) {
                           if (next != NULL)
                                   err = drbr_enqueue(ifp, txr->br, next);
   #else
         while ((next = drbr_peek(ifp, txr->br)) != NULL) {          while ((next = drbr_peek(ifp, txr->br)) != NULL) {
                 if ((err = ixgbe_xmit(txr, &next)) != 0) {                  if ((err = ixgbe_xmit(txr, &next)) != 0) {
                         if (next == NULL) {                          if (next == NULL) {
Line 1037  ixgbe_mq_start_locked(struct ifnet *ifp,
Line 1060  ixgbe_mq_start_locked(struct ifnet *ifp,
                         } else {                          } else {
                                 drbr_putback(ifp, txr->br, next);                                  drbr_putback(ifp, txr->br, next);
                         }                          }
   #endif
                         break;                          break;
                 }                  }
   #if __FreeBSD_version >= 901504
                 drbr_advance(ifp, txr->br);                  drbr_advance(ifp, txr->br);
   #endif
                 enqueued++;                  enqueued++;
                 /* Send a copy of the frame to the BPF listener */                  /* Send a copy of the frame to the BPF listener */
                 bpf_mtap(ifp, next);                  bpf_mtap(ifp, next);
                 if ((ifp->if_flags & IFF_RUNNING) == 0)                  if ((ifp->if_flags & IFF_RUNNING) == 0)
                         break;                          break;
                 if (txr->tx_avail < IXGBE_TX_OP_THRESHOLD)  #if __FreeBSD_version < 901504
                         ixgbe_txeof(txr);                  next = drbr_dequeue(ifp, txr->br);
   #endif
         }          }
   
         if (enqueued > 0) {          if (enqueued > 0) {
Line 1065  ixgbe_mq_start_locked(struct ifnet *ifp,
Line 1092  ixgbe_mq_start_locked(struct ifnet *ifp,
  * Called from a taskqueue to drain queued transmit packets.   * Called from a taskqueue to drain queued transmit packets.
  */   */
 static void  static void
 ixgbe_deferred_mq_start(void *arg)  ixgbe_deferred_mq_start(void *arg, int pending)
 {  {
         struct tx_ring *txr = arg;          struct tx_ring *txr = arg;
         struct adapter *adapter = txr->adapter;          struct adapter *adapter = txr->adapter;
Line 1073  ixgbe_deferred_mq_start(void *arg)
Line 1100  ixgbe_deferred_mq_start(void *arg)
   
         IXGBE_TX_LOCK(txr);          IXGBE_TX_LOCK(txr);
         if (!drbr_empty(ifp, txr->br))          if (!drbr_empty(ifp, txr->br))
                 ixgbe_mq_start_locked(ifp, txr, NULL);                  ixgbe_mq_start_locked(ifp, txr);
         IXGBE_TX_UNLOCK(txr);          IXGBE_TX_UNLOCK(txr);
 }  }
   
Line 1175  ixgbe_ioctl(struct ifnet * ifp, u_long c
Line 1202  ixgbe_ioctl(struct ifnet * ifp, u_long c
                 struct ixgbe_i2c_req    i2c;                  struct ixgbe_i2c_req    i2c;
                 IOCTL_DEBUGOUT("ioctl: SIOCGI2C (Get I2C Data)");                  IOCTL_DEBUGOUT("ioctl: SIOCGI2C (Get I2C Data)");
                 error = copyin(ifr->ifr_data, &i2c, sizeof(i2c));                  error = copyin(ifr->ifr_data, &i2c, sizeof(i2c));
                 if (error)                  if (error != 0)
                           break;
                   if (i2c.dev_addr != 0xA0 && i2c.dev_addr != 0xA2) {
                           error = EINVAL;
                         break;                          break;
                 if ((i2c.dev_addr != 0xA0) || (i2c.dev_addr != 0xA2)){                  }
                   if (i2c.len > sizeof(i2c.data)) {
                         error = EINVAL;                          error = EINVAL;
                         break;                          break;
                 }                  }
   
                 hw->phy.ops.read_i2c_byte(hw, i2c.offset,                  hw->phy.ops.read_i2c_byte(hw, i2c.offset,
                     i2c.dev_addr, i2c.data);                      i2c.dev_addr, i2c.data);
                 error = copyout(&i2c, ifr->ifr_data, sizeof(i2c));                  error = copyout(&i2c, ifr->ifr_data, sizeof(i2c));
Line 1248  ixgbe_init_locked(struct adapter *adapte
Line 1280  ixgbe_init_locked(struct adapter *adapte
         /* XXX check IFF_UP and IFF_RUNNING, power-saving state! */          /* XXX check IFF_UP and IFF_RUNNING, power-saving state! */
   
         KASSERT(mutex_owned(&adapter->core_mtx));          KASSERT(mutex_owned(&adapter->core_mtx));
         INIT_DEBUGOUT("ixgbe_init: begin");          INIT_DEBUGOUT("ixgbe_init_locked: begin");
         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 1307  ixgbe_init_locked(struct adapter *adapte
Line 1339  ixgbe_init_locked(struct adapter *adapte
         /* Enable Fan Failure Interrupt */          /* Enable Fan Failure Interrupt */
         gpie |= IXGBE_SDP1_GPIEN;          gpie |= IXGBE_SDP1_GPIEN;
   
         /* Add for Thermal detection */          /* Add for Module detection */
         if (hw->mac.type == ixgbe_mac_82599EB)          if (hw->mac.type == ixgbe_mac_82599EB)
                 gpie |= IXGBE_SDP2_GPIEN;                  gpie |= IXGBE_SDP2_GPIEN;
   
Line 1393  ixgbe_init_locked(struct adapter *adapte
Line 1425  ixgbe_init_locked(struct adapter *adapte
                 if (ifp->if_capenable & IFCAP_NETMAP) {                  if (ifp->if_capenable & IFCAP_NETMAP) {
                         struct netmap_adapter *na = NA(adapter->ifp);                          struct netmap_adapter *na = NA(adapter->ifp);
                         struct netmap_kring *kring = &na->rx_rings[i];                          struct netmap_kring *kring = &na->rx_rings[i];
                         int t = na->num_rx_desc - 1 - kring->nr_hwavail;                          int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring);
   
                         IXGBE_WRITE_REG(hw, IXGBE_RDT(i), t);                          IXGBE_WRITE_REG(hw, IXGBE_RDT(i), t);
                 } else                  } else
Line 1401  ixgbe_init_locked(struct adapter *adapte
Line 1433  ixgbe_init_locked(struct adapter *adapte
                 IXGBE_WRITE_REG(hw, IXGBE_RDT(i), adapter->num_rx_desc - 1);                  IXGBE_WRITE_REG(hw, IXGBE_RDT(i), adapter->num_rx_desc - 1);
         }          }
   
         /* Set up VLAN support and filter */  
         ixgbe_setup_vlan_hw_support(adapter);  
   
         /* Enable Receive engine */          /* Enable Receive engine */
         rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);          rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
         if (hw->mac.type == ixgbe_mac_82598EB)          if (hw->mac.type == ixgbe_mac_82598EB)
Line 1487  ixgbe_init_locked(struct adapter *adapte
Line 1516  ixgbe_init_locked(struct adapter *adapte
         /* Initialize the FC settings */          /* Initialize the FC settings */
         ixgbe_start_hw(hw);          ixgbe_start_hw(hw);
   
           /* Set up VLAN support and filter */
           ixgbe_setup_vlan_hw_support(adapter);
   
         /* And now turn on interrupts */          /* And now turn on interrupts */
         ixgbe_enable_intr(adapter);          ixgbe_enable_intr(adapter);
   
Line 1554  ixgbe_disable_queue(struct adapter *adap
Line 1586  ixgbe_disable_queue(struct adapter *adap
         }          }
 }  }
   
 static inline void  
 ixgbe_rearm_queues(struct adapter *adapter, u64 queues)  
 {  
         u32 mask;  
   
         if (adapter->hw.mac.type == ixgbe_mac_82598EB) {  
                 mask = (IXGBE_EIMS_RTX_QUEUE & queues);  
                 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask);  
         } else {  
                 mask = (queues & 0xFFFFFFFF);  
                 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask);  
                 mask = (queues >> 32);  
                 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(1), mask);  
         }  
 }  
   
   
 static void  static void
 ixgbe_handle_que(void *context)  ixgbe_handle_que(void *context)
 {  {
Line 1578  ixgbe_handle_que(void *context)
Line 1593  ixgbe_handle_que(void *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;  
   
         adapter->handleq.ev_count++;          adapter->handleq.ev_count++;
   
         if (ifp->if_flags & IFF_RUNNING) {          if (ifp->if_flags & IFF_RUNNING) {
                 more = ixgbe_rxeof(que);                  ixgbe_rxeof(que);
                 IXGBE_TX_LOCK(txr);                  IXGBE_TX_LOCK(txr);
                 ixgbe_txeof(txr);                  ixgbe_txeof(txr);
 #ifndef IXGBE_LEGACY_TX  #ifndef IXGBE_LEGACY_TX
                 if (!drbr_empty(ifp, txr->br))                  if (!drbr_empty(ifp, txr->br))
                         ixgbe_mq_start_locked(ifp, txr, NULL);                          ixgbe_mq_start_locked(ifp, txr);
 #else  #else
                 if (!IFQ_IS_EMPTY(&ifp->if_snd))                  if (!IFQ_IS_EMPTY(&ifp->if_snd))
                         ixgbe_start_locked(txr, ifp);                          ixgbe_start_locked(txr, ifp);
 #endif  #endif
                 IXGBE_TX_UNLOCK(txr);                  IXGBE_TX_UNLOCK(txr);
                 if (more) {  
                         adapter->req.ev_count++;  
                         softint_schedule(que->que_si);  
                         return;  
                 }  
         }          }
   
         /* Reenable this interrupt */          /* Reenable this interrupt */
         ixgbe_enable_queue(adapter, que->msix);          if (que->res != NULL)
                   ixgbe_enable_queue(adapter, que->msix);
           else
                   ixgbe_enable_intr(adapter);
         return;          return;
 }  }
   
Line 1618  ixgbe_legacy_irq(void *arg)
Line 1630  ixgbe_legacy_irq(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 ixgbe_hw *hw = &adapter->hw;          struct ixgbe_hw *hw = &adapter->hw;
           struct ifnet    *ifp = adapter->ifp;
         struct          tx_ring *txr = adapter->tx_rings;          struct          tx_ring *txr = adapter->tx_rings;
         bool            more_tx = false, more_rx = false;          bool            more = false;
         u32             reg_eicr, loop = MAX_LOOP;          u32             reg_eicr;
   
   
         reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR);          reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
   
Line 1636  ixgbe_legacy_irq(void *arg)
Line 1649  ixgbe_legacy_irq(void *arg)
         }          }
   
         if ((ifp->if_flags & IFF_RUNNING) != 0) {          if ((ifp->if_flags & IFF_RUNNING) != 0) {
                 more_rx = ixgbe_rxeof(que);                  more = ixgbe_rxeof(que);
   
                 IXGBE_TX_LOCK(txr);                  IXGBE_TX_LOCK(txr);
                 do {                  ixgbe_txeof(txr);
                         adapter->txloops.ev_count++;  #ifdef IXGBE_LEGACY_TX
                         more_tx = ixgbe_txeof(txr);                  if (!IFQ_IS_EMPTY(&ifp->if_snd))
                 } while (loop-- && more_tx);                          ixgbe_start_locked(txr, ifp);
   #else
                   if (!drbr_empty(ifp, txr->br))
                           ixgbe_mq_start_locked(ifp, txr);
   #endif
                 IXGBE_TX_UNLOCK(txr);                  IXGBE_TX_UNLOCK(txr);
         }          }
   
         if (more_rx || more_tx) {  
                 if (more_rx)  
                         adapter->morerx.ev_count++;  
                 if (more_tx)  
                         adapter->moretx.ev_count++;  
                 softint_schedule(que->que_si);  
         }  
   
         /* Check for fan failure */          /* Check for fan failure */
         if ((hw->phy.media_type == ixgbe_media_type_copper) &&          if ((hw->phy.media_type == ixgbe_media_type_copper) &&
             (reg_eicr & IXGBE_EICR_GPI_SDP1)) {              (reg_eicr & IXGBE_EICR_GPI_SDP1)) {
Line 1666  ixgbe_legacy_irq(void *arg)
Line 1675  ixgbe_legacy_irq(void *arg)
         if (reg_eicr & IXGBE_EICR_LSC)          if (reg_eicr & IXGBE_EICR_LSC)
                 softint_schedule(adapter->link_si);                  softint_schedule(adapter->link_si);
   
         ixgbe_enable_intr(adapter);          if (more)
   #ifndef IXGBE_LEGACY_TX
                   softint_schedule(txr->txq_si);
   #else
                   softint_schedule(que->que_si);
   #endif
           else
                   ixgbe_enable_intr(adapter);
         return 1;          return 1;
 }  }
   
Line 1682  ixgbe_msix_que(void *arg)
Line 1698  ixgbe_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;
   
           /* Protect against spurious interrupts */
           if ((ifp->if_flags & IFF_RUNNING) == 0)
                   return;
   
         ixgbe_disable_queue(adapter, que->msix);          ixgbe_disable_queue(adapter, que->msix);
         ++que->irqs;          ++que->irqs;
   
         more_rx = ixgbe_rxeof(que);          more = ixgbe_rxeof(que);
   
         IXGBE_TX_LOCK(txr);          IXGBE_TX_LOCK(txr);
         more_tx = ixgbe_txeof(txr);          ixgbe_txeof(txr);
         /*  
         ** Make certain that if the stack  
         ** has anything queued the task gets  
         ** scheduled to handle it.  
         */  
 #ifdef IXGBE_LEGACY_TX  #ifdef IXGBE_LEGACY_TX
         if (!IFQ_IS_EMPTY(&adapter->ifp->if_snd))          if (!IFQ_IS_EMPTY(&adapter->ifp->if_snd))
 #else  #else
         if (!drbr_empty(adapter->ifp, txr->br))          if (!drbr_empty(ifp, txr->br))
                   ixgbe_mq_start_locked(ifp, txr);
 #endif  #endif
                 more_tx = 1;  
         IXGBE_TX_UNLOCK(txr);          IXGBE_TX_UNLOCK(txr);
   
         /* Do AIM now? */          /* Do AIM now? */
Line 1758  ixgbe_msix_que(void *arg)
Line 1774  ixgbe_msix_que(void *arg)
         rxr->packets = 0;          rxr->packets = 0;
   
 no_calc:  no_calc:
         if (more_tx || more_rx)          if (more)
                 softint_schedule(que->que_si);                  softint_schedule(que->que_si);
         else /* Reenable this interrupt */          else
                 ixgbe_enable_queue(adapter, que->msix);                  ixgbe_enable_queue(adapter, que->msix);
         return;          return;
 }  }
Line 1777  ixgbe_msix_link(void *arg)
Line 1793  ixgbe_msix_link(void *arg)
   
         /* First get the cause */          /* First get the cause */
         reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICS);          reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
           /* Be sure the queue bits are not cleared */
           reg_eicr &= ~IXGBE_EICR_RTX_QUEUE;
         /* Clear interrupt with write */          /* Clear interrupt with write */
         IXGBE_WRITE_REG(hw, IXGBE_EICR, reg_eicr);          IXGBE_WRITE_REG(hw, IXGBE_EICR, reg_eicr);
   
Line 1846  static void
Line 1864  static void
 ixgbe_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)  ixgbe_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)
 {  {
         struct adapter *adapter = ifp->if_softc;          struct adapter *adapter = ifp->if_softc;
           struct ixgbe_hw *hw = &adapter->hw;
   
         INIT_DEBUGOUT("ixgbe_media_status: begin");          INIT_DEBUGOUT("ixgbe_media_status: begin");
         IXGBE_CORE_LOCK(adapter);          IXGBE_CORE_LOCK(adapter);
Line 1861  ixgbe_media_status(struct ifnet * ifp, s
Line 1880  ixgbe_media_status(struct ifnet * ifp, s
   
         ifmr->ifm_status |= IFM_ACTIVE;          ifmr->ifm_status |= IFM_ACTIVE;
   
         switch (adapter->link_speed) {          /*
                 case IXGBE_LINK_SPEED_100_FULL:           * Not all NIC are 1000baseSX as an example X540T.
            * We must set properly the media based on NIC model.
            */
           switch (hw->device_id) {
           case IXGBE_DEV_ID_X540T:
                   if (adapter->link_speed == IXGBE_LINK_SPEED_100_FULL)
                         ifmr->ifm_active |= IFM_100_TX | IFM_FDX;                          ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
                         break;                  else if (adapter->link_speed == IXGBE_LINK_SPEED_1GB_FULL)
                 case IXGBE_LINK_SPEED_1GB_FULL:                          ifmr->ifm_active |= IFM_1000_T | IFM_FDX;
                   else if (adapter->link_speed == IXGBE_LINK_SPEED_10GB_FULL)
                           ifmr->ifm_active |= adapter->optics | IFM_FDX;
                   break;
           default:
                   if (adapter->link_speed == IXGBE_LINK_SPEED_100_FULL)
                           ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
                   else if (adapter->link_speed == IXGBE_LINK_SPEED_1GB_FULL)
                         ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;                          ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
                         break;                  else if (adapter->link_speed == IXGBE_LINK_SPEED_10GB_FULL)
                 case IXGBE_LINK_SPEED_10GB_FULL:  
                         ifmr->ifm_active |= adapter->optics | IFM_FDX;                          ifmr->ifm_active |= adapter->optics | IFM_FDX;
                         break;                  break;
         }          }
   
         IXGBE_CORE_UNLOCK(adapter);          IXGBE_CORE_UNLOCK(adapter);
Line 1898  ixgbe_media_change(struct ifnet * ifp)
Line 1928  ixgbe_media_change(struct ifnet * ifp)
                 return (EINVAL);                  return (EINVAL);
   
         switch (IFM_SUBTYPE(ifm->ifm_media)) {          switch (IFM_SUBTYPE(ifm->ifm_media)) {
         case IFM_AUTO:          case IFM_10G_T:
                 adapter->hw.phy.autoneg_advertised =          case IFM_AUTO:
                   adapter->hw.phy.autoneg_advertised =
                     IXGBE_LINK_SPEED_100_FULL |                      IXGBE_LINK_SPEED_100_FULL |
                     IXGBE_LINK_SPEED_1GB_FULL |                      IXGBE_LINK_SPEED_1GB_FULL |
                     IXGBE_LINK_SPEED_10GB_FULL;                      IXGBE_LINK_SPEED_10GB_FULL;
Line 1977  ixgbe_xmit(struct tx_ring *txr, struct m
Line 2008  ixgbe_xmit(struct tx_ring *txr, struct m
                 default:                  default:
                         adapter->other_tx_dma_setup.ev_count++;                          adapter->other_tx_dma_setup.ev_count++;
                         return error;                          return error;
                 case 0:  
                         break;  
                 }                  }
         }          }
   
Line 2222  ixgbe_local_timer1(void *arg)
Line 2251  ixgbe_local_timer1(void *arg)
                     (paused == 0))                      (paused == 0))
                         ++hung;                          ++hung;
                 else if (txr->queue_status == IXGBE_QUEUE_WORKING)                  else if (txr->queue_status == IXGBE_QUEUE_WORKING)
   #ifndef IXGBE_LEGACY_TX
                           softint_schedule(txr->txq_si);
   #else
                         softint_schedule(que->que_si);                          softint_schedule(que->que_si);
   #endif
         }          }
         /* Only truely watchdog if all queues show hung */          /* Only truely watchdog if all queues show hung */
         if (hung == adapter->num_queues)          if (hung == adapter->num_queues)
                 goto watchdog;                  goto watchdog;
   
 out:  out:
         ixgbe_rearm_queues(adapter, adapter->que_mask);  
         callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);          callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
         return;          return;
   
Line 2329  ixgbe_stop(void *arg)
Line 2361  ixgbe_stop(void *arg)
         ixgbe_reset_hw(hw);          ixgbe_reset_hw(hw);
         hw->adapter_stopped = FALSE;          hw->adapter_stopped = FALSE;
         ixgbe_stop_adapter(hw);          ixgbe_stop_adapter(hw);
         /* Turn off the laser */          if (hw->mac.type == ixgbe_mac_82599EB)
         if (hw->phy.multispeed_fiber)                  ixgbe_stop_mac_link_on_d3_82599(hw);
                 ixgbe_disable_tx_laser(hw);          /* Turn off the laser - noop with no optics */
           ixgbe_disable_tx_laser(hw);
   
           /* Update the stack */
           adapter->link_up = FALSE;
           ixgbe_update_link_status(adapter);
   
         /* reprogram the RAR[0] in case user changed it. */          /* reprogram the RAR[0] in case user changed it. */
         ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV);          ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV);
Line 2536  ixgbe_allocate_msix(struct adapter *adap
Line 2573  ixgbe_allocate_msix(struct adapter *adap
         struct          ix_queue *que = adapter->queues;          struct          ix_queue *que = adapter->queues;
         struct          tx_ring *txr = adapter->tx_rings;          struct          tx_ring *txr = adapter->tx_rings;
         int             error, rid, vector = 0;          int             error, rid, vector = 0;
           int             cpu_id = 0;
   #ifdef  RSS
           cpuset_t cpu_mask;
   #endif
   
   #ifdef  RSS
           /*
            * If we're doing RSS, the number of queues needs to
            * match the number of RSS buckets that are configured.
            *
            * + If there's more queues than RSS buckets, we'll end
            *   up with queues that get no traffic.
            *
            * + If there's more RSS buckets than queues, we'll end
            *   up having multiple RSS buckets map to the same queue,
            *   so there'll be some contention.
            */
           if (adapter->num_queues != rss_getnumbuckets()) {
                   device_printf(dev,
                       "%s: number of queues (%d) != number of RSS buckets (%d)"
                       "; performance will be impacted.\n",
                       __func__,
                       adapter->num_queues,
                       rss_getnumbuckets());
           }
   #endif
   
         for (int i = 0; i < adapter->num_queues; i++, vector++, que++, txr++) {          for (int i = 0; i < adapter->num_queues; i++, vector++, que++, txr++) {
                 rid = vector + 1;                  rid = vector + 1;
Line 2561  ixgbe_allocate_msix(struct adapter *adap
Line 2624  ixgbe_allocate_msix(struct adapter *adap
 #endif  #endif
                 que->msix = vector;                  que->msix = vector;
                 adapter->que_mask |= (u64)(1 << que->msix);                  adapter->que_mask |= (u64)(1 << que->msix);
   #ifdef  RSS
                 /*                  /*
                 ** Bind the msix vector, and thus the                   * The queue ID is used as the RSS layer bucket ID.
                 ** ring to the corresponding cpu.                   * We look up the queue ID -> RSS CPU ID and select
                 */                   * that.
                    */
                   cpu_id = rss_getcpu(i % rss_getnumbuckets());
   #else
                   /*
                    * Bind the msix vector, and thus the
                    * rings to the corresponding cpu.
                    *
                    * This just happens to match the default RSS round-robin
                    * bucket -> queue -> CPU allocation.
                    */
                 if (adapter->num_queues > 1)                  if (adapter->num_queues > 1)
                         bus_bind_intr(dev, que->res, i);                          cpu_id = i;
   #endif
                   if (adapter->num_queues > 1)
                           bus_bind_intr(dev, que->res, cpu_id);
   
   #ifdef  RSS
                   device_printf(dev,
                       "Bound RSS bucket %d to CPU %d\n",
                       i, cpu_id);
   #else
                   device_printf(dev,
                       "Bound queue %d to cpu %d\n",
                       i, cpu_id);
   #endif
   
 #ifndef IXGBE_LEGACY_TX  #ifndef IXGBE_LEGACY_TX
                 txr->txq_si = softint_establish(SOFTINT_NET,                  txr->txq_si = softint_establish(SOFTINT_NET,
Line 2635  ixgbe_setup_msix(struct adapter *adapter
Line 2722  ixgbe_setup_msix(struct adapter *adapter
                 goto msi;                  goto msi;
   
         /* First try MSI/X */          /* First try MSI/X */
           msgs = pci_msix_count(dev);
           if (msgs == 0)
                   goto msi;
         rid = PCI_BAR(MSIX_82598_BAR);          rid = PCI_BAR(MSIX_82598_BAR);
         adapter->msix_mem = bus_alloc_resource_any(dev,          adapter->msix_mem = bus_alloc_resource_any(dev,
             SYS_RES_MEMORY, &rid, RF_ACTIVE);              SYS_RES_MEMORY, &rid, RF_ACTIVE);
         if (!adapter->msix_mem) {          if (adapter->msix_mem == NULL) {
                 rid += 4;       /* 82599 maps in higher BAR */                  rid += 4;       /* 82599 maps in higher BAR */
                 adapter->msix_mem = bus_alloc_resource_any(dev,                  adapter->msix_mem = bus_alloc_resource_any(dev,
                     SYS_RES_MEMORY, &rid, RF_ACTIVE);                      SYS_RES_MEMORY, &rid, RF_ACTIVE);
         }          }
         if (!adapter->msix_mem) {          if (adapter->msix_mem == NULL) {
                 /* May not be enabled */                  /* May not be enabled */
                 device_printf(adapter->dev,                  device_printf(adapter->dev,
                     "Unable to map MSIX table \n");                      "Unable to map MSIX table \n");
                 goto msi;                  goto msi;
         }          }
   
         msgs = pci_msix_count(dev);  
         if (msgs == 0) { /* system has msix disabled */  
                 bus_release_resource(dev, SYS_RES_MEMORY,  
                     rid, adapter->msix_mem);  
                 adapter->msix_mem = NULL;  
                 goto msi;  
         }  
   
         /* Figure out a reasonable auto config value */          /* Figure out a reasonable auto config value */
         queues = (mp_ncpus > (msgs-1)) ? (msgs-1) : mp_ncpus;          queues = (mp_ncpus > (msgs-1)) ? (msgs-1) : mp_ncpus;
   
           /* Override based on tuneable */
         if (ixgbe_num_queues != 0)          if (ixgbe_num_queues != 0)
                 queues = ixgbe_num_queues;                  queues = ixgbe_num_queues;
         /* Set max queues to 8 when autoconfiguring */  
         else if ((ixgbe_num_queues == 0) && (queues > 8))  #ifdef  RSS
                 queues = 8;          /* If we're doing RSS, clamp at the number of RSS buckets */
           if (queues > rss_getnumbuckets())
                   queues = rss_getnumbuckets();
   #endif
   
           /* reflect correct sysctl value */
           ixgbe_num_queues = queues;
   
         /*          /*
         ** Want one vector (RX/TX pair) per queue          ** Want one vector (RX/TX pair) per queue
Line 2679  ixgbe_setup_msix(struct adapter *adapter
Line 2768  ixgbe_setup_msix(struct adapter *adapter
                     "MSIX Configuration Problem, "                      "MSIX Configuration Problem, "
                     "%d vectors but %d queues wanted!\n",                      "%d vectors but %d queues wanted!\n",
                     msgs, want);                      msgs, want);
                 return (0); /* Will go to Legacy setup */                  goto msi;
         }          }
         if ((msgs) && pci_alloc_msix(dev, &msgs) == 0) {          if ((pci_alloc_msix(dev, &msgs) == 0) && (msgs == want)) {
                 device_printf(adapter->dev,                  device_printf(adapter->dev,
                     "Using MSIX interrupts with %d vectors\n", msgs);                      "Using MSIX interrupts with %d vectors\n", msgs);
                 adapter->num_queues = queues;                  adapter->num_queues = queues;
                 return (msgs);                  return (msgs);
         }          }
           /*
           ** If MSIX alloc failed or provided us with
           ** less than needed, free and fall through to MSI
           */
           pci_release_msi(dev);
   
 msi:  msi:
         msgs = pci_msi_count(dev);          msgs = pci_msi_count(dev);
         if (msgs == 1 && pci_alloc_msi(dev, &msgs) == 0)          if (adapter->msix_mem != NULL) {
                   bus_release_resource(dev, SYS_RES_MEMORY,
                       rid, adapter->msix_mem);
                   adapter->msix_mem = NULL;
           }
           msgs = 1;
           if (pci_alloc_msi(dev, &msgs) == 0) {
                 device_printf(adapter->dev,"Using an MSI interrupt\n");                  device_printf(adapter->dev,"Using an MSI interrupt\n");
         else                  return (msgs);
                 device_printf(adapter->dev,"Using a Legacy interrupt\n");          }
         return (msgs);          device_printf(adapter->dev,"Using a Legacy interrupt\n");
           return (0);
 #endif  #endif
 }  }
   
Line 2792  ixgbe_free_pci_resources(struct adapter 
Line 2894  ixgbe_free_pci_resources(struct adapter 
         else          else
                 (adapter->msix != 0) ? (rid = 1):(rid = 0);                  (adapter->msix != 0) ? (rid = 1):(rid = 0);
   
         pci_intr_disestablish(adapter->osdep.pc, adapter->osdep.intr);          if (adapter->osdep.intr != NULL)
                   pci_intr_disestablish(adapter->osdep.pc, adapter->osdep.intr);
         adapter->osdep.intr = NULL;          adapter->osdep.intr = NULL;
   
 #if defined(NETBSD_MSI_OR_MSIX)  #if defined(NETBSD_MSI_OR_MSIX)
Line 2842  ixgbe_setup_interface(device_t dev, stru
Line 2945  ixgbe_setup_interface(device_t dev, stru
 #else  #else
         ifp->if_start = ixgbe_start;          ifp->if_start = ixgbe_start;
         IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 2);          IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 2);
   #if 0
           ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 2;
   #endif
           IFQ_SET_READY(&ifp->if_snd);
 #endif  #endif
   
         if_attach(ifp);          if_attach(ifp);
Line 3293  ixgbe_setup_transmit_ring(struct tx_ring
Line 3400  ixgbe_setup_transmit_ring(struct tx_ring
                  */                   */
                 if (slot) {                  if (slot) {
                         int si = netmap_idx_n2k(&na->tx_rings[txr->me], i);                          int si = netmap_idx_n2k(&na->tx_rings[txr->me], i);
                         netmap_load_map(txr->txtag, txbuf->map, NMB(slot + si));                          netmap_load_map(na, txr->txtag, txbuf->map, NMB(na, slot + si));
                 }                  }
 #endif /* DEV_NETMAP */  #endif /* DEV_NETMAP */
                 /* Clear the EOP descriptor pointer */                  /* Clear the EOP descriptor pointer */
Line 3436  ixgbe_free_transmit_buffers(struct tx_ri
Line 3543  ixgbe_free_transmit_buffers(struct tx_ri
         struct ixgbe_tx_buf *tx_buffer;          struct ixgbe_tx_buf *tx_buffer;
         int             i;          int             i;
   
         INIT_DEBUGOUT("free_transmit_ring: begin");          INIT_DEBUGOUT("ixgbe_free_transmit_ring: begin");
   
         if (txr->tx_buffers == NULL)          if (txr->tx_buffers == NULL)
                 return;                  return;
Line 3802  ixgbe_atr(struct tx_ring *txr, struct mb
Line 3909  ixgbe_atr(struct tx_ring *txr, struct mb
  *  tx_buffer is put back on the free queue.   *  tx_buffer is put back on the free queue.
  *   *
  **********************************************************************/   **********************************************************************/
 static bool  static void
 ixgbe_txeof(struct tx_ring *txr)  ixgbe_txeof(struct tx_ring *txr)
 {  {
         struct adapter          *adapter = txr->adapter;          struct adapter          *adapter = txr->adapter;
Line 3835  ixgbe_txeof(struct tx_ring *txr)
Line 3942  ixgbe_txeof(struct tx_ring *txr)
                  *   means the user thread should not be woken up);                   *   means the user thread should not be woken up);
                  * - the driver ignores tx interrupts unless netmap_mitigate=0                   * - the driver ignores tx interrupts unless netmap_mitigate=0
                  *   or the slot has the DD bit set.                   *   or the slot has the DD bit set.
                  *  
                  * When the driver has separate locks, we need to  
                  * release and re-acquire txlock to avoid deadlocks.  
                  * XXX see if we can find a better way.  
                  */                   */
                 if (!netmap_mitigate ||                  if (!netmap_mitigate ||
                     (kring->nr_kflags < kring->nkr_num_slots &&                      (kring->nr_kflags < kring->nkr_num_slots &&
                     txd[kring->nr_kflags].wb.status & IXGBE_TXD_STAT_DD)) {                      txd[kring->nr_kflags].wb.status & IXGBE_TXD_STAT_DD)) {
                         netmap_tx_irq(ifp, txr->me |                          netmap_tx_irq(ifp, txr->me);
                             (NETMAP_LOCKED_ENTER|NETMAP_LOCKED_EXIT));  
                 }                  }
                 return FALSE;                  return;
         }          }
 #endif /* DEV_NETMAP */  #endif /* DEV_NETMAP */
   
         if (txr->tx_avail == txr->num_desc) {          if (txr->tx_avail == txr->num_desc) {
                 txr->queue_status = IXGBE_QUEUE_IDLE;                  txr->queue_status = IXGBE_QUEUE_IDLE;
                 return false;                  return;
         }          }
   
         /* Get work starting point */          /* Get work starting point */
Line 3956  ixgbe_txeof(struct tx_ring *txr)
Line 4058  ixgbe_txeof(struct tx_ring *txr)
         if (!processed && tvtohz(&elapsed) > IXGBE_WATCHDOG)          if (!processed && tvtohz(&elapsed) > IXGBE_WATCHDOG)
                 txr->queue_status = IXGBE_QUEUE_HUNG;                  txr->queue_status = IXGBE_QUEUE_HUNG;
   
         if (txr->tx_avail == txr->num_desc) {          if (txr->tx_avail == txr->num_desc)
                 txr->queue_status = IXGBE_QUEUE_IDLE;                  txr->queue_status = IXGBE_QUEUE_IDLE;
                 return false;  
         }  
   
         return true;          return;
 }  }
   
 /*********************************************************************  /*********************************************************************
Line 4002  ixgbe_refresh_mbufs(struct rx_ring *rxr,
Line 4102  ixgbe_refresh_mbufs(struct rx_ring *rxr,
                         mp = rxbuf->buf;                          mp = rxbuf->buf;
   
                 mp->m_pkthdr.len = mp->m_len = rxr->mbuf_sz;                  mp->m_pkthdr.len = mp->m_len = rxr->mbuf_sz;
   
                 /* If we're dealing with an mbuf that was copied rather                  /* If we're dealing with an mbuf that was copied rather
                  * than replaced, there's no need to go through busdma.                   * than replaced, there's no need to go through busdma.
                  */                   */
Line 4185  ixgbe_free_receive_ring(struct rx_ring *
Line 4286  ixgbe_free_receive_ring(struct rx_ring *
                         rxbuf->buf->m_flags |= M_PKTHDR;                          rxbuf->buf->m_flags |= M_PKTHDR;
                         m_freem(rxbuf->buf);                          m_freem(rxbuf->buf);
                         rxbuf->buf = NULL;                          rxbuf->buf = NULL;
                           rxbuf->flags = 0;
                 }                  }
         }          }
 }  }
Line 4258  ixgbe_setup_receive_ring(struct rx_ring 
Line 4360  ixgbe_setup_receive_ring(struct rx_ring 
                         uint64_t paddr;                          uint64_t paddr;
                         void *addr;                          void *addr;
   
                         addr = PNMB(slot + sj, &paddr);                          addr = PNMB(na, slot + sj, &paddr);
                         netmap_load_map(rxr->ptag, rxbuf->pmap, addr);                          netmap_load_map(na, rxr->ptag, rxbuf->pmap, addr);
                         /* Update descriptor */                          /* Update descriptor and the cached value */
                         rxr->rx_base[j].read.pkt_addr = htole64(paddr);                          rxr->rx_base[j].read.pkt_addr = htole64(paddr);
                           rxbuf->addr = htole64(paddr);
                         continue;                          continue;
                 }                  }
 #endif /* DEV_NETMAP */  #endif /* DEV_NETMAP */
                   rxbuf->flags = 0;
                 rxbuf->buf = ixgbe_getjcl(&adapter->jcl_head, M_NOWAIT,                  rxbuf->buf = ixgbe_getjcl(&adapter->jcl_head, M_NOWAIT,
                     MT_DATA, M_PKTHDR, adapter->rx_mbuf_sz);                      MT_DATA, M_PKTHDR, adapter->rx_mbuf_sz);
                 if (rxbuf->buf == NULL) {                  if (rxbuf->buf == NULL) {
Line 4280  ixgbe_setup_receive_ring(struct rx_ring 
Line 4384  ixgbe_setup_receive_ring(struct rx_ring 
                         goto fail;                          goto fail;
                 bus_dmamap_sync(rxr->ptag->dt_dmat, rxbuf->pmap,                  bus_dmamap_sync(rxr->ptag->dt_dmat, rxbuf->pmap,
                     0, adapter->rx_mbuf_sz, BUS_DMASYNC_PREREAD);                      0, adapter->rx_mbuf_sz, BUS_DMASYNC_PREREAD);
                 /* Update descriptor */                  /* Update the descriptor and the cached value */
                 rxr->rx_base[j].read.pkt_addr =                  rxr->rx_base[j].read.pkt_addr =
                     htole64(rxbuf->pmap->dm_segs[0].ds_addr);                      htole64(rxbuf->pmap->dm_segs[0].ds_addr);
                   rxbuf->addr = htole64(rxbuf->pmap->dm_segs[0].ds_addr);
         }          }
   
   
Line 4292  ixgbe_setup_receive_ring(struct rx_ring 
Line 4397  ixgbe_setup_receive_ring(struct rx_ring 
         rxr->lro_enabled = FALSE;          rxr->lro_enabled = FALSE;
         rxr->rx_copies.ev_count = 0;          rxr->rx_copies.ev_count = 0;
         rxr->rx_bytes.ev_count = 0;          rxr->rx_bytes.ev_count = 0;
         rxr->discard = FALSE;  
         rxr->vtag_strip = FALSE;          rxr->vtag_strip = FALSE;
   
         ixgbe_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,          ixgbe_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
Line 4356  fail:
Line 4460  fail:
         return (ENOBUFS);          return (ENOBUFS);
 }  }
   
   static void
   ixgbe_initialise_rss_mapping(struct adapter *adapter)
   {
           struct ixgbe_hw *hw = &adapter->hw;
           uint32_t reta;
           int i, j, queue_id;
           uint32_t rss_key[10];
           uint32_t mrqc;
   #ifdef  RSS
           uint32_t rss_hash_config;
   #endif
   
           /* Setup RSS */
           reta = 0;
   
   #ifdef  RSS
           /* Fetch the configured RSS key */
           rss_getkey((uint8_t *) &rss_key);
   #else
           /* set up random bits */
           cprng_fast(&rss_key, sizeof(rss_key));
   #endif
   
           /* Set up the redirection table */
           for (i = 0, j = 0; i < 128; i++, j++) {
                   if (j == adapter->num_queues) j = 0;
   #ifdef  RSS
                   /*
                    * Fetch the RSS bucket id for the given indirection entry.
                    * Cap it at the number of configured buckets (which is
                    * num_queues.)
                    */
                   queue_id = rss_get_indirection_to_bucket(i);
                   queue_id = queue_id % adapter->num_queues;
   #else
                   queue_id = (j * 0x11);
   #endif
                   /*
                    * The low 8 bits are for hash value (n+0);
                    * The next 8 bits are for hash value (n+1), etc.
                    */
                   reta = reta >> 8;
                   reta = reta | ( ((uint32_t) queue_id) << 24);
                   if ((i & 3) == 3) {
                           IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
                           reta = 0;
                   }
           }
   
           /* Now fill our hash function seeds */
           for (i = 0; i < 10; i++)
                   IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rss_key[i]);
   
           /* Perform hash on these packet types */
   #ifdef  RSS
           mrqc = IXGBE_MRQC_RSSEN;
           rss_hash_config = rss_gethashconfig();
           if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4)
                   mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4;
           if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4)
                   mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP;
           if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6)
                   mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6;
           if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6)
                   mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
           if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX)
                   mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX;
           if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX)
                   mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP;
           if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4)
                   mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP;
           if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4_EX)
                   device_printf(adapter->dev,
                       "%s: RSS_HASHTYPE_RSS_UDP_IPV4_EX defined, "
                       "but not supported\n", __func__);
           if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6)
                   mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
           if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX)
                   mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
   #else
           /*
            * Disable UDP - IP fragments aren't currently being handled
            * and so we end up with a mix of 2-tuple and 4-tuple
            * traffic.
            */
           mrqc = IXGBE_MRQC_RSSEN
                | IXGBE_MRQC_RSS_FIELD_IPV4
                | IXGBE_MRQC_RSS_FIELD_IPV4_TCP
   #if 0
                | IXGBE_MRQC_RSS_FIELD_IPV4_UDP
   #endif
                | IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP
                | IXGBE_MRQC_RSS_FIELD_IPV6_EX
                | IXGBE_MRQC_RSS_FIELD_IPV6
                | IXGBE_MRQC_RSS_FIELD_IPV6_TCP
   #if 0
                | IXGBE_MRQC_RSS_FIELD_IPV6_UDP
                | IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP
   #endif
           ;
   #endif /* RSS */
           IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
   }
   
   
 /*********************************************************************  /*********************************************************************
  *   *
  *  Setup receive registers and features.   *  Setup receive registers and features.
Line 4373  ixgbe_initialize_receive_units(struct ad
Line 4582  ixgbe_initialize_receive_units(struct ad
         struct ixgbe_hw *hw = &adapter->hw;          struct ixgbe_hw *hw = &adapter->hw;
         struct ifnet   *ifp = adapter->ifp;          struct ifnet   *ifp = adapter->ifp;
         u32             bufsz, rxctrl, fctrl, srrctl, rxcsum;          u32             bufsz, rxctrl, fctrl, srrctl, rxcsum;
         u32             reta, mrqc = 0, hlreg, r[10];          u32             hlreg;
   
   
         /*          /*
Line 4425  ixgbe_initialize_receive_units(struct ad
Line 4634  ixgbe_initialize_receive_units(struct ad
                 srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;                  srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
                 srrctl |= bufsz;                  srrctl |= bufsz;
                 srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;                  srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
   
                   /*
                    * Set DROP_EN iff we have no flow control and >1 queue.
                    * Note that srrctl was cleared shortly before during reset,
                    * so we do not need to clear the bit, but do it just in case
                    * this code is moved elsewhere.
                    */
                   if (adapter->num_queues > 1 &&
                       adapter->fc == ixgbe_fc_none) {
                           srrctl |= IXGBE_SRRCTL_DROP_EN;
                   } else {
                           srrctl &= ~IXGBE_SRRCTL_DROP_EN;
                   }
   
                 IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(i), srrctl);                  IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(i), srrctl);
   
                 /* Setup the HW Rx Head and Tail Descriptor Pointers */                  /* Setup the HW Rx Head and Tail Descriptor Pointers */
Line 4445  ixgbe_initialize_receive_units(struct ad
Line 4668  ixgbe_initialize_receive_units(struct ad
   
         rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);          rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
   
         /* Setup RSS */          ixgbe_initialise_rss_mapping(adapter);
         if (adapter->num_queues > 1) {  
                 int j;  
                 reta = 0;  
   
                 /* set up random bits */  
                 cprng_fast(&r, sizeof(r));  
   
                 /* Set up the redirection table */  
                 for (i = 0, j = 0; i < 128; i++, j++) {  
                         if (j == adapter->num_queues) j = 0;  
                         reta = (reta << 8) | (j * 0x11);  
                         if ((i & 3) == 3)  
                                 IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);  
                 }  
   
                 /* Now fill our hash function seeds */  
                 for (i = 0; i < 10; i++)  
                         IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), r[i]);  
   
                 /* Perform hash on these packet types */  
                 mrqc = IXGBE_MRQC_RSSEN  
                      | IXGBE_MRQC_RSS_FIELD_IPV4  
                      | IXGBE_MRQC_RSS_FIELD_IPV4_TCP  
                      | IXGBE_MRQC_RSS_FIELD_IPV4_UDP  
                      | IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP  
                      | IXGBE_MRQC_RSS_FIELD_IPV6_EX  
                      | IXGBE_MRQC_RSS_FIELD_IPV6  
                      | IXGBE_MRQC_RSS_FIELD_IPV6_TCP  
                      | IXGBE_MRQC_RSS_FIELD_IPV6_UDP  
                      | IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;  
                 IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);  
   
           if (adapter->num_queues > 1) {
                 /* RSS and RX IPP Checksum are mutually exclusive */                  /* RSS and RX IPP Checksum are mutually exclusive */
                 rxcsum |= IXGBE_RXCSUM_PCSD;                  rxcsum |= IXGBE_RXCSUM_PCSD;
         }          }
Line 4503  ixgbe_free_receive_structures(struct ada
Line 4696  ixgbe_free_receive_structures(struct ada
 {  {
         struct rx_ring *rxr = adapter->rx_rings;          struct rx_ring *rxr = adapter->rx_rings;
   
           INIT_DEBUGOUT("ixgbe_free_receive_structures: begin");
   
         for (int i = 0; i < adapter->num_queues; i++, rxr++) {          for (int i = 0; i < adapter->num_queues; i++, rxr++) {
 #ifdef LRO  #ifdef LRO
                 struct lro_ctrl         *lro = &rxr->lro;                  struct lro_ctrl         *lro = &rxr->lro;
Line 4532  ixgbe_free_receive_buffers(struct rx_rin
Line 4727  ixgbe_free_receive_buffers(struct rx_rin
         struct adapter          *adapter = rxr->adapter;          struct adapter          *adapter = rxr->adapter;
         struct ixgbe_rx_buf     *rxbuf;          struct ixgbe_rx_buf     *rxbuf;
   
         INIT_DEBUGOUT("free_receive_structures: begin");          INIT_DEBUGOUT("ixgbe_free_receive_buffers: begin");
   
         /* Cleanup any existing buffers */          /* Cleanup any existing buffers */
         if (rxr->rx_buffers != NULL) {          if (rxr->rx_buffers != NULL) {
Line 4619  ixgbe_rx_discard(struct rx_ring *rxr, in
Line 4814  ixgbe_rx_discard(struct rx_ring *rxr, in
   
         rbuf = &rxr->rx_buffers[i];          rbuf = &rxr->rx_buffers[i];
   
         if (rbuf->fmp != NULL) {/* Partial chain ? */  
                 rbuf->fmp->m_flags |= M_PKTHDR;  
                 m_freem(rbuf->fmp);  
                 rbuf->fmp = NULL;  
         }  
   
         /*          /*
         ** With advanced descriptors the writeback          ** With advanced descriptors the writeback
Line 4632  ixgbe_rx_discard(struct rx_ring *rxr, in
Line 4822  ixgbe_rx_discard(struct rx_ring *rxr, in
         ** the normal refresh path to get new buffers          ** the normal refresh path to get new buffers
         ** and mapping.          ** and mapping.
         */          */
         if (rbuf->buf) {  
           if (rbuf->buf != NULL) {/* Partial chain ? */
                   rbuf->fmp->m_flags |= M_PKTHDR;
                   m_freem(rbuf->fmp);
                   rbuf->fmp = NULL;
                   rbuf->buf = NULL; /* rbuf->buf is part of fmp's chain */
           } else if (rbuf->buf) {
                 m_free(rbuf->buf);                  m_free(rbuf->buf);
                 rbuf->buf = NULL;                  rbuf->buf = NULL;
         }          }
   
           rbuf->flags = 0;
   
         return;          return;
 }  }
   
Line 4667  ixgbe_rxeof(struct ix_queue *que)
Line 4865  ixgbe_rxeof(struct ix_queue *que)
         u16                     count = rxr->process_limit;          u16                     count = rxr->process_limit;
         union ixgbe_adv_rx_desc *cur;          union ixgbe_adv_rx_desc *cur;
         struct ixgbe_rx_buf     *rbuf, *nbuf;          struct ixgbe_rx_buf     *rbuf, *nbuf;
   #ifdef RSS
           u16                     pkt_info;
   #endif
   
         IXGBE_RX_LOCK(rxr);          IXGBE_RX_LOCK(rxr);
   
 #ifdef DEV_NETMAP  #ifdef DEV_NETMAP
         /* Same as the txeof routine: wakeup clients on intr. */          /* Same as the txeof routine: wakeup clients on intr. */
         if (netmap_rx_irq(ifp, rxr->me | NETMAP_LOCKED_ENTER, &processed))          if (netmap_rx_irq(ifp, rxr->me, &processed)) {
                   IXGBE_RX_UNLOCK(rxr);
                 return (FALSE);                  return (FALSE);
           }
 #endif /* DEV_NETMAP */  #endif /* DEV_NETMAP */
   
         for (i = rxr->next_to_check; count != 0;) {          for (i = rxr->next_to_check; count != 0;) {
                 struct mbuf     *sendmp, *mp;                  struct mbuf     *sendmp, *mp;
                 u32             rsc, ptype;                  u32             rsc, ptype;
Line 4688  ixgbe_rxeof(struct ix_queue *que)
Line 4892  ixgbe_rxeof(struct ix_queue *que)
   
                 cur = &rxr->rx_base[i];                  cur = &rxr->rx_base[i];
                 staterr = le32toh(cur->wb.upper.status_error);                  staterr = le32toh(cur->wb.upper.status_error);
   #ifdef RSS
                   pkt_info = le16toh(cur->wb.lower.lo_dword.hs_rss.pkt_info);
   #endif
   
                 if ((staterr & IXGBE_RXD_STAT_DD) == 0)                  if ((staterr & IXGBE_RXD_STAT_DD) == 0)
                         break;                          break;
Line 4708  ixgbe_rxeof(struct ix_queue *que)
Line 4915  ixgbe_rxeof(struct ix_queue *que)
                 eop = ((staterr & IXGBE_RXD_STAT_EOP) != 0);                  eop = ((staterr & IXGBE_RXD_STAT_EOP) != 0);
   
                 /* Make sure bad packets are discarded */                  /* Make sure bad packets are discarded */
                 if (((staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) != 0) ||                  if (eop && (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) != 0) {
                     (rxr->discard)) {  
                         rxr->rx_discarded.ev_count++;                          rxr->rx_discarded.ev_count++;
                         if (eop)  
                                 rxr->discard = FALSE;  
                         else  
                                 rxr->discard = TRUE;  
                         ixgbe_rx_discard(rxr, i);                          ixgbe_rx_discard(rxr, i);
                         goto next_desc;                          goto next_desc;
                 }                  }
Line 4764  ixgbe_rxeof(struct ix_queue *que)
Line 4966  ixgbe_rxeof(struct ix_queue *que)
                 ** that determines what we are                  ** that determines what we are
                 */                  */
                 sendmp = rbuf->fmp;                  sendmp = rbuf->fmp;
   
                 if (sendmp != NULL) {  /* secondary frag */                  if (sendmp != NULL) {  /* secondary frag */
                         rbuf->buf = rbuf->fmp = NULL;                          rbuf->buf = rbuf->fmp = NULL;
                         mp->m_flags &= ~M_PKTHDR;                          mp->m_flags &= ~M_PKTHDR;
Line 4798  ixgbe_rxeof(struct ix_queue *que)
Line 4999  ixgbe_rxeof(struct ix_queue *que)
                         sendmp->m_pkthdr.len = mp->m_len;                          sendmp->m_pkthdr.len = mp->m_len;
                 }                  }
                 ++processed;                  ++processed;
   
                 /* Pass the head pointer on */                  /* Pass the head pointer on */
                 if (eop == 0) {                  if (eop == 0) {
                         nbuf->fmp = sendmp;                          nbuf->fmp = sendmp;
Line 4824  ixgbe_rxeof(struct ix_queue *que)
Line 5026  ixgbe_rxeof(struct ix_queue *que)
                                    &adapter->stats);                                     &adapter->stats);
                         }                          }
 #if __FreeBSD_version >= 800000  #if __FreeBSD_version >= 800000
   #ifdef RSS
                           sendmp->m_pkthdr.flowid =
                               le32toh(cur->wb.lower.hi_dword.rss);
                           switch (pkt_info & IXGBE_RXDADV_RSSTYPE_MASK) {
                           case IXGBE_RXDADV_RSSTYPE_IPV4_TCP:
                                   M_HASHTYPE_SET(sendmp, M_HASHTYPE_RSS_TCP_IPV4);
                                   break;
                           case IXGBE_RXDADV_RSSTYPE_IPV4:
                                   M_HASHTYPE_SET(sendmp, M_HASHTYPE_RSS_IPV4);
                                   break;
                           case IXGBE_RXDADV_RSSTYPE_IPV6_TCP:
                                   M_HASHTYPE_SET(sendmp, M_HASHTYPE_RSS_TCP_IPV6);
                                   break;
                           case IXGBE_RXDADV_RSSTYPE_IPV6_EX:
                                   M_HASHTYPE_SET(sendmp, M_HASHTYPE_RSS_IPV6_EX);
                                   break;
                           case IXGBE_RXDADV_RSSTYPE_IPV6:
                                   M_HASHTYPE_SET(sendmp, M_HASHTYPE_RSS_IPV6);
                                   break;
                           case IXGBE_RXDADV_RSSTYPE_IPV6_TCP_EX:
                                   M_HASHTYPE_SET(sendmp, M_HASHTYPE_RSS_TCP_IPV6_EX);
                                   break;
                           case IXGBE_RXDADV_RSSTYPE_IPV4_UDP:
                                   M_HASHTYPE_SET(sendmp, M_HASHTYPE_RSS_UDP_IPV4);
                                   break;
                           case IXGBE_RXDADV_RSSTYPE_IPV6_UDP:
                                   M_HASHTYPE_SET(sendmp, M_HASHTYPE_RSS_UDP_IPV6);
                                   break;
                           case IXGBE_RXDADV_RSSTYPE_IPV6_UDP_EX:
                                   M_HASHTYPE_SET(sendmp, M_HASHTYPE_RSS_UDP_IPV6_EX);
                                   break;
                           default:
                                   /* XXX fallthrough */
                                   M_HASHTYPE_SET(sendmp, M_HASHTYPE_OPAQUE);
                                   break;
                           }
   #else /* RSS */
                         sendmp->m_pkthdr.flowid = que->msix;                          sendmp->m_pkthdr.flowid = que->msix;
                         sendmp->m_flags |= M_FLOWID;                          M_HASHTYPE_SET(sendmp, M_HASHTYPE_OPAQUE);
 #endif  #endif /* RSS */
   #endif /* FreeBSD_version */
                 }                  }
 next_desc:  next_desc:
                 ixgbe_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,                  ixgbe_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
Line 4869  next_desc:
Line 5109  next_desc:
         IXGBE_RX_UNLOCK(rxr);          IXGBE_RX_UNLOCK(rxr);
   
         /*          /*
         ** We still have cleaning to do?          ** Still have cleaning to do?
         ** Schedule another interrupt if so.  
         */          */
         if ((staterr & IXGBE_RXD_STAT_DD) != 0) {          if ((staterr & IXGBE_RXD_STAT_DD) != 0)
                 ixgbe_rearm_queues(adapter, (u64)(1ULL << que->msix));  
                 return true;                  return true;
         }          else
                   return false;
         return false;  
 }  }
   
   
Line 4915  ixgbe_rx_checksum(u32 staterr, struct mb
Line 5152  ixgbe_rx_checksum(u32 staterr, struct mb
         }          }
         if (status & IXGBE_RXD_STAT_L4CS) {          if (status & IXGBE_RXD_STAT_L4CS) {
                 stats->l4cs.ev_count++;                  stats->l4cs.ev_count++;
                 u16 type = M_CSUM_TCPv4|M_CSUM_TCPv6|M_CSUM_UDPv4|M_CSUM_UDPv6;                  int type = M_CSUM_TCPv4|M_CSUM_TCPv6|M_CSUM_UDPv4|M_CSUM_UDPv6;
                 if (!(errors & IXGBE_RXD_ERR_TCPE)) {                  if (!(errors & IXGBE_RXD_ERR_TCPE)) {
                         mp->m_pkthdr.csum_flags |= type;                          mp->m_pkthdr.csum_flags |= type;
                 } else {                  } else {
Line 4951  ixgbe_register_vlan(void *arg, struct if
Line 5188  ixgbe_register_vlan(void *arg, struct if
         index = (vtag >> 5) & 0x7F;          index = (vtag >> 5) & 0x7F;
         bit = vtag & 0x1F;          bit = vtag & 0x1F;
         adapter->shadow_vfta[index] |= (1 << bit);          adapter->shadow_vfta[index] |= (1 << bit);
         ixgbe_init_locked(adapter);          ixgbe_setup_vlan_hw_support(adapter);
         IXGBE_CORE_UNLOCK(adapter);          IXGBE_CORE_UNLOCK(adapter);
 }  }
   
Line 4977  ixgbe_unregister_vlan(void *arg, struct 
Line 5214  ixgbe_unregister_vlan(void *arg, struct 
         bit = vtag & 0x1F;          bit = vtag & 0x1F;
         adapter->shadow_vfta[index] &= ~(1 << bit);          adapter->shadow_vfta[index] &= ~(1 << bit);
         /* Re-init to load the changes */          /* Re-init to load the changes */
         ixgbe_init_locked(adapter);          ixgbe_setup_vlan_hw_support(adapter);
         IXGBE_CORE_UNLOCK(adapter);          IXGBE_CORE_UNLOCK(adapter);
 }  }
 #endif  #endif
Line 4990  ixgbe_setup_vlan_hw_support(struct adapt
Line 5227  ixgbe_setup_vlan_hw_support(struct adapt
         struct rx_ring  *rxr;          struct rx_ring  *rxr;
         u32             ctrl;          u32             ctrl;
   
   
         /*          /*
         ** We get here thru init_locked, meaning          ** We get here thru init_locked, meaning
         ** a soft reset, this has already cleared          ** a soft reset, this has already cleared
Line 5000  ixgbe_setup_vlan_hw_support(struct adapt
Line 5238  ixgbe_setup_vlan_hw_support(struct adapt
                 return;                  return;
         }          }
   
           /* Setup the queues for vlans */
           for (int i = 0; i < adapter->num_queues; i++) {
                   rxr = &adapter->rx_rings[i];
                   /* On 82599 the VLAN enable is per/queue in RXDCTL */
                   if (hw->mac.type != ixgbe_mac_82598EB) {
                           ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
                           ctrl |= IXGBE_RXDCTL_VME;
                           IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), ctrl);
                   }
                   rxr->vtag_strip = TRUE;
           }
   
           if ((ec->ec_capenable & ETHERCAP_VLAN_HWFILTER) == 0)
                   return;
         /*          /*
         ** 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.
Line 5018  ixgbe_setup_vlan_hw_support(struct adapt
Line 5270  ixgbe_setup_vlan_hw_support(struct adapt
         if (hw->mac.type == ixgbe_mac_82598EB)          if (hw->mac.type == ixgbe_mac_82598EB)
                 ctrl |= IXGBE_VLNCTRL_VME;                  ctrl |= IXGBE_VLNCTRL_VME;
         IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl);          IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl);
   
         /* Setup the queues for vlans */  
         for (int i = 0; i < adapter->num_queues; i++) {  
                 rxr = &adapter->rx_rings[i];  
                 /* On 82599 the VLAN enable is per/queue in RXDCTL */  
                 if (hw->mac.type != ixgbe_mac_82598EB) {  
                         ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));  
                         ctrl |= IXGBE_RXDCTL_VME;  
                         IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), ctrl);  
                 }  
                 rxr->vtag_strip = TRUE;  
         }  
 }  }
   
 static void  static void
Line 5150  ixgbe_write_pci_cfg(struct ixgbe_hw *hw,
Line 5390  ixgbe_write_pci_cfg(struct ixgbe_hw *hw,
 }  }
   
 /*  /*
   ** Get the width and transaction speed of
   ** the slot this adapter is plugged into.
   */
   static void
   ixgbe_get_slot_info(struct ixgbe_hw *hw)
   {
           device_t                dev = ((struct ixgbe_osdep *)hw->back)->dev;
           struct ixgbe_mac_info   *mac = &hw->mac;
           u16                     link;
   
           /* For most devices simply call the shared code routine */
           if (hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) {
                   ixgbe_get_bus_info(hw);
                   goto display;
           }
   
           /*
           ** For the Quad port adapter we need to parse back
           ** up the PCI tree to find the speed of the expansion
           ** slot into which this adapter is plugged. A bit more work.
           */
           dev = device_parent(device_parent(dev));
   #ifdef IXGBE_DEBUG
           device_printf(dev, "parent pcib = %x,%x,%x\n",
               pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev));
   #endif
           dev = device_parent(device_parent(dev));
   #ifdef IXGBE_DEBUG
           device_printf(dev, "slot pcib = %x,%x,%x\n",
               pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev));
   #endif
           /* Now get the PCI Express Capabilities offset */
           /* ...and read the Link Status Register */
           link = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS);
           switch (link & IXGBE_PCI_LINK_WIDTH) {
           case IXGBE_PCI_LINK_WIDTH_1:
                   hw->bus.width = ixgbe_bus_width_pcie_x1;
                   break;
           case IXGBE_PCI_LINK_WIDTH_2:
                   hw->bus.width = ixgbe_bus_width_pcie_x2;
                   break;
           case IXGBE_PCI_LINK_WIDTH_4:
                   hw->bus.width = ixgbe_bus_width_pcie_x4;
                   break;
           case IXGBE_PCI_LINK_WIDTH_8:
                   hw->bus.width = ixgbe_bus_width_pcie_x8;
                   break;
           default:
                   hw->bus.width = ixgbe_bus_width_unknown;
                   break;
           }
   
           switch (link & IXGBE_PCI_LINK_SPEED) {
           case IXGBE_PCI_LINK_SPEED_2500:
                   hw->bus.speed = ixgbe_bus_speed_2500;
                   break;
           case IXGBE_PCI_LINK_SPEED_5000:
                   hw->bus.speed = ixgbe_bus_speed_5000;
                   break;
           case IXGBE_PCI_LINK_SPEED_8000:
                   hw->bus.speed = ixgbe_bus_speed_8000;
                   break;
           default:
                   hw->bus.speed = ixgbe_bus_speed_unknown;
                   break;
           }
   
           mac->ops.set_lan_id(hw);
   
   display:
           device_printf(dev,"PCI Express Bus: Speed %s %s\n",
               ((hw->bus.speed == ixgbe_bus_speed_8000) ? "8.0GT/s":
               (hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0GT/s":
               (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5GT/s":"Unknown"),
               (hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" :
               (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" :
               (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" :
               ("Unknown"));
   
           if ((hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) &&
               ((hw->bus.width <= ixgbe_bus_width_pcie_x4) &&
               (hw->bus.speed == ixgbe_bus_speed_2500))) {
                   device_printf(dev, "PCI-Express bandwidth available"
                       " for this card\n     is not sufficient for"
                       " optimal performance.\n");
                   device_printf(dev, "For optimal performance a x8 "
                       "PCIE, or x4 PCIE Gen2 slot is required.\n");
           }
           if ((hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP) &&
               ((hw->bus.width <= ixgbe_bus_width_pcie_x8) &&
               (hw->bus.speed < ixgbe_bus_speed_8000))) {
                   device_printf(dev, "PCI-Express bandwidth available"
                       " for this card\n     is not sufficient for"
                       " optimal performance.\n");
                   device_printf(dev, "For optimal performance a x8 "
                       "PCIE Gen3 slot is required.\n");
           }
   
           return;
   }
   
   
   /*
 ** Setup the correct IVAR register for a particular MSIX interrupt  ** Setup the correct IVAR register for a particular MSIX interrupt
 **   (yes this is all very magic and confusing :)  **   (yes this is all very magic and confusing :)
 **  - entry is the register array entry  **  - entry is the register array entry
Line 5988  ixgbe_set_flowcntl(SYSCTLFN_ARGS)
Line 6331  ixgbe_set_flowcntl(SYSCTLFN_ARGS)
         return 0;          return 0;
 }  }
   
   
 /*  /*
 ** Control link advertise speed:  ** Control link advertise speed:
 **      1 - advertise only 1G  **      1 - advertise only 1G
Line 6039  ixgbe_set_advertise(SYSCTLFN_ARGS)
Line 6383  ixgbe_set_advertise(SYSCTLFN_ARGS)
         else if (adapter->advertise == 3)          else if (adapter->advertise == 3)
                 speed = IXGBE_LINK_SPEED_1GB_FULL |                  speed = IXGBE_LINK_SPEED_1GB_FULL |
                         IXGBE_LINK_SPEED_10GB_FULL;                          IXGBE_LINK_SPEED_10GB_FULL;
         else {/* bogus value */          else {  /* bogus value */
                 adapter->advertise = last;                  adapter->advertise = last;
                 return (EINVAL);                  return (EINVAL);
         }          }
Line 6053  ixgbe_set_advertise(SYSCTLFN_ARGS)
Line 6397  ixgbe_set_advertise(SYSCTLFN_ARGS)
 /*  /*
 ** Thermal Shutdown Trigger  ** Thermal Shutdown Trigger
 **   - cause a Thermal Overtemp IRQ  **   - cause a Thermal Overtemp IRQ
   **   - this now requires firmware enabling
 */  */
 static int  static int
 ixgbe_set_thermal_test(SYSCTLFN_ARGS)  ixgbe_set_thermal_test(SYSCTLFN_ARGS)

Legend:
Removed from v.1.14.2.5  
changed lines
  Added in v.1.14.2.6

CVSweb <webmaster@jp.NetBSD.org>