Skip to content

Commit a99bbf6

Browse files
committed
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: David S. Miller <[email protected]>
2 parents 8eb1b3c + 0a4ecc2 commit a99bbf6

File tree

9 files changed

+77
-19
lines changed

9 files changed

+77
-19
lines changed

drivers/net/ethernet/intel/i40e/i40e.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,10 +502,12 @@ struct i40e_pf {
502502
struct ptp_clock *ptp_clock;
503503
struct ptp_clock_info ptp_caps;
504504
struct sk_buff *ptp_tx_skb;
505+
unsigned long ptp_tx_start;
505506
struct hwtstamp_config tstamp_config;
506507
struct mutex tmreg_lock; /* Used to protect the SYSTIME registers. */
507508
u64 ptp_base_adj;
508509
u32 tx_hwtstamp_timeouts;
510+
u32 tx_hwtstamp_skipped;
509511
u32 rx_hwtstamp_cleared;
510512
u32 latch_event_flags;
511513
spinlock_t ptp_rx_lock; /* Used to protect Rx timestamp registers. */
@@ -955,7 +957,8 @@ bool i40e_dcb_need_reconfig(struct i40e_pf *pf,
955957
struct i40e_dcbx_config *old_cfg,
956958
struct i40e_dcbx_config *new_cfg);
957959
#endif /* CONFIG_I40E_DCB */
958-
void i40e_ptp_rx_hang(struct i40e_vsi *vsi);
960+
void i40e_ptp_rx_hang(struct i40e_pf *pf);
961+
void i40e_ptp_tx_hang(struct i40e_pf *pf);
959962
void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf);
960963
void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index);
961964
void i40e_ptp_set_increment(struct i40e_pf *pf);

drivers/net/ethernet/intel/i40e/i40e_client.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,8 @@ static int i40e_client_setup_qvlist(struct i40e_info *ldev,
595595
size = sizeof(struct i40e_qvlist_info) +
596596
(sizeof(struct i40e_qv_info) * (qvlist_info->num_vectors - 1));
597597
ldev->qvlist_info = kzalloc(size, GFP_KERNEL);
598+
if (!ldev->qvlist_info)
599+
return -ENOMEM;
598600
ldev->qvlist_info->num_vectors = qvlist_info->num_vectors;
599601

600602
for (i = 0; i < qvlist_info->num_vectors; i++) {

drivers/net/ethernet/intel/i40e/i40e_ethtool.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ static const struct i40e_stats i40e_gstrings_stats[] = {
147147
I40E_PF_STAT("VF_admin_queue_requests", vf_aq_requests),
148148
I40E_PF_STAT("arq_overflows", arq_overflows),
149149
I40E_PF_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
150+
I40E_PF_STAT("tx_hwtstamp_skipped", tx_hwtstamp_skipped),
150151
I40E_PF_STAT("fdir_flush_cnt", fd_flush_cnt),
151152
I40E_PF_STAT("fdir_atr_match", stats.fd_atr_match),
152153
I40E_PF_STAT("fdir_atr_tunnel_match", stats.fd_atr_tunnel_match),

drivers/net/ethernet/intel/i40e/i40e_main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6372,7 +6372,8 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf)
63726372
i40e_update_veb_stats(pf->veb[i]);
63736373
}
63746374

6375-
i40e_ptp_rx_hang(pf->vsi[pf->lan_vsi]);
6375+
i40e_ptp_rx_hang(pf);
6376+
i40e_ptp_tx_hang(pf);
63766377
}
63776378

63786379
/**

drivers/net/ethernet/intel/i40e/i40e_ptp.c

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -269,16 +269,16 @@ static u32 i40e_ptp_get_rx_events(struct i40e_pf *pf)
269269

270270
/**
271271
* i40e_ptp_rx_hang - Detect error case when Rx timestamp registers are hung
272+
* @pf: The PF private data structure
272273
* @vsi: The VSI with the rings relevant to 1588
273274
*
274275
* This watchdog task is scheduled to detect error case where hardware has
275276
* dropped an Rx packet that was timestamped when the ring is full. The
276277
* particular error is rare but leaves the device in a state unable to timestamp
277278
* any future packets.
278279
**/
279-
void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
280+
void i40e_ptp_rx_hang(struct i40e_pf *pf)
280281
{
281-
struct i40e_pf *pf = vsi->back;
282282
struct i40e_hw *hw = &pf->hw;
283283
unsigned int i, cleared = 0;
284284

@@ -327,6 +327,36 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
327327
pf->rx_hwtstamp_cleared += cleared;
328328
}
329329

