]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Merge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next...
authorDavid S. Miller <davem@davemloft.net>
Wed, 31 May 2017 21:49:37 +0000 (17:49 -0400)
committerDavid S. Miller <davem@davemloft.net>
Wed, 31 May 2017 21:49:37 +0000 (17:49 -0400)
Jeff Kirsher says:

====================
40GbE Intel Wired LAN Driver Updates 2017-05-31

This series contains updates to i40e and i40evf only.

Jesse provides a couple of fixes, starting with cleaning up duplicate
lines of code.  Fixed a missing line which enables RSS as a negotiated
feature.  Since the VF does not have any way of reporting FCoE enabled,
so just force the code to always report FCoE as disabled.

Jake provides several fixes and changes, starting with fixing a race
condition in i40e.  The hardware has a limitation on transmit PTP packets,
which requires us to limit the driver to timestamping a single packet at
once.  This is done using a state bitlock which enforces that only one
timestamp request is honored at a time, unfortunately this suffers from
a race condition.  Fixed a corner case where we failed to cleanup the
bit lock after a failed transmit, and resulted in a state bit being
locked forever.  Added a new statistic which tracks when a transmit
timestamp request is skipped/ignored, since the driver can only handle
one transmit timestamp request at a time.

Christophe Jaillet fixes a NULL pointer dereference if kzalloc fails.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_client.c
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_ptp.c
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/i40evf/i40e_common.c
drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h
drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c

index cdde3cc28fb59f16234fe5aaf501f569abb62dc4..25bf336c5f380eca444cfd0a0b502b44654c27d6 100644 (file)
@@ -502,10 +502,12 @@ struct i40e_pf {
        struct ptp_clock *ptp_clock;
        struct ptp_clock_info ptp_caps;
        struct sk_buff *ptp_tx_skb;
+       unsigned long ptp_tx_start;
        struct hwtstamp_config tstamp_config;
        struct mutex tmreg_lock; /* Used to protect the SYSTIME registers. */
        u64 ptp_base_adj;
        u32 tx_hwtstamp_timeouts;
+       u32 tx_hwtstamp_skipped;
        u32 rx_hwtstamp_cleared;
        u32 latch_event_flags;
        spinlock_t ptp_rx_lock; /* Used to protect Rx timestamp registers. */
@@ -955,7 +957,8 @@ bool i40e_dcb_need_reconfig(struct i40e_pf *pf,
                            struct i40e_dcbx_config *old_cfg,
                            struct i40e_dcbx_config *new_cfg);
 #endif /* CONFIG_I40E_DCB */
-void i40e_ptp_rx_hang(struct i40e_vsi *vsi);
+void i40e_ptp_rx_hang(struct i40e_pf *pf);
+void i40e_ptp_tx_hang(struct i40e_pf *pf);
 void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf);
 void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index);
 void i40e_ptp_set_increment(struct i40e_pf *pf);
index c3b81a97558e07c7729a0556a9bb87c01444ca37..088b4a43bd2a8dd68e2b7bb31040b9ed24662278 100644 (file)
@@ -595,6 +595,8 @@ static int i40e_client_setup_qvlist(struct i40e_info *ldev,
        size = sizeof(struct i40e_qvlist_info) +
               (sizeof(struct i40e_qv_info) * (qvlist_info->num_vectors - 1));
        ldev->qvlist_info = kzalloc(size, GFP_KERNEL);
+       if (!ldev->qvlist_info)
+               return -ENOMEM;
        ldev->qvlist_info->num_vectors = qvlist_info->num_vectors;
 
        for (i = 0; i < qvlist_info->num_vectors; i++) {
index 7a8eb486b9ea554421fc7f62929a973b9c6efad4..35a246f0552076b896851a3e326d237661d764d5 100644 (file)
@@ -147,6 +147,7 @@ static const struct i40e_stats i40e_gstrings_stats[] = {
        I40E_PF_STAT("VF_admin_queue_requests", vf_aq_requests),
        I40E_PF_STAT("arq_overflows", arq_overflows),
        I40E_PF_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
+       I40E_PF_STAT("tx_hwtstamp_skipped", tx_hwtstamp_skipped),
        I40E_PF_STAT("fdir_flush_cnt", fd_flush_cnt),
        I40E_PF_STAT("fdir_atr_match", stats.fd_atr_match),
        I40E_PF_STAT("fdir_atr_tunnel_match", stats.fd_atr_tunnel_match),
index d5c9c9e06ff57e21c1e28d09b9eea18af6e22f1a..e4eb97832413ac564454c880fbafc8f50f35c750 100644 (file)
@@ -6372,7 +6372,8 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf)
                                i40e_update_veb_stats(pf->veb[i]);
        }
 
-       i40e_ptp_rx_hang(pf->vsi[pf->lan_vsi]);
+       i40e_ptp_rx_hang(pf);
+       i40e_ptp_tx_hang(pf);
 }
 
 /**
index 0efff18ee336ba1568173e45be29efa064703440..1a0be835fa060882a8da1b987980a3e9a2cc8a8f 100644 (file)
@@ -269,6 +269,7 @@ static u32 i40e_ptp_get_rx_events(struct i40e_pf *pf)
 
 /**
  * i40e_ptp_rx_hang - Detect error case when Rx timestamp registers are hung
+ * @pf: The PF private data structure
  * @vsi: The VSI with the rings relevant to 1588
  *
  * This watchdog task is scheduled to detect error case where hardware has
@@ -276,9 +277,8 @@ static u32 i40e_ptp_get_rx_events(struct i40e_pf *pf)
  * particular error is rare but leaves the device in a state unable to timestamp
  * any future packets.
  **/
