igb: serialize access to the time sync interrupt registers
authorRichard Cochran <richardcochran@gmail.com>
Fri, 21 Nov 2014 20:51:15 +0000 (20:51 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Fri, 23 Jan 2015 02:10:18 +0000 (18:10 -0800)
The time sync related interrupt registers may be manipulated from
different contexts. This patch protects the registers from being
asynchronously changed by the reset function.

Also, the patch removes a misleading comment. The reset function
is disabling a bunch of functions, not enabling them.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/igb/igb_ptp.c

index 5e7a4e3..8389bb4 100644 (file)
@@ -900,6 +900,7 @@ void igb_ptp_stop(struct igb_adapter *adapter)
 void igb_ptp_reset(struct igb_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
+       unsigned long flags;
 
        if (!(adapter->flags & IGB_FLAG_PTP))
                return;
@@ -907,6 +908,8 @@ void igb_ptp_reset(struct igb_adapter *adapter)
        /* reset the tstamp_config */
        igb_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config);
 
+       spin_lock_irqsave(&adapter->tmreg_lock, flags);
+
        switch (adapter->hw.mac.type) {
        case e1000_82576:
                /* Dial the nominal frequency. */
@@ -917,23 +920,24 @@ void igb_ptp_reset(struct igb_adapter *adapter)
        case e1000_i350:
        case e1000_i210:
        case e1000_i211:
-               /* Enable the timer functions and interrupts. */
                wr32(E1000_TSAUXC, 0x0);
                wr32(E1000_TSIM, TSYNC_INTERRUPTS);
                wr32(E1000_IMS, E1000_IMS_TS);
                break;
        default:
                /* No work to do. */
-               return;
+               goto out;
        }
 
        /* Re-initialize the timer. */
        if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) {
                struct timespec ts = ktime_to_timespec(ktime_get_real());
 
-               igb_ptp_settime_i210(&adapter->ptp_caps, &ts);
+               igb_ptp_write_i210(adapter, &ts);
        } else {
                timecounter_init(&adapter->tc, &adapter->cc,
                                 ktime_to_ns(ktime_get_real()));
        }
+out:
+       spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
 }