i40e: use a mutex instead of spinlock in PTP user entry points
authorJacob Keller <jacob.e.keller@intel.com>
Wed, 5 Oct 2016 16:30:43 +0000 (09:30 -0700)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Mon, 31 Oct 2016 21:26:40 +0000 (14:26 -0700)
We need a locking mechanism to protect the hardware SYSTIME register
which is split over 2 values, and has internal hardware latching. We
can't allow multiple accesses at the same time. However....

The spinlock_t is overkill here, especially use of spin_lock_irqsave,
since every PTP access will halt hardirqs. Notice that the only places
which need the SYSTIME value are user context and are capable of sleeping.
Thus, it is safe to use a mutex here instead of the spinlock.

Change-ID: I971761a89b58c6aad953590162e85a327fbba232
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_ptp.c

index 60dbb5b90e1a84e5957dab4d3a75dfcdf79d2905..21f2bb321cb40fb2778e8b30b0ce97999b475a2b 100644 (file)
@@ -430,7 +430,7 @@ struct i40e_pf {
        struct sk_buff *ptp_tx_skb;
        struct hwtstamp_config tstamp_config;
        unsigned long last_rx_ptp_check;
-       spinlock_t tmreg_lock; /* Used to protect the device time registers. */
+       struct mutex tmreg_lock; /* Used to protect the SYSTIME registers. */
        u64 ptp_base_adj;
        u32 tx_hwtstamp_timeouts;
        u32 rx_hwtstamp_cleared;
index f1feceab758a5235237df685f2b8666a5a9c0ffd..177b7fb606af6d6ed168c405802b8f5091ed0595 100644 (file)
@@ -159,16 +159,15 @@ static int i40e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
 {
        struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
        struct timespec64 now, then;
-       unsigned long flags;
 
        then = ns_to_timespec64(delta);
-       spin_lock_irqsave(&pf->tmreg_lock, flags);
+       mutex_lock(&pf->tmreg_lock);
 
        i40e_ptp_read(pf, &now);
        now = timespec64_add(now, then);
        i40e_ptp_write(pf, (const struct timespec64 *)&now);
 
-       spin_unlock_irqrestore(&pf->tmreg_lock, flags);
+       mutex_unlock(&pf->tmreg_lock);
 
        return 0;
 }
@@ -184,11 +183,10 @@ static int i40e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
 static int i40e_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
 {
        struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
-       unsigned long flags;
 
-       spin_lock_irqsave(&pf->tmreg_lock, flags);
+       mutex_lock(&pf->tmreg_lock);
        i40e_ptp_read(pf, ts);
-       spin_unlock_irqrestore(&pf->tmreg_lock, flags);
+       mutex_unlock(&pf->tmreg_lock);
 
        return 0;
 }
@@ -205,11 +203,10 @@ static int i40e_ptp_settime(struct ptp_clock_info *ptp,
                            const struct timespec64 *ts)
 {
        struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
-       unsigned long flags;
 
-       spin_lock_irqsave(&pf->tmreg_lock, flags);
+       mutex_lock(&pf->tmreg_lock);
        i40e_ptp_write(pf, ts);
-       spin_unlock_irqrestore(&pf->tmreg_lock, flags);
+       mutex_unlock(&pf->tmreg_lock);
 
        return 0;
 }
@@ -658,10 +655,7 @@ void i40e_ptp_init(struct i40e_pf *pf)
                return;
        }
 
-       /* we have to initialize the lock first, since we can't control
-        * when the user will enter the PHC device entry points
-        */
-       spin_lock_init(&pf->tmreg_lock);
+       mutex_init(&pf->tmreg_lock);
 
        /* ensure we have a clock device */
        err = i40e_ptp_create_clock(pf);