-void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
+void i40e_ptp_rx_hang(struct i40e_pf *pf)
 {
-       struct i40e_pf *pf = vsi->back;
        struct i40e_hw *hw = &pf->hw;
        unsigned int i, cleared = 0;
 
@@ -327,6 +327,36 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
        pf->rx_hwtstamp_cleared += cleared;
 }
 
+/**
+ * i40e_ptp_tx_hang - Detect error case when Tx timestamp register is hung
+ * @pf: The PF private data structure
+ *
+ * This watchdog task is run periodically to make sure that we clear the Tx
+ * timestamp logic if we don't obtain a timestamp in a reasonable amount of
+ * time. It is unexpected in the normal case but if it occurs it results in
+ * permanently prevent timestamps of future packets
+ **/
+void i40e_ptp_tx_hang(struct i40e_pf *pf)
+{
+       if (!(pf->flags & I40E_FLAG_PTP) || !pf->ptp_tx)
+               return;
+
+       /* Nothing to do if we're not already waiting for a timestamp */
+       if (!test_bit(__I40E_PTP_TX_IN_PROGRESS, pf->state))
+               return;
+
+       /* We already have a handler routine which is run when we are notified
+        * of a Tx timestamp in the hardware. If we don't get an interrupt
+        * within a second it is reasonable to assume that we never will.
+        */
+       if (time_is_before_jiffies(pf->ptp_tx_start + HZ)) {
+               dev_kfree_skb_any(pf->ptp_tx_skb);
+               pf->ptp_tx_skb = NULL;
+               clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, pf->state);
+               pf->tx_hwtstamp_timeouts++;
+       }
+}
+
 /**
  * i40e_ptp_tx_hwtstamp - Utility function which returns the Tx timestamp
  * @pf: Board private structure
@@ -338,6 +368,7 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
 void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf)
 {
        struct skb_shared_hwtstamps shhwtstamps;
+       struct sk_buff *skb = pf->ptp_tx_skb;
        struct i40e_hw *hw = &pf->hw;
        u32 hi, lo;
        u64 ns;
@@ -353,12 +384,19 @@ void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf)
        hi = rd32(hw, I40E_PRTTSYN_TXTIME_H);
 
        ns = (((u64)hi) << 32) | lo;
-
        i40e_ptp_convert_to_hwtstamp(&shhwtstamps, ns);
-       skb_tstamp_tx(pf->ptp_tx_skb, &shhwtstamps);
-       dev_kfree_skb_any(pf->ptp_tx_skb);
+
+       /* Clear the bit lock as soon as possible after reading the register,
+        * and prior to notifying the stack via skb_tstamp_tx(). Otherwise
+        * applications might wake up and attempt to request another transmit
+        * timestamp prior to the bit lock being cleared.
+        */
        pf->ptp_tx_skb = NULL;
        clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, pf->state);
+
+       /* Notify the stack and free the skb after we've unlocked */
+       skb_tstamp_tx(skb, &shhwtstamps);
+       dev_kfree_skb_any(skb);
 }
 
 /**
index 29321a6167a6675757e74ab4e3cd1a100cb423b0..c2e9013d05eb7142949cbb1c9ecd8d4a623b1ca1 100644 (file)
@@ -2628,8 +2628,10 @@ static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb,
        if (pf->ptp_tx &&
            !test_and_set_bit_lock(__I40E_PTP_TX_IN_PROGRESS, pf->state)) {
                skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+               pf->ptp_tx_start = jiffies;
                pf->ptp_tx_skb = skb_get(skb);
        } else {
+               pf->tx_hwtstamp_skipped++;
                return 0;
        }
 
@@ -2932,10 +2934,12 @@ bool __i40e_chk_linearize(struct sk_buff *skb)
  * @hdr_len:  size of the packet header
  * @td_cmd:   the command field in the descriptor
  * @td_offset: offset for checksum or crc
+ *
+ * Returns 0 on success, -1 on failure to DMA
  **/
