Print this page
NEX-20178 Heavy read load using 10G i40e causes network disconnect
MFV illumos-joyent@83a8d0d616db36010b59cc850d1926c0f6a30de1
OS-7457 i40e Tx freezes on zero descriptors
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Rob Johnston <rob.johnston@joyent.com>
Approved by: Robert Mustacchi <rm@joyent.com>
MFV illumos-joyent@0d3f2b61dcfb18edace4fd257054f6fdbe07c99c
OS-7492 i40e Tx freeze when b_cont chain exceeds 8 descriptors
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Rob Johnston <rob.johnston@joyent.com>
Approved by: Robert Mustacchi <rm@joyent.com>
MFV illumos-joyent@b4bede175d4c50ac1b36078a677b69388f6fb59f
OS-7577 initialize FC for i40e
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Rob Johnston <rob.johnston@joyent.com>
MFV illumos-joyent@83a8d0d616db36010b59cc850d1926c0f6a30de1
OS-7457 i40e Tx freezes on zero descriptors
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Rob Johnston <rob.johnston@joyent.com>
Approved by: Robert Mustacchi <rm@joyent.com>
MFV: illumos-joyent@61dc3dec4f82a3e13e94609a0a83d5f66c64e760
OS-6846 want i40e multi-group support
OS-7372 i40e_alloc_ring_mem() unwinds when it shouldn't
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Robert Mustacchi <rm@joyent.com>
Author: Ryan Zezeski <rpz@joyent.com>
MFV: illumos-joyent@757454db6669c1186f60bc625510c1b67217aae6
OS-7082 i40e: blown assert in i40e_tx_cleanup_ring()
OS-7086 i40e: add mdb dcmd to dump info on tx descriptor rings
OS-7101 i40e: add kstat to track TX DMA bind failures
Reviewed by: Ryan Zezeski <rpz@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Patrick Mooney <patrick.mooney@joyent.com>
Author: Rob Johnston <rob.johnston@joyent.com>
MFV: illumos-joyent@9e30beee2f0c127bf41868db46257124206e28d6
OS-5225 Want Fortville TSO support
Reviewed by: Ryan Zezeski <rpz@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Patrick Mooney <patrick.mooney@joyent.com>
Author: Rob Johnston <rob.johnston@joyent.com>
        
*** 9,19 ****
   * http://www.illumos.org/license/CDDL.
   */
  
  /*
   * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
!  * Copyright 2016 Joyent, Inc.
   */
  
  #include "i40e_sw.h"
  
  /*
--- 9,19 ----
   * http://www.illumos.org/license/CDDL.
   */
  
  /*
   * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
!  * Copyright 2019 Joyent, Inc.
   */
  
  #include "i40e_sw.h"
  
  /*
*** 67,82 ****
   * ---------------------
   * Hardware Arrangements
   * ---------------------
   *
   * The hardware keeps statistics at each physical function/MAC (PF) and it keeps
!  * statistics on each virtual station interface (VSI). Currently we only use one
!  * VSI per PF (see the i40e_main.c theory statement). The hardware has a limited
!  * number of statistics units available. While every PF is guaranteed to have a
!  * statistics unit, it is possible that we will run out for a given VSI. We'll
!  * have to figure out an appropriate strategy here when we end up supporting
!  * multiple VSIs.
   *
   * The hardware keeps these statistics as 32-bit and 48-bit counters. We are
   * required to read them and then compute the differences between them. The
   * 48-bit counters span more than one 32-bit register in the BAR. The hardware
   * suggests that to read them, we perform 64-bit reads of the lower of the two
--- 67,77 ----
   * ---------------------
   * Hardware Arrangements
   * ---------------------
   *
   * The hardware keeps statistics at each physical function/MAC (PF) and it keeps
!  * statistics on each virtual station interface (VSI).
   *
   * The hardware keeps these statistics as 32-bit and 48-bit counters. We are
   * required to read them and then compute the differences between them. The
   * 48-bit counters span more than one 32-bit register in the BAR. The hardware
   * suggests that to read them, we perform 64-bit reads of the lower of the two
*** 98,111 ****
   * isn't the most reassuring statement and we should investigate ways of
   * ensuring that if a system is active, but not actively measured, we don't lose
   * data.
   *
   * The pf kstats data is stored in the i40e_t`i40e_pf_kstat. It is backed by the
!  * i40e_t`i40e_pf_stat structure. Similarly the VSI related kstat is in
!  * i40e_t`i40e_vsi_kstat and the data is backed in the i40e_t`i40e_vsi_stat. All
!  * of this data is protected by the i40e_stat_lock, which should be taken last,
!  * when acquiring locks.
   */
  
  static void
  i40e_stat_get_uint48(i40e_t *i40e, uintptr_t reg, kstat_named_t *kstat,
      uint64_t *base, boolean_t init)
