Skip to content

Commit

Permalink
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/jkirsher/net-next

Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates

This series contains updates to e1000e, igb, i40e and i40evf

Anjali provides i40e fix to remove the ATR filter on RST as well as FIN
packets.  Cleans up add_del_fdir() because it was used and implemented
only for the add, so change the name and drop a parameter.  Adds the
ability to drop a flow if we wanted to and adds a flow director
message level to be used for flow director specific messages.

Mitch fixes an issue on i40evf where the Tx watchdog handler was causing
an oops when sending an admin queue message to request a reset because
the admin queue functions use spinlocks.

Greg provides a change to i40e to make the alloc and free queue vector
calls orthogonal.

Shannon fixes i40e to verify the eeprom checksum and firmware CRC status
bits, and shutdown the driver if they fail.  This change stops the
processing of traffic, but does not kill the PF netdev so that the
NVMUpdate process still has a chance at fixing the image.  Also provides
a fix to make sure the VSI has a netdev before trying to use it in
the debugfs netdev_ops commands.

Jakub Kicinski provides patches for e1000e and igb to fix a number issues
found in the PTP code.

v2:
- drop patch 11 "i40e: Add a fallback debug flow for the driver" from the
  series based on feedback from David Miller
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 28, 2014
2 parents 2405e8f + ed4420a commit c8c3d7e
Show file tree
Hide file tree
Showing 16 changed files with 131 additions and 61 deletions.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/intel/e1000e/e1000.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ struct e1000_adapter {
u32 tx_head_addr;
u32 tx_fifo_size;
u32 tx_dma_failed;
u32 tx_hwtstamp_timeouts;

/* Rx */
bool (*clean_rx) (struct e1000_ring *ring, int *work_done,
Expand Down Expand Up @@ -334,6 +335,7 @@ struct e1000_adapter {
struct hwtstamp_config hwtstamp_config;
struct delayed_work systim_overflow_work;
struct sk_buff *tx_hwtstamp_skb;
unsigned long tx_hwtstamp_start;
struct work_struct tx_hwtstamp_work;
spinlock_t systim_lock; /* protects SYSTIML/H regsters */
struct cyclecounter cc;
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/e1000e/ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
E1000_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
E1000_STAT("uncorr_ecc_errors", uncorr_errors),
E1000_STAT("corr_ecc_errors", corr_errors),
E1000_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts),
};

#define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats)
Expand Down
10 changes: 7 additions & 3 deletions drivers/net/ethernet/intel/e1000e/netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1148,9 +1148,6 @@ static void e1000e_tx_hwtstamp_work(struct work_struct *work)
tx_hwtstamp_work);
struct e1000_hw *hw = &adapter->hw;

if (!adapter->tx_hwtstamp_skb)
return;

