hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/net/ethernet/intel/igc/igc_ptp.c
....@@ -134,10 +134,12 @@
134134 *
135135 * We need to convert the system time value stored in the RX/TXSTMP registers
136136 * into a hwtstamp which can be used by the upper level timestamping functions.
137
+ *
138
+ * Returns 0 on success.
137139 **/
138
-static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,
139
- struct skb_shared_hwtstamps *hwtstamps,
140
- u64 systim)
140
+static int igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,
141
+ struct skb_shared_hwtstamps *hwtstamps,
142
+ u64 systim)
141143 {
142144 switch (adapter->hw.mac.type) {
143145 case igc_i225:
....@@ -147,8 +149,9 @@
147149 systim & 0xFFFFFFFF);
148150 break;
149151 default:
150
- break;
152
+ return -EINVAL;
151153 }
154
+ return 0;
152155 }
153156
154157 /**
....@@ -320,6 +323,7 @@
320323 return 0;
321324 }
322325
326
+/* Requires adapter->ptp_tx_lock held by caller. */
323327 static void igc_ptp_tx_timeout(struct igc_adapter *adapter)
324328 {
325329 struct igc_hw *hw = &adapter->hw;
....@@ -327,7 +331,6 @@
327331 dev_kfree_skb_any(adapter->ptp_tx_skb);
328332 adapter->ptp_tx_skb = NULL;
329333 adapter->tx_hwtstamp_timeouts++;
330
- clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
331334 /* Clear the tx valid bit in TSYNCTXCTL register to enable interrupt. */
332335 rd32(IGC_TXSTMPH);
333336 netdev_warn(adapter->netdev, "Tx timestamp timeout\n");
....@@ -335,20 +338,20 @@
335338
336339 void igc_ptp_tx_hang(struct igc_adapter *adapter)
337340 {
338
- bool timeout = time_is_before_jiffies(adapter->ptp_tx_start +
339
- IGC_PTP_TX_TIMEOUT);
341
+ unsigned long flags;
340342
341
- if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state))
342
- return;
343
+ spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
343344
344
- /* If we haven't received a timestamp within the timeout, it is
345
- * reasonable to assume that it will never occur, so we can unlock the
346
- * timestamp bit when this occurs.
347
- */
348
- if (timeout) {
349
- cancel_work_sync(&adapter->ptp_tx_work);
350
- igc_ptp_tx_timeout(adapter);
351
- }
345
+ if (!adapter->ptp_tx_skb)
346
+ goto unlock;
347
+
348
+ if (time_is_after_jiffies(adapter->ptp_tx_start + IGC_PTP_TX_TIMEOUT))
349
+ goto unlock;
350
+
351
+ igc_ptp_tx_timeout(adapter);
352
+
353
+unlock:
354
+ spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
352355 }
353356
354357 /**
....@@ -358,6 +361,8 @@
358361 * If we were asked to do hardware stamping and such a time stamp is
359362 * available, then it must have been for this skb here because we only
360363 * allow only one such packet into the queue.
364
+ *
365
+ * Context: Expects adapter->ptp_tx_lock to be held by caller.
361366 */
362367 static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
363368 {
....@@ -372,7 +377,8 @@
372377
373378 regval = rd32(IGC_TXSTMPL);
374379 regval |= (u64)rd32(IGC_TXSTMPH) << 32;
375
- igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval);
380
+ if (igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval))
381
+ return;
376382
377383 switch (adapter->link_speed) {
378384 case SPEED_10:
....@@ -392,13 +398,7 @@
392398 shhwtstamps.hwtstamp =
393399 ktime_add_ns(shhwtstamps.hwtstamp, adjust);
394400
395
- /* Clear the lock early before calling skb_tstamp_tx so that
396
- * applications are not woken up before the lock bit is clear. We use
397
- * a copy of the skb pointer to ensure other threads can't change it
398
- * while we're notifying the stack.
399
- */
400401 adapter->ptp_tx_skb = NULL;
401
- clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
402402
403403 /* Notify the stack and free the skb after we've unlocked */
404404 skb_tstamp_tx(skb, &shhwtstamps);
....@@ -409,24 +409,33 @@
409409 * igc_ptp_tx_work
410410 * @work: pointer to work struct
411411 *
412
- * This work function polls the TSYNCTXCTL valid bit to determine when a
413
- * timestamp has been taken for the current stored skb.
412
+ * This work function checks the TSYNCTXCTL valid bit to determine when
413
+ * a timestamp has been taken for the current stored skb.
414414 */
415415 static void igc_ptp_tx_work(struct work_struct *work)
416416 {
417417 struct igc_adapter *adapter = container_of(work, struct igc_adapter,
418418 ptp_tx_work);
419419 struct igc_hw *hw = &adapter->hw;
420
+ unsigned long flags;
420421 u32 tsynctxctl;
421422
422
- if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state))
423
- return;
423
+ spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
424
+
425
+ if (!adapter->ptp_tx_skb)
426
+ goto unlock;
424427
425428 tsynctxctl = rd32(IGC_TSYNCTXCTL);
426
- if (WARN_ON_ONCE(!(tsynctxctl & IGC_TSYNCTXCTL_TXTT_0)))
427
- return;
429
+ tsynctxctl &= IGC_TSYNCTXCTL_TXTT_0;
430
+ if (!tsynctxctl) {
431
+ WARN_ONCE(1, "Received a TSTAMP interrupt but no TSTAMP is ready.\n");
432
+ goto unlock;
433
+ }
428434
429435 igc_ptp_tx_hwtstamp(adapter);
436
+
437
+unlock:
438
+ spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
430439 }
431440
432441 /**
....@@ -502,6 +511,7 @@
502511 return;
503512 }
504513
514
+ spin_lock_init(&adapter->ptp_tx_lock);
505515 spin_lock_init(&adapter->tmreg_lock);
506516 INIT_WORK(&adapter->ptp_tx_work, igc_ptp_tx_work);
507517
....@@ -555,7 +565,6 @@
555565 cancel_work_sync(&adapter->ptp_tx_work);
556566 dev_kfree_skb_any(adapter->ptp_tx_skb);
557567 adapter->ptp_tx_skb = NULL;
558
- clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
559568
560569 if (pci_device_is_present(adapter->pdev))
561570 igc_ptp_time_save(adapter);