bnxt_en: replace ptp_lock with irqsave variant
BugLink: https://bugs.launchpad.net/bugs/2097575
[ Upstream commit 4ab3e4983bcc9d9b9dd9720253cb93f44e9e657c ]
In netpoll configuration the completion processing can happen in hard
irq context which will break with spin_lock_bh() for fullfilling RX
timestamp in case of all packets timestamping. Replace it with
spin_lock_irqsave() variant.
Fixes: 7f5515d19c ("bnxt_en: Get the RX packet timestamp")
Reviewed-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: Vadim Fedorenko <vadfed@meta.com>
Message-ID: <20241016195234.2622004-1-vadfed@meta.com>
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Manuel Diewald <manuel.diewald@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
This commit is contained in:
committed by
Stefan Bader
parent
0e27ad8f77
commit
c4a0f8f8e6
@@ -2152,10 +2152,11 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
|
||||
|
||||
if (!bnxt_get_rx_ts_p5(bp, &ts, cmpl_ts)) {
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_bh(&ptp->ptp_lock);
|
||||
spin_lock_irqsave(&ptp->ptp_lock, flags);
|
||||
ns = timecounter_cyc2time(&ptp->tc, ts);
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
memset(skb_hwtstamps(skb), 0,
|
||||
sizeof(*skb_hwtstamps(skb)));
|
||||
skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(ns);
|
||||
@@ -2652,17 +2653,18 @@ static int bnxt_async_event_process(struct bnxt *bp,
|
||||
case ASYNC_EVENT_CMPL_PHC_UPDATE_EVENT_DATA1_FLAGS_PHC_RTC_UPDATE:
|
||||
if (BNXT_PTP_USE_RTC(bp)) {
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
unsigned long flags;
|
||||
u64 ns;
|
||||
|
||||
if (!ptp)
|
||||
goto async_event_process_exit;
|
||||
|
||||
spin_lock_bh(&ptp->ptp_lock);
|
||||
spin_lock_irqsave(&ptp->ptp_lock, flags);
|
||||
bnxt_ptp_update_current_time(bp);
|
||||
ns = (((u64)BNXT_EVENT_PHC_RTC_UPDATE(data1) <<
|
||||
BNXT_PHC_BITS) | ptp->current_time);
|
||||
bnxt_ptp_rtc_timecounter_init(ptp, ns);
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -12833,9 +12835,11 @@ static void bnxt_force_fw_reset(struct bnxt *bp)
|
||||
return;
|
||||
|
||||
if (ptp) {
|
||||
spin_lock_bh(&ptp->ptp_lock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ptp->ptp_lock, flags);
|
||||
set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
} else {
|
||||
set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
|
||||
}
|
||||
@@ -12898,9 +12902,11 @@ void bnxt_fw_reset(struct bnxt *bp)
|
||||
int n = 0, tmo;
|
||||
|
||||
if (ptp) {
|
||||
spin_lock_bh(&ptp->ptp_lock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ptp->ptp_lock, flags);
|
||||
set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
} else {
|
||||
set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
|
||||
}
|
||||
|
||||
@@ -62,13 +62,14 @@ static int bnxt_ptp_settime(struct ptp_clock_info *ptp_info,
|
||||
struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
|
||||
ptp_info);
|
||||
u64 ns = timespec64_to_ns(ts);
|
||||
unsigned long flags;
|
||||
|
||||
if (BNXT_PTP_USE_RTC(ptp->bp))
|
||||
return bnxt_ptp_cfg_settime(ptp->bp, ns);
|
||||
|
||||
spin_lock_bh(&ptp->ptp_lock);
|
||||
spin_lock_irqsave(&ptp->ptp_lock, flags);
|
||||
timecounter_init(&ptp->tc, &ptp->cc, ns);
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -100,13 +101,14 @@ static int bnxt_refclk_read(struct bnxt *bp, struct ptp_system_timestamp *sts,
|
||||
static void bnxt_ptp_get_current_time(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
unsigned long flags;
|
||||
|
||||
if (!ptp)
|
||||
return;
|
||||
spin_lock_bh(&ptp->ptp_lock);
|
||||
spin_lock_irqsave(&ptp->ptp_lock, flags);
|
||||
WRITE_ONCE(ptp->old_time, ptp->current_time);
|
||||
bnxt_refclk_read(bp, NULL, &ptp->current_time);
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_port_ts_query(struct bnxt *bp, u32 flags, u64 *ts)
|
||||
@@ -142,17 +144,18 @@ static int bnxt_ptp_gettimex(struct ptp_clock_info *ptp_info,
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
|
||||
ptp_info);
|
||||
unsigned long flags;
|
||||
u64 ns, cycles;
|
||||
int rc;
|
||||
|
||||
spin_lock_bh(&ptp->ptp_lock);
|
||||
spin_lock_irqsave(&ptp->ptp_lock, flags);
|
||||
rc = bnxt_refclk_read(ptp->bp, sts, &cycles);
|
||||
if (rc) {
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
return rc;
|
||||
}
|
||||
ns = timecounter_cyc2time(&ptp->tc, cycles);
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
*ts = ns_to_timespec64(ns);
|
||||
|
||||
return 0;
|
||||
@@ -170,6 +173,7 @@ void bnxt_ptp_update_current_time(struct bnxt *bp)
|
||||
static int bnxt_ptp_adjphc(struct bnxt_ptp_cfg *ptp, s64 delta)
|
||||
{
|
||||
struct hwrm_port_mac_cfg_input *req;
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
||||
rc = hwrm_req_init(ptp->bp, req, HWRM_PORT_MAC_CFG);
|
||||
@@ -183,9 +187,9 @@ static int bnxt_ptp_adjphc(struct bnxt_ptp_cfg *ptp, s64 delta)
|
||||
if (rc) {
|
||||
netdev_err(ptp->bp->dev, "ptp adjphc failed. rc = %x\n", rc);
|
||||
} else {
|
||||
spin_lock_bh(&ptp->ptp_lock);
|
||||
spin_lock_irqsave(&ptp->ptp_lock, flags);
|
||||
bnxt_ptp_update_current_time(ptp->bp);
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -195,13 +199,14 @@ static int bnxt_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
|
||||
ptp_info);
|
||||
unsigned long flags;
|
||||
|
||||
if (BNXT_PTP_USE_RTC(ptp->bp))
|
||||
return bnxt_ptp_adjphc(ptp, delta);
|
||||
|
||||
spin_lock_bh(&ptp->ptp_lock);
|
||||
spin_lock_irqsave(&ptp->ptp_lock, flags);
|
||||
timecounter_adjtime(&ptp->tc, delta);
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -229,14 +234,15 @@ static int bnxt_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm)
|
||||
struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
|
||||
ptp_info);
|
||||
struct bnxt *bp = ptp->bp;
|
||||
unsigned long flags;
|
||||
|
||||
if (!BNXT_MH(bp))
|
||||
return bnxt_ptp_adjfine_rtc(bp, scaled_ppm);
|
||||
|
||||
spin_lock_bh(&ptp->ptp_lock);
|
||||
spin_lock_irqsave(&ptp->ptp_lock, flags);
|
||||
timecounter_read(&ptp->tc);
|
||||
ptp->cc.mult = adjust_by_scaled_ppm(ptp->cmult, scaled_ppm);
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -244,12 +250,13 @@ void bnxt_ptp_pps_event(struct bnxt *bp, u32 data1, u32 data2)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
struct ptp_clock_event event;
|
||||
unsigned long flags;
|
||||
u64 ns, pps_ts;
|
||||
|
||||
pps_ts = EVENT_PPS_TS(data2, data1);
|
||||
spin_lock_bh(&ptp->ptp_lock);
|
||||
spin_lock_irqsave(&ptp->ptp_lock, flags);
|
||||
ns = timecounter_cyc2time(&ptp->tc, pps_ts);
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
|
||||
switch (EVENT_DATA2_PPS_EVENT_TYPE(data2)) {
|
||||
case ASYNC_EVENT_CMPL_PPS_TIMESTAMP_EVENT_DATA2_EVENT_TYPE_INTERNAL:
|
||||
@@ -386,16 +393,17 @@ static int bnxt_get_target_cycles(struct bnxt_ptp_cfg *ptp, u64 target_ns,
|
||||
{
|
||||
u64 cycles_now;
|
||||
u64 nsec_now, nsec_delta;
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
||||
spin_lock_bh(&ptp->ptp_lock);
|
||||
spin_lock_irqsave(&ptp->ptp_lock, flags);
|
||||
rc = bnxt_refclk_read(ptp->bp, NULL, &cycles_now);
|
||||
if (rc) {
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
return rc;
|
||||
}
|
||||
nsec_now = timecounter_cyc2time(&ptp->tc, cycles_now);
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
|
||||
nsec_delta = target_ns - nsec_now;
|
||||
*cycles_delta = div64_u64(nsec_delta << ptp->cc.shift, ptp->cc.mult);
|
||||
@@ -672,15 +680,16 @@ static void bnxt_stamp_tx_skb(struct bnxt *bp, struct sk_buff *skb)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
struct skb_shared_hwtstamps timestamp;
|
||||
unsigned long flags;
|
||||
u64 ts = 0, ns = 0;
|
||||
int rc;
|
||||
|
||||
rc = bnxt_hwrm_port_ts_query(bp, PORT_TS_QUERY_REQ_FLAGS_PATH_TX, &ts);
|
||||
if (!rc) {
|
||||
memset(×tamp, 0, sizeof(timestamp));
|
||||
spin_lock_bh(&ptp->ptp_lock);
|
||||
spin_lock_irqsave(&ptp->ptp_lock, flags);
|
||||
ns = timecounter_cyc2time(&ptp->tc, ts);
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
timestamp.hwtstamp = ns_to_ktime(ns);
|
||||
skb_tstamp_tx(ptp->tx_skb, ×tamp);
|
||||
} else {
|
||||
@@ -699,6 +708,7 @@ static long bnxt_ptp_ts_aux_work(struct ptp_clock_info *ptp_info)
|
||||
ptp_info);
|
||||
unsigned long now = jiffies;
|
||||
struct bnxt *bp = ptp->bp;
|
||||
unsigned long flags;
|
||||
|
||||
if (ptp->tx_skb)
|
||||
bnxt_stamp_tx_skb(bp, ptp->tx_skb);
|
||||
@@ -709,9 +719,9 @@ static long bnxt_ptp_ts_aux_work(struct ptp_clock_info *ptp_info)
|
||||
bnxt_ptp_get_current_time(bp);
|
||||
ptp->next_period = now + HZ;
|
||||
if (time_after_eq(now, ptp->next_overflow_check)) {
|
||||
spin_lock_bh(&ptp->ptp_lock);
|
||||
spin_lock_irqsave(&ptp->ptp_lock, flags);
|
||||
timecounter_read(&ptp->tc);
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
ptp->next_overflow_check = now + BNXT_PHC_OVERFLOW_PERIOD;
|
||||
}
|
||||
return HZ;
|
||||
@@ -878,6 +888,7 @@ void bnxt_ptp_rtc_timecounter_init(struct bnxt_ptp_cfg *ptp, u64 ns)
|
||||
int bnxt_ptp_init_rtc(struct bnxt *bp, bool phc_cfg)
|
||||
{
|
||||
struct timespec64 tsp;
|
||||
unsigned long flags;
|
||||
u64 ns;
|
||||
int rc;
|
||||
|
||||
@@ -895,9 +906,9 @@ int bnxt_ptp_init_rtc(struct bnxt *bp, bool phc_cfg)
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
spin_lock_bh(&bp->ptp_cfg->ptp_lock);
|
||||
spin_lock_irqsave(&bp->ptp_cfg->ptp_lock, flags);
|
||||
bnxt_ptp_rtc_timecounter_init(bp->ptp_cfg, ns);
|
||||
spin_unlock_bh(&bp->ptp_cfg->ptp_lock);
|
||||
spin_unlock_irqrestore(&bp->ptp_cfg->ptp_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -959,10 +970,12 @@ int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg)
|
||||
goto out;
|
||||
}
|
||||
if (BNXT_CHIP_P5(bp)) {
|
||||
spin_lock_bh(&ptp->ptp_lock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ptp->ptp_lock, flags);
|
||||
bnxt_refclk_read(bp, NULL, &ptp->current_time);
|
||||
WRITE_ONCE(ptp->old_time, ptp->current_time);
|
||||
spin_unlock_bh(&ptp->ptp_lock);
|
||||
spin_unlock_irqrestore(&ptp->ptp_lock, flags);
|
||||
ptp_schedule_worker(ptp->ptp_clock, 0);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -123,11 +123,13 @@ struct bnxt_ptp_cfg {
|
||||
};
|
||||
|
||||
#if BITS_PER_LONG == 32
|
||||
#define BNXT_READ_TIME64(ptp, dst, src) \
|
||||
do { \
|
||||
spin_lock_bh(&(ptp)->ptp_lock); \
|
||||
(dst) = (src); \
|
||||
spin_unlock_bh(&(ptp)->ptp_lock); \
|
||||
#define BNXT_READ_TIME64(ptp, dst, src) \
|
||||
do { \
|
||||
unsigned long flags; \
|
||||
\
|
||||
spin_lock_irqsave(&(ptp)->ptp_lock, flags); \
|
||||
(dst) = (src); \
|
||||
spin_unlock_irqrestore(&(ptp)->ptp_lock, flags); \
|
||||
} while (0)
|
||||
#else
|
||||
#define BNXT_READ_TIME64(ptp, dst, src) \
|
||||
|
||||
Reference in New Issue
Block a user