Skip to content

Commit

Permalink
Merge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git…
Browse files Browse the repository at this point in the history
…/jkirsher/next-queue

Jeff Kirsher says:

====================
40GbE Intel Wired LAN Driver Updates 2018-02-12

This series contains updates to i40e and i40evf.

Alan fixes a spelling mistake in code comments.  Fixes an issue on older
firmware versions or NPAR enabled PFs which do not support the
I40E_FLAG_DISABLE_FW_LLDP flag and would get into a situation where any
attempt to change any priv flag would be forbidden.

Alex got busy with the ITR code and made several cleanups and fixes so
that we can more easily understand what is going on.  The fixes included
a computational fix when determining the register offset, as well as a
fix for unnecessarily toggling the CLEARPBA bit which could lead to
potential lost events if auto-masking is not enabled.

Filip adds a necessary delay to recover after a EMP reset when using
firmware version 4.33.

Paweł adds a warning message for MFP devices when the link-down-on-close
flag is set because it may affect other partitions.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Feb 13, 2018
2 parents 9b2c45d + a0073a4 commit cf19e5e
Show file tree
Hide file tree
Showing 12 changed files with 769 additions and 457 deletions.
3 changes: 1 addition & 2 deletions drivers/net/ethernet/intel/i40e/i40e.h
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,7 @@ struct i40e_q_vector {
struct i40e_ring_container rx;
struct i40e_ring_container tx;

u8 itr_countdown; /* when 0 should adjust adaptive ITR */
u8 num_ringpairs; /* total number of ring pairs in vector */

cpumask_t affinity_mask;
Expand All @@ -832,8 +833,6 @@ struct i40e_q_vector {
struct rcu_head rcu; /* to avoid race with update stats on free */
char name[I40E_INT_NAME_STR_LEN];
bool arm_wb_state;
#define ITR_COUNTDOWN_START 100
u8 itr_countdown; /* when 0 should adjust ITR */
} ____cacheline_internodealigned_in_smp;

/* lan device */
Expand Down
12 changes: 6 additions & 6 deletions drivers/net/ethernet/intel/i40e/i40e_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,9 +315,9 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
i, rx_ring->vsi,
rx_ring->q_vector);
dev_info(&pf->pdev->dev,
" rx_rings[%i]: rx_itr_setting = %d (%s)\n",
i, rx_ring->rx_itr_setting,
ITR_IS_DYNAMIC(rx_ring->rx_itr_setting) ? "dynamic" : "fixed");
" rx_rings[%i]: itr_setting = %d (%s)\n",
i, rx_ring->itr_setting,
ITR_IS_DYNAMIC(rx_ring->itr_setting) ? "dynamic" : "fixed");
}
for (i = 0; i < vsi->num_queue_pairs; i++) {
struct i40e_ring *tx_ring = READ_ONCE(vsi->tx_rings[i]);
Expand Down Expand Up @@ -366,9 +366,9 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
" tx_rings[%i]: DCB tc = %d\n",
i, tx_ring->dcb_tc);
dev_info(&pf->pdev->dev,
" tx_rings[%i]: tx_itr_setting = %d (%s)\n",
i, tx_ring->tx_itr_setting,
ITR_IS_DYNAMIC(tx_ring->tx_itr_setting) ? "dynamic" : "fixed");
" tx_rings[%i]: itr_setting = %d (%s)\n",
i, tx_ring->itr_setting,
ITR_IS_DYNAMIC(tx_ring->itr_setting) ? "dynamic" : "fixed");
}
rcu_read_unlock();
dev_info(&pf->pdev->dev,
Expand Down
81 changes: 48 additions & 33 deletions drivers/net/ethernet/intel/i40e/i40e_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -2244,14 +2244,14 @@ static int __i40e_get_coalesce(struct net_device *netdev,
rx_ring = vsi->rx_rings[queue];
tx_ring = vsi->tx_rings[queue];

if (ITR_IS_DYNAMIC(rx_ring->rx_itr_setting))
if (ITR_IS_DYNAMIC(rx_ring->itr_setting))
ec->use_adaptive_rx_coalesce = 1;

if (ITR_IS_DYNAMIC(tx_ring->tx_itr_setting))
if (ITR_IS_DYNAMIC(tx_ring->itr_setting))
ec->use_adaptive_tx_coalesce = 1;

ec->rx_coalesce_usecs = rx_ring->rx_itr_setting & ~I40E_ITR_DYNAMIC;
ec->tx_coalesce_usecs = tx_ring->tx_itr_setting & ~I40E_ITR_DYNAMIC;
ec->rx_coalesce_usecs = rx_ring->itr_setting & ~I40E_ITR_DYNAMIC;
ec->tx_coalesce_usecs = tx_ring->itr_setting & ~I40E_ITR_DYNAMIC;

/* we use the _usecs_high to store/set the interrupt rate limit
* that the hardware supports, that almost but not quite
Expand Down Expand Up @@ -2311,34 +2311,35 @@ static void i40e_set_itr_per_queue(struct i40e_vsi *vsi,
struct i40e_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
struct i40e_q_vector *q_vector;
u16 vector, intrl;
u16 intrl;

intrl = i40e_intrl_usec_to_reg(vsi->int_rate_limit);

rx_ring->rx_itr_setting = ec->rx_coalesce_usecs;
tx_ring->tx_itr_setting = ec->tx_coalesce_usecs;
rx_ring->itr_setting = ITR_REG_ALIGN(ec->rx_coalesce_usecs);
tx_ring->itr_setting = ITR_REG_ALIGN(ec->tx_coalesce_usecs);

if (ec->use_adaptive_rx_coalesce)
rx_ring->rx_itr_setting |= I40E_ITR_DYNAMIC;
rx_ring->itr_setting |= I40E_ITR_DYNAMIC;
else
rx_ring->rx_itr_setting &= ~I40E_ITR_DYNAMIC;
rx_ring->itr_setting &= ~I40E_ITR_DYNAMIC;

if (ec->use_adaptive_tx_coalesce)
tx_ring->tx_itr_setting |= I40E_ITR_DYNAMIC;
tx_ring->itr_setting |= I40E_ITR_DYNAMIC;
else
tx_ring->tx_itr_setting &= ~I40E_ITR_DYNAMIC;
tx_ring->itr_setting &= ~I40E_ITR_DYNAMIC;

q_vector = rx_ring->q_vector;
q_vector->rx.itr = ITR_TO_REG(rx_ring->rx_itr_setting);
vector = vsi->base_vector + q_vector->v_idx;
wr32(hw, I40E_PFINT_ITRN(I40E_RX_ITR, vector - 1), q_vector->rx.itr);
q_vector->rx.target_itr = ITR_TO_REG(rx_ring->itr_setting);

q_vector = tx_ring->q_vector;
q_vector->tx.itr = ITR_TO_REG(tx_ring->tx_itr_setting);
vector = vsi->base_vector + q_vector->v_idx;
wr32(hw, I40E_PFINT_ITRN(I40E_TX_ITR, vector - 1), q_vector->tx.itr);
q_vector->tx.target_itr = ITR_TO_REG(tx_ring->itr_setting);

wr32(hw, I40E_PFINT_RATEN(vector - 1), intrl);
/* The interrupt handler itself will take care of programming
* the Tx and Rx ITR values based on the values we have entered
* into the q_vector, no need to write the values now.
*/

wr32(hw, I40E_PFINT_RATEN(q_vector->reg_idx), intrl);
i40e_flush(hw);
}

Expand All @@ -2364,11 +2365,11 @@ static int __i40e_set_coalesce(struct net_device *netdev,
vsi->work_limit = ec->tx_max_coalesced_frames_irq;

if (queue < 0) {
cur_rx_itr = vsi->rx_rings[0]->rx_itr_setting;
cur_tx_itr = vsi->tx_rings[0]->tx_itr_setting;
cur_rx_itr = vsi->rx_rings[0]->itr_setting;
cur_tx_itr = vsi->tx_rings[0]->itr_setting;
} else if (queue < vsi->num_queue_pairs) {
cur_rx_itr = vsi->rx_rings[queue]->rx_itr_setting;
cur_tx_itr = vsi->tx_rings[queue]->tx_itr_setting;
cur_rx_itr = vsi->rx_rings[queue]->itr_setting;
cur_tx_itr = vsi->tx_rings[queue]->itr_setting;
} else {
netif_info(pf, drv, netdev, "Invalid queue value, queue range is 0 - %d\n",
vsi->num_queue_pairs - 1);
Expand Down Expand Up @@ -2396,7 +2397,7 @@ static int __i40e_set_coalesce(struct net_device *netdev,
return -EINVAL;
}

if (ec->rx_coalesce_usecs > (I40E_MAX_ITR << 1)) {
if (ec->rx_coalesce_usecs > I40E_MAX_ITR) {
netif_info(pf, drv, netdev, "Invalid value, rx-usecs range is 0-8160\n");
return -EINVAL;
}
Expand All @@ -2407,16 +2408,16 @@ static int __i40e_set_coalesce(struct net_device *netdev,
return -EINVAL;
}

if (ec->tx_coalesce_usecs > (I40E_MAX_ITR << 1)) {
if (ec->tx_coalesce_usecs > I40E_MAX_ITR) {
netif_info(pf, drv, netdev, "Invalid value, tx-usecs range is 0-8160\n");
return -EINVAL;
}

if (ec->use_adaptive_rx_coalesce && !cur_rx_itr)
ec->rx_coalesce_usecs = I40E_MIN_ITR << 1;
ec->rx_coalesce_usecs = I40E_MIN_ITR;

if (ec->use_adaptive_tx_coalesce && !cur_tx_itr)
ec->tx_coalesce_usecs = I40E_MIN_ITR << 1;
ec->tx_coalesce_usecs = I40E_MIN_ITR;

intrl_reg = i40e_intrl_usec_to_reg(ec->rx_coalesce_usecs_high);
vsi->int_rate_limit = INTRL_REG_TO_USEC(intrl_reg);
Expand Down Expand Up @@ -4406,6 +4407,8 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
}

flags_complete:
changed_flags = orig_flags ^ new_flags;

/* Before we finalize any flag changes, we need to perform some
* checks to ensure that the changes are supported and safe.
*/
Expand All @@ -4415,21 +4418,25 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
!(pf->hw_features & I40E_HW_ATR_EVICT_CAPABLE))
return -EOPNOTSUPP;

/* Disable FW LLDP not supported if NPAR active or if FW
* API version < 1.7
/* If the driver detected FW LLDP was disabled on init, this flag could
* be set, however we do not support _changing_ the flag if NPAR is
* enabled or FW API version < 1.7. There are situations where older
* FW versions/NPAR enabled PFs could disable LLDP, however we _must_
* not allow the user to enable/disable LLDP with this flag on
* unsupported FW versions.
*/
if (new_flags & I40E_FLAG_DISABLE_FW_LLDP) {
if (changed_flags & I40E_FLAG_DISABLE_FW_LLDP) {
if (pf->hw.func_caps.npar_enable) {
dev_warn(&pf->pdev->dev,
"Unable to stop FW LLDP if NPAR active\n");
"Unable to change FW LLDP if NPAR active\n");
return -EOPNOTSUPP;
}

if (pf->hw.aq.api_maj_ver < 1 ||
(pf->hw.aq.api_maj_ver == 1 &&
pf->hw.aq.api_min_ver < 7)) {
dev_warn(&pf->pdev->dev,
"FW ver does not support stopping FW LLDP\n");
"FW ver does not support changing FW LLDP\n");
return -EOPNOTSUPP;
}
}
Expand All @@ -4439,15 +4446,17 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
* something else has modified the flags variable since we copied it
* originally. We'll just punt with an error and log something in the
* message buffer.
*
* This is the point of no return for this function. We need to have
* checked any discrepancies or misconfigurations and returned
* EOPNOTSUPP before updating pf->flags here.
*/
if (cmpxchg64(&pf->flags, orig_flags, new_flags) != orig_flags) {
dev_warn(&pf->pdev->dev,
"Unable to update pf->flags as it was modified by another thread...\n");
return -EAGAIN;
}

changed_flags = orig_flags ^ new_flags;

/* Process any additional changes needed as a result of flag changes.
* The changed_flags value reflects the list of bits that were
* changed in the code above.
Expand Down Expand Up @@ -4479,6 +4488,12 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
}
}

if ((changed_flags & pf->flags &
I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED) &&
(pf->flags & I40E_FLAG_MFP_ENABLED))
dev_warn(&pf->pdev->dev,
"Turning on link-down-on-close flag may affect other partitions\n");

if (changed_flags & I40E_FLAG_DISABLE_FW_LLDP) {
if (pf->flags & I40E_FLAG_DISABLE_FW_LLDP) {
struct i40e_dcbx_config *dcbcfg;
Expand Down
54 changes: 34 additions & 20 deletions drivers/net/ethernet/intel/i40e/i40e_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3449,15 +3449,20 @@ static void i40e_vsi_configure_msix(struct i40e_vsi *vsi)
for (i = 0; i < vsi->num_q_vectors; i++, vector++) {
struct i40e_q_vector *q_vector = vsi->q_vectors[i];

q_vector->itr_countdown = ITR_COUNTDOWN_START;
q_vector->rx.itr = ITR_TO_REG(vsi->rx_rings[i]->rx_itr_setting);
q_vector->rx.latency_range = I40E_LOW_LATENCY;
q_vector->rx.next_update = jiffies + 1;
q_vector->rx.target_itr =
ITR_TO_REG(vsi->rx_rings[i]->itr_setting);
wr32(hw, I40E_PFINT_ITRN(I40E_RX_ITR, vector - 1),
q_vector->rx.itr);
q_vector->tx.itr = ITR_TO_REG(vsi->tx_rings[i]->tx_itr_setting);
q_vector->tx.latency_range = I40E_LOW_LATENCY;
q_vector->rx.target_itr);
q_vector->rx.current_itr = q_vector->rx.target_itr;

q_vector->tx.next_update = jiffies + 1;
q_vector->tx.target_itr =
ITR_TO_REG(vsi->tx_rings[i]->itr_setting);
wr32(hw, I40E_PFINT_ITRN(I40E_TX_ITR, vector - 1),
q_vector->tx.itr);
q_vector->tx.target_itr);
q_vector->tx.current_itr = q_vector->tx.target_itr;

wr32(hw, I40E_PFINT_RATEN(vector - 1),
i40e_intrl_usec_to_reg(vsi->int_rate_limit));

Expand Down Expand Up @@ -3558,13 +3563,14 @@ static void i40e_configure_msi_and_legacy(struct i40e_vsi *vsi)
u32 val;

/* set the ITR configuration */
q_vector->itr_countdown = ITR_COUNTDOWN_START;
q_vector->rx.itr = ITR_TO_REG(vsi->rx_rings[0]->rx_itr_setting);
q_vector->rx.latency_range = I40E_LOW_LATENCY;
wr32(hw, I40E_PFINT_ITR0(I40E_RX_ITR), q_vector->rx.itr);
q_vector->tx.itr = ITR_TO_REG(vsi->tx_rings[0]->tx_itr_setting);
q_vector->tx.latency_range = I40E_LOW_LATENCY;
wr32(hw, I40E_PFINT_ITR0(I40E_TX_ITR), q_vector->tx.itr);
q_vector->rx.next_update = jiffies + 1;
q_vector->rx.target_itr = ITR_TO_REG(vsi->rx_rings[0]->itr_setting);
wr32(hw, I40E_PFINT_ITR0(I40E_RX_ITR), q_vector->rx.target_itr);
q_vector->rx.current_itr = q_vector->rx.target_itr;
q_vector->tx.next_update = jiffies + 1;
q_vector->tx.target_itr = ITR_TO_REG(vsi->tx_rings[0]->itr_setting);
wr32(hw, I40E_PFINT_ITR0(I40E_TX_ITR), q_vector->tx.target_itr);
q_vector->tx.current_itr = q_vector->tx.target_itr;

i40e_enable_misc_int_causes(pf);

Expand Down Expand Up @@ -9215,6 +9221,17 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
}
i40e_get_oem_version(&pf->hw);

if (test_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state) &&
((hw->aq.fw_maj_ver == 4 && hw->aq.fw_min_ver <= 33) ||
hw->aq.fw_maj_ver < 4) && hw->mac.type == I40E_MAC_XL710) {
/* The following delay is necessary for 4.33 firmware and older
* to recover after EMP reset. 200 ms should suffice but we
* put here 300 ms to be sure that FW is ready to operate
* after reset.
*/
mdelay(300);
}

