Skip to content

Commit 99f5711

Browse files
edumazetdavem330
authored andcommitted
mlx4: do not use rwlock in fast path
Using a reader-writer lock in fast path is silly, when we can instead use RCU or a seqlock. For mlx4 hwstamp clock, a seqlock is the way to go, removing two atomic operations and false sharing. Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Tariq Toukan <tariqt@mellanox.com> Reviewed-by: Tariq Toukan <tariqt@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent d5bc161 commit 99f5711

File tree

2 files changed

+19
-18
lines changed

2 files changed

+19
-18
lines changed

drivers/net/ethernet/mellanox/mlx4/en_clock.c

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,13 @@ void mlx4_en_fill_hwtstamps(struct mlx4_en_dev *mdev,
6262
struct skb_shared_hwtstamps *hwts,
6363
u64 timestamp)
6464
{
65-
unsigned long flags;
65+
unsigned int seq;
6666
u64 nsec;
6767

68-
read_lock_irqsave(&mdev->clock_lock, flags);
69-
nsec = timecounter_cyc2time(&mdev->clock, timestamp);
70-
read_unlock_irqrestore(&mdev->clock_lock, flags);
68+
do {
69+
seq = read_seqbegin(&mdev->clock_lock);
70+
nsec = timecounter_cyc2time(&mdev->clock, timestamp);
71+
} while (read_seqretry(&mdev->clock_lock, seq));
7172

7273
memset(hwts, 0, sizeof(struct skb_shared_hwtstamps));
7374
hwts->hwtstamp = ns_to_ktime(nsec);
@@ -95,9 +96,9 @@ void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev)
9596
unsigned long flags;
9697

9798
if (timeout) {
98-
write_lock_irqsave(&mdev->clock_lock, flags);
99+
write_seqlock_irqsave(&mdev->clock_lock, flags);
99100
timecounter_read(&mdev->clock);
100-
write_unlock_irqrestore(&mdev->clock_lock, flags);
101+
write_sequnlock_irqrestore(&mdev->clock_lock, flags);
101102
mdev->last_overflow_check = jiffies;
102103
}
103104
}
@@ -128,10 +129,10 @@ static int mlx4_en_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
128129
adj *= delta;
129130
diff = div_u64(adj, 1000000000ULL);
130131

131-
write_lock_irqsave(&mdev->clock_lock, flags);
132+
write_seqlock_irqsave(&mdev->clock_lock, flags);
132133
timecounter_read(&mdev->clock);
133134
mdev->cycles.mult = neg_adj ? mult - diff : mult + diff;
134-
write_unlock_irqrestore(&mdev->clock_lock, flags);
135+
write_sequnlock_irqrestore(&mdev->clock_lock, flags);
135136

136137
return 0;
137138
}
@@ -149,9 +150,9 @@ static int mlx4_en_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
149150
ptp_clock_info);
150151
unsigned long flags;
151152

152-
write_lock_irqsave(&mdev->clock_lock, flags);
153+
write_seqlock_irqsave(&mdev->clock_lock, flags);
153154
timecounter_adjtime(&mdev->clock, delta);
154-
write_unlock_irqrestore(&mdev->clock_lock, flags);
155+
write_sequnlock_irqrestore(&mdev->clock_lock, flags);
155156

156157
return 0;
157158
}
@@ -172,9 +173,9 @@ static int mlx4_en_phc_gettime(struct ptp_clock_info *ptp,
172173
unsigned long flags;
173174
u64 ns;
174175

175-
write_lock_irqsave(&mdev->clock_lock, flags);
176+
write_seqlock_irqsave(&mdev->clock_lock, flags);
176177
ns = timecounter_read(&mdev->clock);
177-
write_unlock_irqrestore(&mdev->clock_lock, flags);
178+
write_sequnlock_irqrestore(&mdev->clock_lock, flags);
178179

179180
*ts = ns_to_timespec64(ns);
180181

@@ -198,9 +199,9 @@ static int mlx4_en_phc_settime(struct ptp_clock_info *ptp,
198199
unsigned long flags;
199200

200201
/* reset the timecounter */
201-
write_lock_irqsave(&mdev->clock_lock, flags);
202+
write_seqlock_irqsave(&mdev->clock_lock, flags);
202203
timecounter_init(&mdev->clock, &mdev->cycles, ns);
203-
write_unlock_irqrestore(&mdev->clock_lock, flags);
204+
write_sequnlock_irqrestore(&mdev->clock_lock, flags);
204205

205206
return 0;
206207
}
@@ -266,7 +267,7 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
266267
if (mdev->ptp_clock)
267268
return;
268269

269-
rwlock_init(&mdev->clock_lock);
270+
seqlock_init(&mdev->clock_lock);
270271

271272
memset(&mdev->cycles, 0, sizeof(mdev->cycles));
272273
mdev->cycles.read = mlx4_en_read_clock;
@@ -276,10 +277,10 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
276277
clocksource_khz2mult(1000 * dev->caps.hca_core_clock, mdev->cycles.shift);
277278
mdev->nominal_c_mult = mdev->cycles.mult;
278279

279-
write_lock_irqsave(&mdev->clock_lock, flags);
280+
write_seqlock_irqsave(&mdev->clock_lock, flags);
280281
timecounter_init(&mdev->clock, &mdev->cycles,
281282
ktime_to_ns(ktime_get_real()));
282-
write_unlock_irqrestore(&mdev->clock_lock, flags);
283+
write_sequnlock_irqrestore(&mdev->clock_lock, flags);
283284

284285
/* Calculate period in seconds to call the overflow watchdog - to make
285286
* sure counter is checked at least once every wrap around.

drivers/net/ethernet/mellanox/mlx4/mlx4_en.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,9 +424,9 @@ struct mlx4_en_dev {
424424
u32 priv_pdn;
425425
spinlock_t uar_lock;
426426
u8 mac_removed[MLX4_MAX_PORTS + 1];
427-
rwlock_t clock_lock;
428427
u32 nominal_c_mult;
429428
struct cyclecounter cycles;
429+
seqlock_t clock_lock;
430430
struct timecounter clock;
431431
unsigned long last_overflow_check;
432432
unsigned long overflow_period;

0 commit comments

Comments
 (0)