if (er32(TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID) {
struct skb_shared_hwtstamps shhwtstamps;
u64 txstmp;
Expand All @@ -1163,6 +1160,12 @@ static void e1000e_tx_hwtstamp_work(struct work_struct *work)
skb_tstamp_tx(adapter->tx_hwtstamp_skb, &shhwtstamps);
dev_kfree_skb_any(adapter->tx_hwtstamp_skb);
adapter->tx_hwtstamp_skb = NULL;
} else if (time_after(jiffies, adapter->tx_hwtstamp_start
+ adapter->tx_timeout_factor * HZ)) {
dev_kfree_skb_any(adapter->tx_hwtstamp_skb);
adapter->tx_hwtstamp_skb = NULL;
adapter->tx_hwtstamp_timeouts++;
e_warn("clearing Tx timestamp hang");
} else {
/* reschedule to check later */
schedule_work(&adapter->tx_hwtstamp_work);
Expand Down Expand Up @@ -5567,6 +5570,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
tx_flags |= E1000_TX_FLAGS_HWTSTAMP;
adapter->tx_hwtstamp_skb = skb_get(skb);
adapter->tx_hwtstamp_start = jiffies;
schedule_work(&adapter->tx_hwtstamp_work);
} else {
skb_tx_timestamp(skb);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/i40e/i40e.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ enum i40e_state_t {
__I40E_EMP_RESET_REQUESTED,
__I40E_FILTER_OVERFLOW_PROMISC,
__I40E_SUSPENDED,
__I40E_BAD_EEPROM,
};

enum i40e_interrupt_policy {
Expand Down
35 changes: 22 additions & 13 deletions drivers/net/ethernet/intel/i40e/i40e_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2087,9 +2087,13 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp,
if (!vsi) {
dev_info(&pf->pdev->dev,
"tx_timeout: VSI %d not found\n", vsi_seid);
goto netdev_ops_write_done;
}
if (rtnl_trylock()) {
} else if (!vsi->netdev) {
dev_info(&pf->pdev->dev, "tx_timeout: no netdev for VSI %d\n",
vsi_seid);
} else if (test_bit(__I40E_DOWN, &vsi->state)) {
dev_info(&pf->pdev->dev, "tx_timeout: VSI %d not UP\n",
vsi_seid);
} else if (rtnl_trylock()) {
vsi->netdev->netdev_ops->ndo_tx_timeout(vsi->netdev);
rtnl_unlock();
dev_info(&pf->pdev->dev, "tx_timeout called\n");
Expand All @@ -2108,9 +2112,10 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp,
if (!vsi) {
dev_info(&pf->pdev->dev,
"change_mtu: VSI %d not found\n", vsi_seid);
goto netdev_ops_write_done;
}
if (rtnl_trylock()) {
} else if (!vsi->netdev) {
dev_info(&pf->pdev->dev, "change_mtu: no netdev for VSI %d\n",
vsi_seid);
} else if (rtnl_trylock()) {
vsi->netdev->netdev_ops->ndo_change_mtu(vsi->netdev,
mtu);
rtnl_unlock();
Expand All @@ -2129,9 +2134,10 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp,
if (!vsi) {
dev_info(&pf->pdev->dev,
"set_rx_mode: VSI %d not found\n", vsi_seid);
goto netdev_ops_write_done;
}
if (rtnl_trylock()) {
} else if (!vsi->netdev) {
dev_info(&pf->pdev->dev, "set_rx_mode: no netdev for VSI %d\n",
vsi_seid);
} else if (rtnl_trylock()) {
vsi->netdev->netdev_ops->ndo_set_rx_mode(vsi->netdev);
rtnl_unlock();
dev_info(&pf->pdev->dev, "set_rx_mode called\n");
Expand All @@ -2149,11 +2155,14 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp,
if (!vsi) {
dev_info(&pf->pdev->dev, "napi: VSI %d not found\n",
vsi_seid);
goto netdev_ops_write_done;
} else if (!vsi->netdev) {
dev_info(&pf->pdev->dev, "napi: no netdev for VSI %d\n",
vsi_seid);
} else {
for (i = 0; i < vsi->num_q_vectors; i++)
napi_schedule(&vsi->q_vectors[i]->napi);
dev_info(&pf->pdev->dev, "napi called\n");
}
for (i = 0; i < vsi->num_q_vectors; i++)
napi_schedule(&vsi->q_vectors[i]->napi);
dev_info(&pf->pdev->dev, "napi called\n");
} else {
dev_info(&pf->pdev->dev, "unknown command '%s'\n",
i40e_dbg_netdev_ops_buf);
Expand Down
39 changes: 19 additions & 20 deletions drivers/net/ethernet/intel/i40e/i40e_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ static const struct i40e_stats i40e_gstrings_net_stats[] = {
I40E_NETDEV_STAT(rx_crc_errors),
};

static int i40e_add_del_fdir_ethtool(struct i40e_vsi *vsi,
struct ethtool_rxnfc *cmd, bool add);
static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi,
struct ethtool_rxnfc *cmd);

/* These PF_STATs might look like duplicates of some NETDEV_STATs,
* but they are separate. This device supports Virtualization, and
Expand Down Expand Up @@ -1470,16 +1470,15 @@ static int i40e_del_fdir_entry(struct i40e_vsi *vsi,
}

/**
* i40e_add_del_fdir_ethtool - Add/Remove Flow Director filters
* i40e_add_fdir_ethtool - Add/Remove Flow Director filters
* @vsi: pointer to the targeted VSI
* @cmd: command to get or set RX flow classification rules
* @add: true adds a filter, false removes it
*
* Add/Remove Flow Director filters for a specific flow spec based on their
* protocol. Returns 0 if the filters were successfully added or removed.
* Add Flow Director filters for a specific flow spec based on their
* protocol. Returns 0 if the filters were successfully added.
**/
static int i40e_add_del_fdir_ethtool(struct i40e_vsi *vsi,
struct ethtool_rxnfc *cmd, bool add)
static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi,
struct ethtool_rxnfc *cmd)
{
struct ethtool_rx_flow_spec *fsp;
struct i40e_fdir_filter *input;
Expand All @@ -1494,7 +1493,7 @@ static int i40e_add_del_fdir_ethtool(struct i40e_vsi *vsi,
if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED))
return -EOPNOTSUPP;

if (add && (pf->auto_disable_flags & I40E_FLAG_FD_SB_ENABLED))
if (pf->auto_disable_flags & I40E_FLAG_FD_SB_ENABLED)
return -ENOSPC;

fsp = (struct ethtool_rx_flow_spec *)&cmd->fs;
Expand All @@ -1504,7 +1503,7 @@ static int i40e_add_del_fdir_ethtool(struct i40e_vsi *vsi,
return -EINVAL;
}

if ((fsp->ring_cookie >= vsi->num_queue_pairs) && add)
if (fsp->ring_cookie >= vsi->num_queue_pairs)
return -EINVAL;

input = kzalloc(sizeof(*input), GFP_KERNEL);
Expand All @@ -1514,11 +1513,16 @@ static int i40e_add_del_fdir_ethtool(struct i40e_vsi *vsi,

input->fd_id = fsp->location;

if (fsp->ring_cookie == RX_CLS_FLOW_DISC)
input->dest_ctl = I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET;
else
input->dest_ctl =
I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX;

input->q_index = fsp->ring_cookie;
input->flex_off = 0;
input->pctype = 0;
input->dest_vsi = vsi->id;
input->dest_ctl = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX;
input->fd_status = I40E_FILTER_PROGRAM_DESC_FD_STATUS_FD_ID;
input->cnt_index = 0;
input->flow_type = fsp->flow_type;
Expand All @@ -1528,16 +1532,11 @@ static int i40e_add_del_fdir_ethtool(struct i40e_vsi *vsi,
input->src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4src;
input->dst_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst;

ret = i40e_add_del_fdir(vsi, input, add);
if (ret) {
ret = i40e_add_del_fdir(vsi, input, true);
if (ret)
kfree(input);
return ret;
}

if (!ret && add)
i40e_update_ethtool_fdir_entry(vsi, input, fsp->location, NULL);
else
kfree(input);
i40e_update_ethtool_fdir_entry(vsi, input, fsp->location, NULL);

return ret;
}
Expand All @@ -1561,7 +1560,7 @@ static int i40e_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
ret = i40e_set_rss_hash_opt(pf, cmd);
break;
case ETHTOOL_SRXCLSRLINS:
ret = i40e_add_del_fdir_ethtool(vsi, cmd, true);
ret = i40e_add_fdir_ethtool(vsi, cmd);
break;
case ETHTOOL_SRXCLSRLDEL:
ret = i40e_del_fdir_entry(vsi, cmd);
Expand Down
62 changes: 50 additions & 12 deletions drivers/net/ethernet/intel/i40e/i40e_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

/* Local includes */
#include "i40e.h"
#include "i40e_diag.h"
#ifdef CONFIG_I40E_VXLAN
#include <net/vxlan.h>
#endif
Expand Down Expand Up @@ -2877,12 +2878,14 @@ static irqreturn_t i40e_intr(int irq, void *data)
val = rd32(hw, I40E_GLGEN_RSTAT);
val = (val & I40E_GLGEN_RSTAT_RESET_TYPE_MASK)
>> I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT;
if (val == I40E_RESET_CORER)
if (val == I40E_RESET_CORER) {
pf->corer_count++;
else if (val == I40E_RESET_GLOBR)
} else if (val == I40E_RESET_GLOBR) {
pf->globr_count++;
else if (val == I40E_RESET_EMPR)
} else if (val == I40E_RESET_EMPR) {
pf->empr_count++;
set_bit(__I40E_EMP_RESET_REQUESTED, &pf->state);
}
}

if (icr0 & I40E_PFINT_ICR0_HMC_ERR_MASK) {
Expand Down Expand Up @@ -4257,8 +4260,9 @@ static int i40e_open(struct net_device *netdev)
struct i40e_pf *pf = vsi->back;
int err;

/* disallow open during test */
if (test_bit(__I40E_TESTING, &pf->state))
/* disallow open during test or if eeprom is broken */
if (test_bit(__I40E_TESTING, &pf->state) ||
test_bit(__I40E_BAD_EEPROM, &pf->state))
return -EBUSY;

netif_carrier_off(netdev);
Expand Down Expand Up @@ -5077,6 +5081,31 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf)
kfree(event.msg_buf);
}

/**
* i40e_verify_eeprom - make sure eeprom is good to use
* @pf: board private structure
**/
static void i40e_verify_eeprom(struct i40e_pf *pf)
{
int err;

err = i40e_diag_eeprom_test(&pf->hw);
if (err) {
/* retry in case of garbage read */
err = i40e_diag_eeprom_test(&pf->hw);
if (err) {
dev_info(&pf->pdev->dev, "eeprom check failed (%d), Tx/Rx traffic disabled\n",
err);
set_bit(__I40E_BAD_EEPROM, &pf->state);
}
}

if (!err && test_bit(__I40E_BAD_EEPROM, &pf->state)) {
dev_info(&pf->pdev->dev, "eeprom check passed, Tx/Rx traffic enabled\n");
clear_bit(__I40E_BAD_EEPROM, &pf->state);
}
}

/**
* i40e_reconstitute_veb - rebuild the VEB and anything connected to it
* @veb: pointer to the VEB instance
Expand Down Expand Up @@ -5386,6 +5415,12 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
goto end_core_reset;
}

/* re-verify the eeprom if we just had an EMP reset */
if (test_bit(__I40E_EMP_RESET_REQUESTED, &pf->state)) {
clear_bit(__I40E_EMP_RESET_REQUESTED, &pf->state);
i40e_verify_eeprom(pf);
}

ret = i40e_get_capabilities(pf);
if (ret) {
dev_info(&pf->pdev->dev, "i40e_get_capabilities failed, %d\n",
Expand Down Expand Up @@ -6111,13 +6146,13 @@ static int i40e_init_msix(struct i40e_pf *pf)
}

/**
* i40e_alloc_q_vector - Allocate memory for a single interrupt vector
* i40e_vsi_alloc_q_vector - Allocate memory for a single interrupt vector
* @vsi: the VSI being configured
* @v_idx: index of the vector in the vsi struct
*
* We allocate one q_vector. If allocation fails we return -ENOMEM.
**/
static int i40e_alloc_q_vector(struct i40e_vsi *vsi, int v_idx)
static int i40e_vsi_alloc_q_vector(struct i40e_vsi *vsi, int v_idx)
{
struct i40e_q_vector *q_vector;

Expand All @@ -6143,13 +6178,13 @@ static int i40e_alloc_q_vector(struct i40e_vsi *vsi, int v_idx)
}

/**
* i40e_alloc_q_vectors - Allocate memory for interrupt vectors
* i40e_vsi_alloc_q_vectors - Allocate memory for interrupt vectors
* @vsi: the VSI being configured
*
* We allocate one q_vector per queue interrupt. If allocation fails we
* return -ENOMEM.
**/
static int i40e_alloc_q_vectors(struct i40e_vsi *vsi)
static int i40e_vsi_alloc_q_vectors(struct i40e_vsi *vsi)
{
struct i40e_pf *pf = vsi->back;
int v_idx, num_q_vectors;
Expand All @@ -6164,7 +6199,7 @@ static int i40e_alloc_q_vectors(struct i40e_vsi *vsi)
return -EINVAL;

for (v_idx = 0; v_idx < num_q_vectors; v_idx++) {
err = i40e_alloc_q_vector(vsi, v_idx);
err = i40e_vsi_alloc_q_vector(vsi, v_idx);
if (err)
goto err_out;
}
Expand Down Expand Up @@ -7020,7 +7055,7 @@ static int i40e_vsi_setup_vectors(struct i40e_vsi *vsi)
return -EEXIST;
}

ret = i40e_alloc_q_vectors(vsi);
ret = i40e_vsi_alloc_q_vectors(vsi);
if (ret) {
dev_info(&pf->pdev->dev,
"failed to allocate %d q_vector for VSI %d, ret=%d\n",
Expand Down Expand Up @@ -8157,6 +8192,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_pf_reset;
}

i40e_verify_eeprom(pf);

i40e_clear_pxe_mode(hw);
err = i40e_get_capabilities(pf);
if (err)
Expand Down Expand Up @@ -8258,7 +8295,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)

/* prep for VF support */
if ((pf->flags & I40E_FLAG_SRIOV_ENABLED) &&
(pf->flags & I40E_FLAG_MSIX_ENABLED)) {
(pf->flags & I40E_FLAG_MSIX_ENABLED) &&
!test_bit(__I40E_BAD_EEPROM, &pf->state)) {
u32 val;

/* disable link interrupts for VFs */
Expand Down
Loading

0 comments on commit c8c3d7e

Please sign in to comment.