Commit a99bbf6e authored by David S. Miller's avatar David S. Miller

Merge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 8eb1b3c3 0a4ecc2c
...@@ -502,10 +502,12 @@ struct i40e_pf { ...@@ -502,10 +502,12 @@ struct i40e_pf {
struct ptp_clock *ptp_clock; struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_caps; struct ptp_clock_info ptp_caps;
struct sk_buff *ptp_tx_skb; struct sk_buff *ptp_tx_skb;
unsigned long ptp_tx_start;
struct hwtstamp_config tstamp_config; struct hwtstamp_config tstamp_config;
struct mutex tmreg_lock; /* Used to protect the SYSTIME registers. */ struct mutex tmreg_lock; /* Used to protect the SYSTIME registers. */
u64 ptp_base_adj; u64 ptp_base_adj;
u32 tx_hwtstamp_timeouts; u32 tx_hwtstamp_timeouts;
u32 tx_hwtstamp_skipped;
u32 rx_hwtstamp_cleared; u32 rx_hwtstamp_cleared;
u32 latch_event_flags; u32 latch_event_flags;
spinlock_t ptp_rx_lock; /* Used to protect Rx timestamp registers. */ spinlock_t ptp_rx_lock; /* Used to protect Rx timestamp registers. */
...@@ -955,7 +957,8 @@ bool i40e_dcb_need_reconfig(struct i40e_pf *pf, ...@@ -955,7 +957,8 @@ bool i40e_dcb_need_reconfig(struct i40e_pf *pf,
struct i40e_dcbx_config *old_cfg, struct i40e_dcbx_config *old_cfg,
struct i40e_dcbx_config *new_cfg); struct i40e_dcbx_config *new_cfg);
#endif /* CONFIG_I40E_DCB */ #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_tx_hwtstamp(struct i40e_pf *pf);
void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index); void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index);
void i40e_ptp_set_increment(struct i40e_pf *pf); void i40e_ptp_set_increment(struct i40e_pf *pf);
......
...@@ -595,6 +595,8 @@ static int i40e_client_setup_qvlist(struct i40e_info *ldev, ...@@ -595,6 +595,8 @@ static int i40e_client_setup_qvlist(struct i40e_info *ldev,
size = sizeof(struct i40e_qvlist_info) + size = sizeof(struct i40e_qvlist_info) +
(sizeof(struct i40e_qv_info) * (qvlist_info->num_vectors - 1)); (sizeof(struct i40e_qv_info) * (qvlist_info->num_vectors - 1));
ldev->qvlist_info = kzalloc(size, GFP_KERNEL); ldev->qvlist_info = kzalloc(size, GFP_KERNEL);
if (!ldev->qvlist_info)
return -ENOMEM;
ldev->qvlist_info->num_vectors = qvlist_info->num_vectors; ldev->qvlist_info->num_vectors = qvlist_info->num_vectors;
for (i = 0; i < qvlist_info->num_vectors; i++) { for (i = 0; i < qvlist_info->num_vectors; i++) {
......
...@@ -147,6 +147,7 @@ static const struct i40e_stats i40e_gstrings_stats[] = { ...@@ -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("VF_admin_queue_requests", vf_aq_requests),
I40E_PF_STAT("arq_overflows", arq_overflows), I40E_PF_STAT("arq_overflows", arq_overflows),
I40E_PF_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared), 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_flush_cnt", fd_flush_cnt),
I40E_PF_STAT("fdir_atr_match", stats.fd_atr_match), I40E_PF_STAT("fdir_atr_match", stats.fd_atr_match),
I40E_PF_STAT("fdir_atr_tunnel_match", stats.fd_atr_tunnel_match), I40E_PF_STAT("fdir_atr_tunnel_match", stats.fd_atr_tunnel_match),
......
...@@ -6372,7 +6372,8 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf) ...@@ -6372,7 +6372,8 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf)
i40e_update_veb_stats(pf->veb[i]); 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);
} }
/** /**
......
...@@ -269,6 +269,7 @@ static u32 i40e_ptp_get_rx_events(struct i40e_pf *pf) ...@@ -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 * 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 * @vsi: The VSI with the rings relevant to 1588
* *
* This watchdog task is scheduled to detect error case where hardware has * 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) ...@@ -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 * particular error is rare but leaves the device in a state unable to timestamp
* any future packets. * 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; struct i40e_hw *hw = &pf->hw;
unsigned int i, cleared = 0; unsigned int i, cleared = 0;
...@@ -327,6 +327,36 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi) ...@@ -327,6 +327,36 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
pf->rx_hwtstamp_cleared += cleared; 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 * i40e_ptp_tx_hwtstamp - Utility function which returns the Tx timestamp
* @pf: Board private structure * @pf: Board private structure
...@@ -338,6 +368,7 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi) ...@@ -338,6 +368,7 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf) void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf)
{ {
struct skb_shared_hwtstamps shhwtstamps; struct skb_shared_hwtstamps shhwtstamps;
struct sk_buff *skb = pf->ptp_tx_skb;
struct i40e_hw *hw = &pf->hw; struct i40e_hw *hw = &pf->hw;
u32 hi, lo; u32 hi, lo;
u64 ns; u64 ns;
...@@ -353,12 +384,19 @@ void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf) ...@@ -353,12 +384,19 @@ void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf)
hi = rd32(hw, I40E_PRTTSYN_TXTIME_H); hi = rd32(hw, I40E_PRTTSYN_TXTIME_H);
ns = (((u64)hi) << 32) | lo; ns = (((u64)hi) << 32) | lo;
i40e_ptp_convert_to_hwtstamp(&shhwtstamps, ns); 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; pf->ptp_tx_skb = NULL;
clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, pf->state); 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);
} }
/** /**
......
...@@ -2628,8 +2628,10 @@ static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -2628,8 +2628,10 @@ static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb,
if (pf->ptp_tx && if (pf->ptp_tx &&
!test_and_set_bit_lock(__I40E_PTP_TX_IN_PROGRESS, pf->state)) { !test_and_set_bit_lock(__I40E_PTP_TX_IN_PROGRESS, pf->state)) {
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
pf->ptp_tx_start = jiffies;
pf->ptp_tx_skb = skb_get(skb); pf->ptp_tx_skb = skb_get(skb);
} else { } else {
pf->tx_hwtstamp_skipped++;
return 0; return 0;
} }
...@@ -2932,10 +2934,12 @@ bool __i40e_chk_linearize(struct sk_buff *skb) ...@@ -2932,10 +2934,12 @@ bool __i40e_chk_linearize(struct sk_buff *skb)
* @hdr_len: size of the packet header * @hdr_len: size of the packet header
* @td_cmd: the command field in the descriptor * @td_cmd: the command field in the descriptor
* @td_offset: offset for checksum or crc * @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, static inline int i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
struct i40e_tx_buffer *first, u32 tx_flags, struct i40e_tx_buffer *first, u32 tx_flags,
const u8 hdr_len, u32 td_cmd, u32 td_offset) const u8 hdr_len, u32 td_cmd, u32 td_offset)
{ {
unsigned int data_len = skb->data_len; unsigned int data_len = skb->data_len;
unsigned int size = skb_headlen(skb); unsigned int size = skb_headlen(skb);
...@@ -3093,7 +3097,7 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -3093,7 +3097,7 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
mmiowb(); mmiowb();
} }
return; return 0;
dma_error: dma_error:
dev_info(tx_ring->dev, "TX DMA map failed\n"); dev_info(tx_ring->dev, "TX DMA map failed\n");
...@@ -3110,6 +3114,8 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -3110,6 +3114,8 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
} }
tx_ring->next_to_use = i; tx_ring->next_to_use = i;
return -1;
} }
/** /**
...@@ -3210,8 +3216,9 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, ...@@ -3210,8 +3216,9 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
*/ */
i40e_atr(tx_ring, skb, tx_flags); i40e_atr(tx_ring, skb, tx_flags);
i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len, if (i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len,
td_cmd, td_offset); td_cmd, td_offset))
goto cleanup_tx_tstamp;
return NETDEV_TX_OK; return NETDEV_TX_OK;
...@@ -3219,6 +3226,15 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, ...@@ -3219,6 +3226,15 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
i40e_trace(xmit_frame_ring_drop, first->skb, tx_ring); i40e_trace(xmit_frame_ring_drop, first->skb, tx_ring);
dev_kfree_skb_any(first->skb); dev_kfree_skb_any(first->skb);
first->skb = NULL; 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; return NETDEV_TX_OK;
} }
......
...@@ -1105,8 +1105,7 @@ void i40e_vf_parse_hw_config(struct i40e_hw *hw, ...@@ -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.num_msix_vectors_vf = msg->max_vectors;
hw->dev_caps.dcb = msg->vf_offload_flags & hw->dev_caps.dcb = msg->vf_offload_flags &
I40E_VIRTCHNL_VF_OFFLOAD_L2; I40E_VIRTCHNL_VF_OFFLOAD_L2;
hw->dev_caps.fcoe = (msg->vf_offload_flags & hw->dev_caps.fcoe = 0;
I40E_VIRTCHNL_VF_OFFLOAD_FCOE) ? 1 : 0;
for (i = 0; i < msg->num_vsis; i++) { for (i = 0; i < msg->num_vsis; i++) {
if (vsi_res->vsi_type == I40E_VSI_SRIOV) { if (vsi_res->vsi_type == I40E_VSI_SRIOV) {
ether_addr_copy(hw->mac.perm_addr, ether_addr_copy(hw->mac.perm_addr,
......
...@@ -79,7 +79,7 @@ enum i40e_virtchnl_ops { ...@@ -79,7 +79,7 @@ enum i40e_virtchnl_ops {
I40E_VIRTCHNL_OP_DEL_VLAN = 13, I40E_VIRTCHNL_OP_DEL_VLAN = 13,
I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE = 14, I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE = 14,
I40E_VIRTCHNL_OP_GET_STATS = 15, 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_EVENT = 17, /* must ALWAYS be 17 */
I40E_VIRTCHNL_OP_IWARP = 20, I40E_VIRTCHNL_OP_IWARP = 20,
I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP = 21, I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP = 21,
...@@ -155,7 +155,6 @@ struct i40e_virtchnl_vsi_resource { ...@@ -155,7 +155,6 @@ struct i40e_virtchnl_vsi_resource {
/* VF offload flags */ /* VF offload flags */
#define I40E_VIRTCHNL_VF_OFFLOAD_L2 0x00000001 #define I40E_VIRTCHNL_VF_OFFLOAD_L2 0x00000001
#define I40E_VIRTCHNL_VF_OFFLOAD_IWARP 0x00000002 #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_AQ 0x00000008
#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG 0x00000010 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG 0x00000010
#define I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR 0x00000020 #define I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR 0x00000020
......
...@@ -152,9 +152,8 @@ int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter) ...@@ -152,9 +152,8 @@ int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter)
{ {
u32 caps; 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 | caps = I40E_VIRTCHNL_VF_OFFLOAD_L2 |
I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF |
I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ | I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ |
I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG | I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG |
I40E_VIRTCHNL_VF_OFFLOAD_VLAN | I40E_VIRTCHNL_VF_OFFLOAD_VLAN |
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment