From ce806783bd43f0cd0631d7b2946d503cb912721f Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Thu, 6 Mar 2014 08:59:54 +0000 Subject: i40e: Delete ATR filter on RST We currently delete ATR filter on FIN alone, delete on RST as well. Change-ID: Ie7cae5d1046b9d1d4a0d6ef5bdbf41224c3dade6 Signed-off-by: Anjali Singhai Jain Signed-off-by: Catherine Sullivan Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 851f6537a96a..de25a32f927e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1624,8 +1624,11 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb, tx_ring->atr_count++; - /* sample on all syn/fin packets or once every atr sample rate */ - if (!th->fin && !th->syn && (tx_ring->atr_count < tx_ring->atr_sample_rate)) + /* sample on all syn/fin/rst packets or once every atr sample rate */ + if (!th->fin && + !th->syn && + !th->rst && + (tx_ring->atr_count < tx_ring->atr_sample_rate)) return; tx_ring->atr_count = 0; @@ -1649,7 +1652,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb, dtype_cmd = I40E_TX_DESC_DTYPE_FILTER_PROG; - dtype_cmd |= th->fin ? + dtype_cmd |= (th->fin || th->rst) ? (I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE << I40E_TXD_FLTR_QW1_PCMD_SHIFT) : (I40E_FILTER_PROGRAM_DESC_PCMD_ADD_UPDATE << -- cgit v1.2.3 From 3526d8005f23da22846bdbdb4ed445ab0038dff0 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Thu, 6 Mar 2014 08:59:56 +0000 Subject: i40evf: fix oops in watchdog handler The Tx watchdog handler runs in interrupt context, so it would cause an oops when sending an admin queue message to request a reset, because the admin queue functions use spinlocks. Instead, set a flag and let the reset task handle sending the request. Change-ID: I65879470b72963d9c308edfb8f45ac4fbba2c14f Signed-off-by: Mitch Williams Signed-off-by: Catherine Sullivan Tested-by: Sibai Li Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf.h | 1 + drivers/net/ethernet/intel/i40evf/i40evf_main.c | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index ccb43d343543..807807d62387 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -211,6 +211,7 @@ struct i40evf_adapter { #define I40EVF_FLAG_NEED_LINK_UPDATE (u32)(1 << 7) #define I40EVF_FLAG_PF_COMMS_FAILED (u32)(1 << 8) #define I40EVF_FLAG_RESET_PENDING (u32)(1 << 9) +#define I40EVF_FLAG_RESET_NEEDED (u32)(1 << 10) /* duplcates for common code */ #define I40E_FLAG_FDIR_ATR_ENABLED 0 #define I40E_FLAG_DCB_ENABLED 0 diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index d3eafa320ba9..51c84c19d2be 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -169,9 +169,7 @@ static void i40evf_tx_timeout(struct net_device *netdev) adapter->tx_timeout_count++; dev_info(&adapter->pdev->dev, "TX timeout detected.\n"); if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING)) { - dev_info(&adapter->pdev->dev, "Requesting reset from PF\n"); - i40evf_request_reset(adapter); - adapter->flags |= I40EVF_FLAG_RESET_PENDING; + adapter->flags |= I40EVF_FLAG_RESET_NEEDED; schedule_work(&adapter->reset_task); } } @@ -1484,6 +1482,12 @@ static void i40evf_reset_task(struct work_struct *work) while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section)) udelay(500); + + if (adapter->flags & I40EVF_FLAG_RESET_NEEDED) { + dev_info(&adapter->pdev->dev, "Requesting reset from PF\n"); + i40evf_request_reset(adapter); + } + /* poll until we see the reset actually happen */ for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) { rstat_val = rd32(hw, I40E_VFGEN_RSTAT) & -- cgit v1.2.3 From 90e04070966a0c393f8e203ac07cda06fcb311f0 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Thu, 6 Mar 2014 08:59:57 +0000 Subject: i40e: Make the alloc and free queue vector calls orthogonal It's annoying to search for a matching alloc and free set of function calls when they don't use the same framework for the name of the functions. Fix that up in the case of alloc and free of vsi queue vectors. i40e_vsi_free_q* i40e_vsi_alloc_q* Change-ID: I510eb863a0fbe405312bebea55c2846c76285e6d Signed-off-by: Greg Rose Signed-off-by: Catherine Sullivan Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 28df88ef3c8b..91fd1f1f8f45 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6111,13 +6111,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; @@ -6143,13 +6143,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; @@ -6164,7 +6164,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; } @@ -7020,7 +7020,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", -- cgit v1.2.3 From 4eb3f7685fd6ffbe28a0a4ff10cced2acda5f7ec Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 6 Mar 2014 08:59:58 +0000 Subject: i40e: eeprom integrity check on load and empr The driver needs to verify the eeprom checksum and firmware crc status bits, and shutdown the driver if they fail. This code stops the processing of traffic, but doesn't kill the PF netdev so that the NVMUpdate process should still have a chance at fixing the image. The eeprom is checked on driver load and after an EMP reset, the latter of which should be generated after an NVMUpdate. Change-ID: I34deef21d2e16bf5a43c603cf8af27e6a29dc9d2 Signed-off-by: Shannon Nelson Signed-off-by: Catherine Sullivan Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 50 +++++++++++++++++++++++++---- 2 files changed, 45 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 33cd8b67535d..beb7b4393a6c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -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 { diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 91fd1f1f8f45..a1ec793b93db 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -26,6 +26,7 @@ /* Local includes */ #include "i40e.h" +#include "i40e_diag.h" #ifdef CONFIG_I40E_VXLAN #include #endif @@ -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) { @@ -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); @@ -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 @@ -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", @@ -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) @@ -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 */ -- cgit v1.2.3 From 1eaa3840b786ac9294e9ed8e8dc3fdca29dc9091 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Thu, 6 Mar 2014 08:59:59 +0000 Subject: i40e: Cleanup in FDIR SB ethtool code Function add_del_fdir was used and implemented only for add. So change the name and drop a parameter. Change-ID: Icf2c6c3bbd4fd00cf8d9613a3f6d8c08e0f8e288 Signed-off-by: Anjali Singhai Jain Signed-off-by: Catherine Sullivan Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 32 +++++++++++--------------- 1 file changed, 13 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 28da4125c8c9..0461a72b1311 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -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 @@ -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; @@ -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; @@ -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); @@ -1528,16 +1527,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; } @@ -1561,7 +1555,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); -- cgit v1.2.3 From 35a91fdd52cc3890764ed429d7aed816aa54f65f Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Thu, 6 Mar 2014 09:00:00 +0000 Subject: i40e: Add functionality for FD SB to drop packets With this change we can drop a flow if we wanted to. Change-ID: I222b1ae960e61a31965bafe3159a95099e70c7d2 Signed-off-by: Anjali Singhai Jain Signed-off-by: Catherine Sullivan Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 0461a72b1311..aa123f43fb8e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1513,11 +1513,16 @@ static int i40e_add_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; -- cgit v1.2.3 From c5503603430bb255f67f518466fd79e924aabe31 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 6 Mar 2014 09:00:01 +0000 Subject: i40evf: remove double space after return There were two spaces between return and the value, we only need one. Change-ID: Iaa42c33f50d8d149cdf1a4c9c1902295bfd991c4 Signed-off-by: Jesse Brandeburg Acked-by: Shannon Nelson Signed-off-by: Kevin Scott Signed-off-by: Catherine Sullivan Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40e_prototype.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h index 862fcdf52675..97ab8c2b76f8 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h @@ -67,7 +67,7 @@ extern struct i40e_rx_ptype_decoded i40evf_ptype_lookup[]; static inline struct i40e_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype) { - return i40evf_ptype_lookup[ptype]; + return i40evf_ptype_lookup[ptype]; } /* prototype for functions used for SW locks */ -- cgit v1.2.3 From ca04657b9d529f11ca6f85f83016d77bcb41b6b4 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 6 Mar 2014 09:00:02 +0000 Subject: i40e: check for netdev before debugfs use Make sure the VSI has a netdev before trying to use it in the debugfs netdev_ops commands. Change-ID: I2d744fc0c32b3226534ce2cde171d9675c5440a6 Signed-off-by: Shannon Nelson Signed-off-by: Catherine Sullivan Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 35 ++++++++++++++++---------- 1 file changed, 22 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index afd43d7973fa..3c37386fd138 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -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"); @@ -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(); @@ -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"); @@ -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); -- cgit v1.2.3 From c2e1b5966a7deb08e44276fa1429175565a7f02d Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Thu, 6 Mar 2014 09:00:03 +0000 Subject: i40e/i40evf: Add an FD message level To use for Flow Director specific messages. Change-ID: I69e39a410aa2661f8fd1ed6af0126fa4c335cb77 Signed-off-by: Anjali Singhai Jain Acked-by: Shannon Nelson Acked-by: Kevin Scott Signed-off-by: Catherine Sullivan Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_type.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_type.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index d2f0b95fd0d7..71a968fe557f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -91,6 +91,7 @@ enum i40e_debug_mask { I40E_DEBUG_FLOW = 0x00000200, I40E_DEBUG_DCB = 0x00000400, I40E_DEBUG_DIAG = 0x00000800, + I40E_DEBUG_FD = 0x00001000, I40E_DEBUG_AQ_MESSAGE = 0x01000000, I40E_DEBUG_AQ_DESCRIPTOR = 0x02000000, diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index efe73ad6fdb9..4673b3381edd 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -88,6 +88,7 @@ enum i40e_debug_mask { I40E_DEBUG_FLOW = 0x00000200, I40E_DEBUG_DCB = 0x00000400, I40E_DEBUG_DIAG = 0x00000800, + I40E_DEBUG_FD = 0x00001000, I40E_DEBUG_AQ_MESSAGE = 0x01000000, I40E_DEBUG_AQ_DESCRIPTOR = 0x02000000, -- cgit v1.2.3 From 13c2884f155bc524c5e94482216030de480fea60 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Thu, 6 Mar 2014 09:00:04 +0000 Subject: i40e: Use DEBUG_FD message level for an FD message We don't need to print this info unless at FD message level. Change-ID: I329efdd8e754a0ea0669ec04d12e03db02e6b76e Signed-off-by: Anjali Singhai Jain Signed-off-by: Catherine Sullivan Tested-by: Kavindya Deegala Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index de25a32f927e..a329aacb392f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -482,8 +482,9 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring, } } else if (error == (0x1 << I40E_RX_PROG_STATUS_DESC_NO_FD_ENTRY_SHIFT)) { - netdev_info(rx_ring->vsi->netdev, "ntuple filter loc = %d, could not be removed\n", - rx_desc->wb.qword0.hi_dword.fd_id); + if (I40E_DEBUG_FD & pf->hw.debug_mask) + dev_info(&pdev->dev, "ntuple filter loc = %d, could not be removed\n", + rx_desc->wb.qword0.hi_dword.fd_id); } } -- cgit v1.2.3 From 59c871c5f0540c974db85eaa77f518de26940c1f Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 15 Mar 2014 14:55:00 +0000 Subject: e1000e: add timeout for TX HW time stamping work Hardware may fail to report time stamp e.g.: - when hardware time stamping is not enabled - when time stamp is requested shortly after ifup Timeout time stamp reading work to prevent it from scheduling itself indefinitely. Report timeout events via system log and device stats. Signed-off-by: Jakub Kicinski Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/e1000e/e1000.h | 2 ++ drivers/net/ethernet/intel/e1000e/ethtool.c | 1 + drivers/net/ethernet/intel/e1000e/netdev.c | 7 +++++++ 3 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h index 5325e3e2154e..1471c5464a89 100644 --- a/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/drivers/net/ethernet/intel/e1000e/e1000.h @@ -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, @@ -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; diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index 3c2898d0c2aa..cad250bc1b99 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c @@ -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) diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 6bd1832e3f3e..b8d252fcad18 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -1163,6 +1163,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); @@ -5567,6 +5573,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); -- cgit v1.2.3 From 201b54b8d245ae248fabd2e62b75272da47c475b Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 15 Mar 2014 14:55:05 +0000 Subject: e1000e: remove redundant if clause from PTP work tx_hwtstamp_skb is always set before work is scheduled, work is cancelled before tx_hwtstamp_skb is set to NULL. PTP work cannot ever see tx_hwtstamp_skb set to NULL. Signed-off-by: Jakub Kicinski Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/e1000e/netdev.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index b8d252fcad18..f1cce5928e20 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -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; -- cgit v1.2.3 From afc835d1bda13923e3792d838dae1fa34c506b09 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 15 Mar 2014 14:55:26 +0000 Subject: igb: never generate both software and hardware timestamps skb_tx_timestamp() does not report software time stamp if SKBTX_IN_PROGRESS is set. According to timestamping.txt software time stamps are a fallback and should not be generated if hardware time stamp is provided. Move call to skb_tx_timestamp() after setting SKBTX_IN_PROGRESS. Signed-off-by: Jakub Kicinski Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index cd20409858d1..1fdffa20fe97 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -4980,8 +4980,6 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, first->bytecount = skb->len; first->gso_segs = 1; - skb_tx_timestamp(skb); - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { struct igb_adapter *adapter = netdev_priv(tx_ring->netdev); @@ -4996,6 +4994,8 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, } } + skb_tx_timestamp(skb); + if (vlan_tx_tag_present(skb)) { tx_flags |= IGB_TX_FLAGS_VLAN; tx_flags |= (vlan_tx_tag_get(skb) << IGB_TX_FLAGS_VLAN_SHIFT); -- cgit v1.2.3 From ed4420a3b412b09cc60d6e3d662428b7e6c36e90 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 15 Mar 2014 14:55:32 +0000 Subject: igb: fix race conditions on queuing skb for HW time stamp igb has a single set of TX time stamping resources per NIC. Use a simple bit lock to avoid race conditions and leaking skbs when multiple TX rings try to claim time stamping. Signed-off-by: Jakub Kicinski Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb.h | 3 ++- drivers/net/ethernet/intel/igb/igb_main.c | 3 ++- drivers/net/ethernet/intel/igb/igb_ptp.c | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 411b213c63be..7fbe1e925143 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -492,7 +492,8 @@ struct igb_adapter { enum e1000_state_t { __IGB_TESTING, __IGB_RESETTING, - __IGB_DOWN + __IGB_DOWN, + __IGB_PTP_TX_IN_PROGRESS, }; enum igb_boards { diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 1fdffa20fe97..55fc5596e2d0 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -4983,7 +4983,8 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { struct igb_adapter *adapter = netdev_priv(tx_ring->netdev); - if (!(adapter->ptp_tx_skb)) { + if (!test_and_set_bit_lock(__IGB_PTP_TX_IN_PROGRESS, + &adapter->state)) { skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; tx_flags |= IGB_TX_FLAGS_TSTAMP; diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index da55fbb090b2..2cca8fd5e574 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -387,6 +387,7 @@ static void igb_ptp_tx_work(struct work_struct *work) IGB_PTP_TX_TIMEOUT)) { dev_kfree_skb_any(adapter->ptp_tx_skb); adapter->ptp_tx_skb = NULL; + clear_bit_unlock(__IGB_PTP_TX_IN_PROGRESS, &adapter->state); adapter->tx_hwtstamp_timeouts++; dev_warn(&adapter->pdev->dev, "clearing Tx timestamp hang"); return; @@ -480,6 +481,7 @@ static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter) skb_tstamp_tx(adapter->ptp_tx_skb, &shhwtstamps); dev_kfree_skb_any(adapter->ptp_tx_skb); adapter->ptp_tx_skb = NULL; + clear_bit_unlock(__IGB_PTP_TX_IN_PROGRESS, &adapter->state); } /** @@ -857,6 +859,7 @@ void igb_ptp_stop(struct igb_adapter *adapter) if (adapter->ptp_tx_skb) { dev_kfree_skb_any(adapter->ptp_tx_skb); adapter->ptp_tx_skb = NULL; + clear_bit_unlock(__IGB_PTP_TX_IN_PROGRESS, &adapter->state); } if (adapter->ptp_clock) { -- cgit v1.2.3