/* re-verify the eeprom if we just had an EMP reset */
if (test_and_clear_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state))
i40e_verify_eeprom(pf);
Expand Down Expand Up @@ -10018,7 +10035,7 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi)
ring->dcb_tc = 0;
if (vsi->back->hw_features & I40E_HW_WB_ON_ITR_CAPABLE)
ring->flags = I40E_TXR_FLAGS_WB_ON_ITR;
ring->tx_itr_setting = pf->tx_itr_default;
ring->itr_setting = pf->tx_itr_default;
vsi->tx_rings[i] = ring++;

if (!i40e_enabled_xdp_vsi(vsi))
Expand All @@ -10036,7 +10053,7 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi)
if (vsi->back->hw_features & I40E_HW_WB_ON_ITR_CAPABLE)
ring->flags = I40E_TXR_FLAGS_WB_ON_ITR;
set_ring_xdp(ring);
ring->tx_itr_setting = pf->tx_itr_default;
ring->itr_setting = pf->tx_itr_default;
vsi->xdp_rings[i] = ring++;

setup_rx:
Expand All @@ -10049,7 +10066,7 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi)
ring->count = vsi->num_desc;
ring->size = 0;
ring->dcb_tc = 0;
ring->rx_itr_setting = pf->rx_itr_default;
ring->itr_setting = pf->rx_itr_default;
vsi->rx_rings[i] = ring;
}

Expand Down Expand Up @@ -10328,9 +10345,6 @@ static int i40e_vsi_alloc_q_vector(struct i40e_vsi *vsi, int v_idx, int cpu)
netif_napi_add(vsi->netdev, &q_vector->napi,
i40e_napi_poll, NAPI_POLL_WEIGHT);

q_vector->rx.latency_range = I40E_LOW_LATENCY;
q_vector->tx.latency_range = I40E_LOW_LATENCY;

/* tie q_vector and vsi together */
vsi->q_vectors[v_idx] = q_vector;

Expand Down
Loading

0 comments on commit cf19e5e

Please sign in to comment.