-static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
-                              struct i40e_tx_buffer *first, u32 tx_flags,
-                              const u8 hdr_len, u32 td_cmd, u32 td_offset)
+static inline int i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
+                             struct i40e_tx_buffer *first, u32 tx_flags,
+                             const u8 hdr_len, u32 td_cmd, u32 td_offset)
 {
        unsigned int data_len = skb->data_len;
        unsigned int size = skb_headlen(skb);
@@ -3093,7 +3097,7 @@ do_rs:
                mmiowb();
        }
 
-       return;
+       return 0;
 
 dma_error:
        dev_info(tx_ring->dev, "TX DMA map failed\n");
@@ -3110,6 +3114,8 @@ dma_error:
        }
 
        tx_ring->next_to_use = i;
+
+       return -1;
 }
 
 /**
@@ -3210,8 +3216,9 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
         */
        i40e_atr(tx_ring, skb, tx_flags);
 
-       i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len,
-                   td_cmd, td_offset);
+       if (i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len,
+                       td_cmd, td_offset))
+               goto cleanup_tx_tstamp;
 
        return NETDEV_TX_OK;
 
@@ -3219,6 +3226,15 @@ out_drop:
        i40e_trace(xmit_frame_ring_drop, first->skb, tx_ring);
        dev_kfree_skb_any(first->skb);
        first->skb = NULL;
+cleanup_tx_tstamp:
+       if (unlikely(tx_flags & I40E_TX_FLAGS_TSYN)) {
+               struct i40e_pf *pf = i40e_netdev_to_pf(tx_ring->netdev);
+
+               dev_kfree_skb_any(pf->ptp_tx_skb);
+               pf->ptp_tx_skb = NULL;
+               clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, pf->state);
+       }
+
        return NETDEV_TX_OK;
 }
 
index 43f10761f4ba0ac966f0d4a01cd7ee666ff54201..6729624fda5b0d1207f9646f4deea5c2683745e4 100644 (file)
@@ -1105,8 +1105,7 @@ void i40e_vf_parse_hw_config(struct i40e_hw *hw,
        hw->dev_caps.num_msix_vectors_vf = msg->max_vectors;
        hw->dev_caps.dcb = msg->vf_offload_flags &
                           I40E_VIRTCHNL_VF_OFFLOAD_L2;
-       hw->dev_caps.fcoe = (msg->vf_offload_flags &
-                            I40E_VIRTCHNL_VF_OFFLOAD_FCOE) ? 1 : 0;
+       hw->dev_caps.fcoe = 0;
        for (i = 0; i < msg->num_vsis; i++) {
                if (vsi_res->vsi_type == I40E_VSI_SRIOV) {
                        ether_addr_copy(hw->mac.perm_addr,
index c5ad0388c3d577be4991ff0b36283151f0be3824..b0b8de5d6f57afdf7b5c344affaf7643ed7c3fe4 100644 (file)
@@ -79,7 +79,7 @@ enum i40e_virtchnl_ops {
        I40E_VIRTCHNL_OP_DEL_VLAN = 13,
        I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE = 14,
        I40E_VIRTCHNL_OP_GET_STATS = 15,
-       I40E_VIRTCHNL_OP_FCOE = 16,
+       I40E_VIRTCHNL_OP_RSVD = 16,
        I40E_VIRTCHNL_OP_EVENT = 17, /* must ALWAYS be 17 */
        I40E_VIRTCHNL_OP_IWARP = 20,
        I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP = 21,
@@ -155,7 +155,6 @@ struct i40e_virtchnl_vsi_resource {
 /* VF offload flags */
 #define I40E_VIRTCHNL_VF_OFFLOAD_L2            0x00000001
 #define I40E_VIRTCHNL_VF_OFFLOAD_IWARP         0x00000002
-#define I40E_VIRTCHNL_VF_OFFLOAD_FCOE          0x00000004
 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ                0x00000008
 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG       0x00000010
 #define I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR     0x00000020
index deb2cb8dac6b2051ed99a05b11076fc561e141c0..91b21f26f8d4de2d887799bf4368e00b35dec7eb 100644 (file)
@@ -152,9 +152,8 @@ int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter)
 {
        u32 caps;
 
-       adapter->current_op = I40E_VIRTCHNL_OP_GET_VF_RESOURCES;
-       adapter->aq_required &= ~I40EVF_FLAG_AQ_GET_CONFIG;
        caps = I40E_VIRTCHNL_VF_OFFLOAD_L2 |
+              I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF |
               I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ |
               I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG |
               I40E_VIRTCHNL_VF_OFFLOAD_VLAN |