--- 93,106 ----
   * isn't the most reassuring statement and we should investigate ways of
   * ensuring that if a system is active, but not actively measured, we don't lose
   * data.
   *
   * The pf kstats data is stored in the i40e_t`i40e_pf_kstat. It is backed by the
!  * i40e_t`i40e_pf_stat structure. Similarly the VSI related kstats are in
!  * i40e_t`i40e_vsis[idx].iv_kstats and the data is backed in the
!  * i40e_t`i40e_vsis[idx].iv_stats. All of this data is protected by the
!  * i40e_stat_lock, which should be taken last, when acquiring locks.
   */
  
  static void
  i40e_stat_get_uint48(i40e_t *i40e, uintptr_t reg, kstat_named_t *kstat,
      uint64_t *base, boolean_t init)
*** 167,185 ****
          *base = raw;
  
  }
  
  static void
! i40e_stat_vsi_update(i40e_t *i40e, boolean_t init)
  {
          i40e_vsi_stats_t *ivs;
          i40e_vsi_kstats_t *ivk;
!         int id = i40e->i40e_vsi_stat_id;
  
!         ASSERT(i40e->i40e_vsi_kstat != NULL);
!         ivs = &i40e->i40e_vsi_stat;
!         ivk = i40e->i40e_vsi_kstat->ks_data;
  
          mutex_enter(&i40e->i40e_stat_lock);
  
          i40e_stat_get_uint48(i40e, I40E_GLV_GORCL(id), &ivk->ivk_rx_bytes,
              &ivs->ivs_rx_bytes, init);
--- 162,180 ----
          *base = raw;
  
  }
  
  static void
! i40e_stat_vsi_update(i40e_t *i40e, uint_t idx, boolean_t init)
  {
          i40e_vsi_stats_t *ivs;
          i40e_vsi_kstats_t *ivk;
!         uint16_t id = i40e->i40e_vsis[idx].iv_stats_id;
  
!         ASSERT3P(i40e->i40e_vsis[idx].iv_kstats, !=, NULL);
!         ivs = &i40e->i40e_vsis[idx].iv_stats;
!         ivk = i40e->i40e_vsis[idx].iv_kstats->ks_data;
  
          mutex_enter(&i40e->i40e_stat_lock);
  
          i40e_stat_get_uint48(i40e, I40E_GLV_GORCL(id), &ivk->ivk_rx_bytes,
              &ivs->ivs_rx_bytes, init);
*** 229,271 ****
  
          if (rw == KSTAT_WRITE)
                  return (EACCES);
  
          i40e = ksp->ks_private;
!         i40e_stat_vsi_update(i40e, B_FALSE);
          return (0);
  }
  
  void
! i40e_stat_vsi_fini(i40e_t *i40e)
  {
!         if (i40e->i40e_vsi_kstat != NULL) {
!                 kstat_delete(i40e->i40e_vsi_kstat);
!                 i40e->i40e_vsi_kstat = NULL;
          }
  }
  
  boolean_t
