Skip to content

Commit 9617863

Browse files
jmberg-intelrichardweinberger
authored andcommitted
um: convert irq_lock to raw spinlock
Since this is deep in the architecture, and the code is called nested into other deep management code, this really needs to be a raw spinlock. Convert it. Link: https://patch.msgid.link/20250110125550.32479-8-johannes@sipsolutions.net Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Richard Weinberger <richard@nod.at>
1 parent daa1a05 commit 9617863

File tree

1 file changed

+47
-32
lines changed

1 file changed

+47
-32
lines changed

arch/um/kernel/irq.c

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ struct irq_entry {
5252
bool sigio_workaround;
5353
};
5454

55-
static DEFINE_SPINLOCK(irq_lock);
55+
static DEFINE_RAW_SPINLOCK(irq_lock);
5656
static LIST_HEAD(active_fds);
5757
static DECLARE_BITMAP(irqs_allocated, UM_LAST_SIGNAL_IRQ);
5858
static bool irqs_suspended;
@@ -257,15 +257,14 @@ static struct irq_entry *get_irq_entry_by_fd(int fd)
257257
return NULL;
258258
}
259259

260-
static void free_irq_entry(struct irq_entry *to_free, bool remove)
260+
static void remove_irq_entry(struct irq_entry *to_free, bool remove)
261261
{
262262
if (!to_free)
263263
return;
264264

265265
if (remove)
266266
os_del_epoll_fd(to_free->fd);
267267
list_del(&to_free->list);
268-
kfree(to_free);
269268
}
270269

271270
static bool update_irq_entry(struct irq_entry *entry)
@@ -286,27 +285,30 @@ static bool update_irq_entry(struct irq_entry *entry)
286285
return false;
287286
}
288287

289-
static void update_or_free_irq_entry(struct irq_entry *entry)
288+
static struct irq_entry *update_or_remove_irq_entry(struct irq_entry *entry)
290289
{
291-
if (!update_irq_entry(entry))
292-
free_irq_entry(entry, false);
290+
if (update_irq_entry(entry))
291+
return NULL;
292+
remove_irq_entry(entry, false);
293+
return entry;
293294
}
294295

