From d1c349ccd06cae0b700591d2bf08edf71b8781e4 Mon Sep 17 00:00:00 2001 From: Bhadram Varka Date: Fri, 3 Apr 2020 15:32:25 +0530 Subject: [PATCH] nvethernet: use IRQ-safe variant of raw spinlock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue: Deadlock observed because ptp_lock shared between process context and Interrupt context. Below is the scenario where deadlock observed - 1) ether_adjust_freq acquired the lock 2) At the same ether_get_ptptime() called from IRQ context 3) ether_adjust_freq() got preempted and ether_get_ptptime() trying to aquire the lock again which leads to dead lock. Fix: Disable the interrupts before aquiring the lock by using IRQ-safe variant of raw spinlock. Bug 200591192 Bug 200535378 Change-Id: I6f884883bf9cf93877ddb5d0fb7b2927573a1858 Signed-off-by: Bhadram Varka Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2323211 Tested-by: mobile promotions Reviewed-by: Bitan Biswas Reviewed-by: automaticguardword Reviewed-by: mobile promotions --- drivers/net/ethernet/nvidia/nvethernet/ptp.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/nvidia/nvethernet/ptp.c b/drivers/net/ethernet/nvidia/nvethernet/ptp.c index e8e0d296..1836b121 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ptp.c +++ b/drivers/net/ethernet/nvidia/nvethernet/ptp.c @@ -74,9 +74,10 @@ static int ether_adjust_time(struct ptp_clock_info *ptp, s64 nsec_delta) struct ether_priv_data, ptp_clock_ops); struct osi_core_priv_data *osi_core = pdata->osi_core; + unsigned long flags; int ret = -1; - raw_spin_lock(&pdata->ptp_lock); + raw_spin_lock_irqsave(&pdata->ptp_lock, flags); ret = osi_adjust_time(osi_core, nsec_delta); if (ret < 0) { @@ -85,7 +86,7 @@ static int ether_adjust_time(struct ptp_clock_info *ptp, s64 nsec_delta) __func__, ret); } - raw_spin_unlock(&pdata->ptp_lock); + raw_spin_unlock_irqrestore(&pdata->ptp_lock, flags); return ret; } @@ -108,9 +109,10 @@ static int ether_adjust_freq(struct ptp_clock_info *ptp, s32 ppb) struct ether_priv_data, ptp_clock_ops); struct osi_core_priv_data *osi_core = pdata->osi_core; + unsigned long flags; int ret = -1; - raw_spin_lock(&pdata->ptp_lock); + raw_spin_lock_irqsave(&pdata->ptp_lock, flags); ret = osi_adjust_freq(osi_core, ppb); if (ret < 0) { @@ -119,7 +121,7 @@ static int ether_adjust_freq(struct ptp_clock_info *ptp, s32 ppb) __func__, ret); } - raw_spin_unlock(&pdata->ptp_lock); + raw_spin_unlock_irqrestore(&pdata->ptp_lock, flags); return ret; } @@ -143,12 +145,13 @@ static int ether_get_time(struct ptp_clock_info *ptp, struct timespec *ts) ptp_clock_ops); struct osi_core_priv_data *osi_core = pdata->osi_core; unsigned int sec, nsec; + unsigned long flags; - raw_spin_lock(&pdata->ptp_lock); + raw_spin_lock_irqsave(&pdata->ptp_lock, flags); osi_get_systime_from_mac(osi_core, &sec, &nsec); - raw_spin_unlock(&pdata->ptp_lock); + raw_spin_unlock_irqrestore(&pdata->ptp_lock, flags); ts->tv_sec = sec; ts->tv_nsec = nsec; @@ -175,9 +178,10 @@ static int ether_set_time(struct ptp_clock_info *ptp, struct ether_priv_data, ptp_clock_ops); struct osi_core_priv_data *osi_core = pdata->osi_core; + unsigned long flags; int ret = -1; - raw_spin_lock(&pdata->ptp_lock); + raw_spin_lock_irqsave(&pdata->ptp_lock, flags); ret = osi_set_systime_to_mac(osi_core, ts->tv_sec, ts->tv_nsec); if (ret < 0) { @@ -186,7 +190,7 @@ static int ether_set_time(struct ptp_clock_info *ptp, __func__, ret); } - raw_spin_unlock(&pdata->ptp_lock); + raw_spin_unlock_irqrestore(&pdata->ptp_lock, flags); return ret; }