! i40e_stat_vsi_init(i40e_t *i40e)
  {
          kstat_t *ksp;
          i40e_vsi_kstats_t *ivk;
          char buf[64];
  
!         (void) snprintf(buf, sizeof (buf), "vsi_%d", i40e->i40e_vsi_id);
  
          ksp = kstat_create(I40E_MODULE_NAME, ddi_get_instance(i40e->i40e_dip),
              buf, "net", KSTAT_TYPE_NAMED,
              sizeof (i40e_vsi_kstats_t) / sizeof (kstat_named_t), 0);
  
          if (ksp == NULL) {
!                 i40e_error(i40e, "Failed to create kstats for VSI %d",
!                     i40e->i40e_vsi_id);
                  return (B_FALSE);
          }
  
!         i40e->i40e_vsi_kstat = ksp;
          ivk = ksp->ks_data;
          ksp->ks_update = i40e_stat_vsi_kstat_update;
          ksp->ks_private = i40e;
  
          kstat_named_init(&ivk->ivk_rx_bytes, "rx_bytes",
--- 224,268 ----
  
          if (rw == KSTAT_WRITE)
                  return (EACCES);
  
          i40e = ksp->ks_private;
!         for (uint_t i = 0; i < i40e->i40e_num_rx_groups; i++)
!                 i40e_stat_vsi_update(i40e, i, B_FALSE);
! 
          return (0);
  }
  
  void
! i40e_stat_vsi_fini(i40e_t *i40e, uint_t idx)
  {
!         if (i40e->i40e_vsis[idx].iv_kstats != NULL) {
!                 kstat_delete(i40e->i40e_vsis[idx].iv_kstats);
!                 i40e->i40e_vsis[idx].iv_kstats = NULL;
          }
  }
  
  boolean_t
! i40e_stat_vsi_init(i40e_t *i40e, uint_t idx)
  {
          kstat_t *ksp;
          i40e_vsi_kstats_t *ivk;
          char buf[64];
+         uint16_t vsi_id = i40e->i40e_vsis[idx].iv_seid;
  
!         (void) snprintf(buf, sizeof (buf), "vsi_%u", vsi_id);
  
          ksp = kstat_create(I40E_MODULE_NAME, ddi_get_instance(i40e->i40e_dip),
              buf, "net", KSTAT_TYPE_NAMED,
              sizeof (i40e_vsi_kstats_t) / sizeof (kstat_named_t), 0);
  
          if (ksp == NULL) {
!                 i40e_error(i40e, "Failed to create kstats for VSI %u", vsi_id);
                  return (B_FALSE);
          }
  
!         i40e->i40e_vsis[idx].iv_kstats = ksp;
          ivk = ksp->ks_data;
          ksp->ks_update = i40e_stat_vsi_kstat_update;
          ksp->ks_private = i40e;
  
          kstat_named_init(&ivk->ivk_rx_bytes, "rx_bytes",
*** 289,301 ****
          kstat_named_init(&ivk->ivk_tx_broadcast, "tx_broadcast",
              KSTAT_DATA_UINT64);
          kstat_named_init(&ivk->ivk_tx_errors, "tx_errors",
              KSTAT_DATA_UINT64);
  
!         bzero(&i40e->i40e_vsi_stat, sizeof (i40e_vsi_stats_t));
!         i40e_stat_vsi_update(i40e, B_TRUE);
!         kstat_install(i40e->i40e_vsi_kstat);
  
          return (B_TRUE);
  }
  
  static void
--- 286,298 ----
          kstat_named_init(&ivk->ivk_tx_broadcast, "tx_broadcast",
              KSTAT_DATA_UINT64);
          kstat_named_init(&ivk->ivk_tx_errors, "tx_errors",
              KSTAT_DATA_UINT64);
  
!         bzero(&i40e->i40e_vsis[idx].iv_stats, sizeof (i40e_vsi_stats_t));
!         i40e_stat_vsi_update(i40e, idx, B_TRUE);
!         kstat_install(i40e->i40e_vsis[idx].iv_kstats);
  
          return (B_TRUE);
  }
  
  static void
*** 668,678 ****
  }
  
  void
  i40e_stats_fini(i40e_t *i40e)
  {
!         ASSERT(i40e->i40e_vsi_kstat == NULL);
          if (i40e->i40e_pf_kstat != NULL) {
                  kstat_delete(i40e->i40e_pf_kstat);
                  i40e->i40e_pf_kstat = NULL;
          }
  
--- 665,680 ----
  }
  
  void
  i40e_stats_fini(i40e_t *i40e)
  {
! #ifdef DEBUG
!         for (uint_t i = 0; i < i40e->i40e_num_rx_groups; i++) {
!                 ASSERT3P(i40e->i40e_vsis[i].iv_kstats, ==, NULL);
!         }
! #endif
! 
          if (i40e->i40e_pf_kstat != NULL) {
                  kstat_delete(i40e->i40e_pf_kstat);
                  i40e->i40e_pf_kstat = NULL;
          }
  
*** 1228,1237 ****
--- 1230,1245 ----
              KSTAT_DATA_UINT64);
          tsp->itxs_descriptors.value.ui64 = 0;
          kstat_named_init(&tsp->itxs_recycled, "tx_recycled",
              KSTAT_DATA_UINT64);
          tsp->itxs_recycled.value.ui64 = 0;
+         kstat_named_init(&tsp->itxs_force_copy, "tx_force_copy",
+             KSTAT_DATA_UINT64);
+         tsp->itxs_force_copy.value.ui64 = 0;
+         kstat_named_init(&tsp->itxs_tso_force_copy, "tx_tso_force_copy",
+             KSTAT_DATA_UINT64);
+         tsp->itxs_tso_force_copy.value.ui64 = 0;
  
          kstat_named_init(&tsp->itxs_hck_meoifail, "tx_hck_meoifail",
              KSTAT_DATA_UINT64);
          tsp->itxs_hck_meoifail.value.ui64 = 0;
          kstat_named_init(&tsp->itxs_hck_nol2info, "tx_hck_nol2info",
*** 1247,1256 ****
--- 1255,1270 ----
              KSTAT_DATA_UINT64);
          tsp->itxs_hck_badl3.value.ui64 = 0;
          kstat_named_init(&tsp->itxs_hck_badl4, "tx_hck_badl4",
              KSTAT_DATA_UINT64);
          tsp->itxs_hck_badl4.value.ui64 = 0;
+         kstat_named_init(&tsp->itxs_lso_nohck, "tx_lso_nohck",
+             KSTAT_DATA_UINT64);
+         tsp->itxs_lso_nohck.value.ui64 = 0;
+         kstat_named_init(&tsp->itxs_bind_fails, "tx_bind_fails",
+             KSTAT_DATA_UINT64);
+         tsp->itxs_bind_fails.value.ui64 = 0;
          kstat_named_init(&tsp->itxs_err_notcb, "tx_err_notcb",
              KSTAT_DATA_UINT64);
          tsp->itxs_err_notcb.value.ui64 = 0;
          kstat_named_init(&tsp->itxs_err_nodescs, "tx_err_nodescs",
              KSTAT_DATA_UINT64);