295296
static int activate_fd(int irq, int fd, enum um_irq_type type, void *dev_id,
296297
void (*timetravel_handler)(int, int, void *,
297298
struct time_travel_event *))
298299
{
299-
struct irq_entry *irq_entry;
300+
struct irq_entry *irq_entry, *to_free = NULL;
300301
int err, events = os_event_mask(type);
301302
unsigned long flags;
302303

303304
err = os_set_fd_async(fd);
304305
if (err < 0)
305306
goto out;
306307

307-
spin_lock_irqsave(&irq_lock, flags);
308+
raw_spin_lock_irqsave(&irq_lock, flags);
308309
irq_entry = get_irq_entry_by_fd(fd);
309310
if (irq_entry) {
311+
already:
310312
/* cannot register the same FD twice with the same type */
311313
if (WARN_ON(irq_entry->reg[type].events)) {
312314
err = -EALREADY;
@@ -316,11 +318,22 @@ static int activate_fd(int irq, int fd, enum um_irq_type type, void *dev_id,
316318
/* temporarily disable to avoid IRQ-side locking */
317319
os_del_epoll_fd(fd);
318320
} else {
319-
irq_entry = kzalloc(sizeof(*irq_entry), GFP_ATOMIC);
320-
if (!irq_entry) {
321-
err = -ENOMEM;
322-
goto out_unlock;
321+
struct irq_entry *new;
322+
323+
/* don't restore interrupts */
324+
raw_spin_unlock(&irq_lock);
325+
new = kzalloc(sizeof(*irq_entry), GFP_ATOMIC);
326+
if (!new) {
327+
local_irq_restore(flags);
328+
return -ENOMEM;
323329
}
330+
raw_spin_lock(&irq_lock);
331+
irq_entry = get_irq_entry_by_fd(fd);
332+
if (irq_entry) {
333+
to_free = new;
334+
goto already;
335+
}
336+
irq_entry = new;
324337
irq_entry->fd = fd;
325338
list_add_tail(&irq_entry->list, &active_fds);
326339
maybe_sigio_broken(fd);
@@ -339,12 +352,11 @@ static int activate_fd(int irq, int fd, enum um_irq_type type, void *dev_id,
339352
#endif
340353

341354
WARN_ON(!update_irq_entry(irq_entry));
342-
spin_unlock_irqrestore(&irq_lock, flags);
343-
344-
return 0;
355+
err = 0;
345356
out_unlock:
346-
spin_unlock_irqrestore(&irq_lock, flags);
357+
raw_spin_unlock_irqrestore(&irq_lock, flags);
347358
out:
359+
kfree(to_free);
348360
return err;
349361
}
350362

@@ -358,19 +370,20 @@ void free_irq_by_fd(int fd)
358370
struct irq_entry *to_free;
359371
unsigned long flags;
360372

361-
spin_lock_irqsave(&irq_lock, flags);
373+
raw_spin_lock_irqsave(&irq_lock, flags);
362374
to_free = get_irq_entry_by_fd(fd);
363-
free_irq_entry(to_free, true);
364-
spin_unlock_irqrestore(&irq_lock, flags);
375+
remove_irq_entry(to_free, true);
376+
raw_spin_unlock_irqrestore(&irq_lock, flags);
377+
kfree(to_free);
365378
}
366379
EXPORT_SYMBOL(free_irq_by_fd);
367380

368381
static void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
369382
{
370-
struct irq_entry *entry;
383+
struct irq_entry *entry, *to_free = NULL;
371384
unsigned long flags;
372385

373-
spin_lock_irqsave(&irq_lock, flags);
386+
raw_spin_lock_irqsave(&irq_lock, flags);
374387
list_for_each_entry(entry, &active_fds, list) {
375388
enum um_irq_type i;
376389

@@ -386,12 +399,13 @@ static void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
386399

387400
os_del_epoll_fd(entry->fd);
388401
reg->events = 0;
389-
update_or_free_irq_entry(entry);
402+
to_free = update_or_remove_irq_entry(entry);
390403
goto out;
391404
}
392405
}
393406
out:
394-
spin_unlock_irqrestore(&irq_lock, flags);
407+
raw_spin_unlock_irqrestore(&irq_lock, flags);
408+
kfree(to_free);
395409
}
396410

397411
void deactivate_fd(int fd, int irqnum)
@@ -402,7 +416,7 @@ void deactivate_fd(int fd, int irqnum)
402416

403417
os_del_epoll_fd(fd);
404418

405-
spin_lock_irqsave(&irq_lock, flags);
419+
raw_spin_lock_irqsave(&irq_lock, flags);
406420
entry = get_irq_entry_by_fd(fd);
407421
if (!entry)
408422
goto out;
@@ -414,9 +428,10 @@ void deactivate_fd(int fd, int irqnum)
414428
entry->reg[i].events = 0;
415429
}
416430

417-
update_or_free_irq_entry(entry);
431+
entry = update_or_remove_irq_entry(entry);
418432
out:
419-
spin_unlock_irqrestore(&irq_lock, flags);
433+
raw_spin_unlock_irqrestore(&irq_lock, flags);
434+
kfree(entry);
420435

421436
ignore_sigio_fd(fd);
422437
}
@@ -546,7 +561,7 @@ void um_irqs_suspend(void)
546561

547562
irqs_suspended = true;
548563

549-
spin_lock_irqsave(&irq_lock, flags);
564+
raw_spin_lock_irqsave(&irq_lock, flags);
550565
list_for_each_entry(entry, &active_fds, list) {
551566
enum um_irq_type t;
552567
bool clear = true;
@@ -579,7 +594,7 @@ void um_irqs_suspend(void)
579594
!__ignore_sigio_fd(entry->fd);
580595
}
581596
}
582-
spin_unlock_irqrestore(&irq_lock, flags);
597+
raw_spin_unlock_irqrestore(&irq_lock, flags);
583598
}
584599

585600
void um_irqs_resume(void)
@@ -588,7 +603,7 @@ void um_irqs_resume(void)
588603
unsigned long flags;
589604

590605

591-
spin_lock_irqsave(&irq_lock, flags);
606+
raw_spin_lock_irqsave(&irq_lock, flags);
592607
list_for_each_entry(entry, &active_fds, list) {
593608
if (entry->suspended) {
594609
int err = os_set_fd_async(entry->fd);
@@ -602,7 +617,7 @@ void um_irqs_resume(void)
602617
}
603618
}
604619
}
605-
spin_unlock_irqrestore(&irq_lock, flags);
620+
raw_spin_unlock_irqrestore(&irq_lock, flags);
606621

607622
irqs_suspended = false;
608623
send_sigio_to_self();
@@ -613,7 +628,7 @@ static int normal_irq_set_wake(struct irq_data *d, unsigned int on)
613628
struct irq_entry *entry;
614629
unsigned long flags;
615630

616-
spin_lock_irqsave(&irq_lock, flags);
631+
raw_spin_lock_irqsave(&irq_lock, flags);
617632
list_for_each_entry(entry, &active_fds, list) {
618633
enum um_irq_type t;
619634

@@ -628,7 +643,7 @@ static int normal_irq_set_wake(struct irq_data *d, unsigned int on)
628643
}
629644
}
630645
unlock:
631-
spin_unlock_irqrestore(&irq_lock, flags);
646+
raw_spin_unlock_irqrestore(&irq_lock, flags);
632647
return 0;
633648
}
634649
#else

0 commit comments

Comments
 (0)