330+
/**
331+
* i40e_ptp_tx_hang - Detect error case when Tx timestamp register is hung
332+
* @pf: The PF private data structure
333+
*
334+
* This watchdog task is run periodically to make sure that we clear the Tx
335+
* timestamp logic if we don't obtain a timestamp in a reasonable amount of
336+
* time. It is unexpected in the normal case but if it occurs it results in
337+
* permanently prevent timestamps of future packets
338+
**/
339+
void i40e_ptp_tx_hang(struct i40e_pf *pf)
340+
{
341+
if (!(pf->flags & I40E_FLAG_PTP) || !pf->ptp_tx)
342+
return;
343+
344+
/* Nothing to do if we're not already waiting for a timestamp */
345+
if (!test_bit(__I40E_PTP_TX_IN_PROGRESS, pf->state))
346+
return;
347+
348+
/* We already have a handler routine which is run when we are notified
349+
* of a Tx timestamp in the hardware. If we don't get an interrupt
350+
* within a second it is reasonable to assume that we never will.
351+
*/
352+
if (time_is_before_jiffies(pf->ptp_tx_start + HZ)) {
353+
dev_kfree_skb_any(pf->ptp_tx_skb);
354+
pf->ptp_tx_skb = NULL;
355+
clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, pf->state);
356+
pf->tx_hwtstamp_timeouts++;
357+
}
358+
}
359+
330360
/**
331361
* i40e_ptp_tx_hwtstamp - Utility function which returns the Tx timestamp
332362
* @pf: Board private structure
@@ -338,6 +368,7 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
338368
void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf)
339369
{
340370
struct skb_shared_hwtstamps shhwtstamps;
371+
struct sk_buff *skb = pf->ptp_tx_skb;
341372
struct i40e_hw *hw = &pf->hw;
342373
u32 hi, lo;
343374
u64 ns;
@@ -353,12 +384,19 @@ void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf)
353384
hi = rd32(hw, I40E_PRTTSYN_TXTIME_H);
354385

355386
ns = (((u64)hi) << 32) | lo;
356-
357387
i40e_ptp_convert_to_hwtstamp(&shhwtstamps, ns);
358-
skb_tstamp_tx(pf->ptp_tx_skb, &shhwtstamps);
359-
dev_kfree_skb_any(pf->ptp_tx_skb);
388+
389+
/* Clear the bit lock as soon as possible after reading the register,
390+
* and prior to notifying the stack via skb_tstamp_tx(). Otherwise
391+
* applications might wake up and attempt to request another transmit
392+
* timestamp prior to the bit lock being cleared.
393+
*/
360394
pf->ptp_tx_skb = NULL;
361395
clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, pf->state);
396+
397+
/* Notify the stack and free the skb after we've unlocked */
398+
skb_tstamp_tx(skb, &shhwtstamps);
399+
dev_kfree_skb_any(skb);
362400
}
363401

364402
/**

drivers/net/ethernet/intel/i40e/i40e_txrx.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2628,8 +2628,10 @@ static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb,
26282628
if (pf->ptp_tx &&
26292629
!test_and_set_bit_lock(__I40E_PTP_TX_IN_PROGRESS, pf->state)) {
26302630
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
2631+
pf->ptp_tx_start = jiffies;
26312632
pf->ptp_tx_skb = skb_get(skb);
26322633
} else {
2634+
pf->tx_hwtstamp_skipped++;
26332635
return 0;
26342636
}
26352637

@@ -2932,10 +2934,12 @@ bool __i40e_chk_linearize(struct sk_buff *skb)
29322934
* @hdr_len: size of the packet header
29332935
* @td_cmd: the command field in the descriptor
29342936
* @td_offset: offset for checksum or crc
2937+
*
2938+
* Returns 0 on success, -1 on failure to DMA
29352939
**/
2936-
static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
2937-
struct i40e_tx_buffer *first, u32 tx_flags,
2938-
const u8 hdr_len, u32 td_cmd, u32 td_offset)
2940+
static inline int i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
2941+
struct i40e_tx_buffer *first, u32 tx_flags,
2942+
const u8 hdr_len, u32 td_cmd, u32 td_offset)
29392943
{
29402944
unsigned int data_len = skb->data_len;
29412945
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,
30933097
mmiowb();
30943098
}
30953099

3096-
return;
3100+
return 0;
30973101

30983102
dma_error:
30993103
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,
31103114
}
31113115

31123116
tx_ring->next_to_use = i;
3117+
3118+
return -1;
31133119
}
31143120

31153121
/**
@@ -3210,15 +3216,25 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
32103216
*/
32113217
i40e_atr(tx_ring, skb, tx_flags);
32123218

3213-
i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len,
3214-
td_cmd, td_offset);
3219+
if (i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len,
3220+
td_cmd, td_offset))
3221+
goto cleanup_tx_tstamp;
32153222

32163223
return NETDEV_TX_OK;
32173224

32183225
out_drop:
32193226
i40e_trace(xmit_frame_ring_drop, first->skb, tx_ring);
32203227
dev_kfree_skb_any(first->skb);
32213228
first->skb = NULL;
3229+
cleanup_tx_tstamp:
3230+
if (unlikely(tx_flags & I40E_TX_FLAGS_TSYN)) {
3231+
struct i40e_pf *pf = i40e_netdev_to_pf(tx_ring->netdev);
3232+
3233+
dev_kfree_skb_any(pf->ptp_tx_skb);
3234+
pf->ptp_tx_skb = NULL;
3235+
clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, pf->state);
3236+
}
3237+
32223238
return NETDEV_TX_OK;
32233239
}
32243240

drivers/net/ethernet/intel/i40evf/i40e_common.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,8 +1105,7 @@ void i40e_vf_parse_hw_config(struct i40e_hw *hw,
11051105
hw->dev_caps.num_msix_vectors_vf = msg->max_vectors;
11061106
hw->dev_caps.dcb = msg->vf_offload_flags &
11071107
I40E_VIRTCHNL_VF_OFFLOAD_L2;
1108-
hw->dev_caps.fcoe = (msg->vf_offload_flags &
1109-
I40E_VIRTCHNL_VF_OFFLOAD_FCOE) ? 1 : 0;
1108+
hw->dev_caps.fcoe = 0;
11101109
for (i = 0; i < msg->num_vsis; i++) {
11111110
if (vsi_res->vsi_type == I40E_VSI_SRIOV) {
11121111
ether_addr_copy(hw->mac.perm_addr,

drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ enum i40e_virtchnl_ops {
7979
I40E_VIRTCHNL_OP_DEL_VLAN = 13,
8080
I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE = 14,
8181
I40E_VIRTCHNL_OP_GET_STATS = 15,
82-
I40E_VIRTCHNL_OP_FCOE = 16,
82+
I40E_VIRTCHNL_OP_RSVD = 16,
8383
I40E_VIRTCHNL_OP_EVENT = 17, /* must ALWAYS be 17 */
8484
I40E_VIRTCHNL_OP_IWARP = 20,
8585
I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP = 21,
@@ -155,7 +155,6 @@ struct i40e_virtchnl_vsi_resource {
155155
/* VF offload flags */
156156
#define I40E_VIRTCHNL_VF_OFFLOAD_L2 0x00000001
157157
#define I40E_VIRTCHNL_VF_OFFLOAD_IWARP 0x00000002
158-
#define I40E_VIRTCHNL_VF_OFFLOAD_FCOE 0x00000004
159158
#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ 0x00000008
160159
#define I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG 0x00000010
161160
#define I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR 0x00000020

drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,8 @@ int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter)
152152
{
153153
u32 caps;
154154

155-
adapter->current_op = I40E_VIRTCHNL_OP_GET_VF_RESOURCES;
156-
adapter->aq_required &= ~I40EVF_FLAG_AQ_GET_CONFIG;
157155
caps = I40E_VIRTCHNL_VF_OFFLOAD_L2 |
156+
I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF |
158157
I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ |
159158
I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG |
160159
I40E_VIRTCHNL_VF_OFFLOAD_VLAN |

0 commit comments

Comments
 (0)