@@ -52,7 +52,7 @@ struct irq_entry {
52
52
bool sigio_workaround ;
53
53
};
54
54
55
- static DEFINE_SPINLOCK (irq_lock );
55
+ static DEFINE_RAW_SPINLOCK (irq_lock );
56
56
static LIST_HEAD (active_fds );
57
57
static DECLARE_BITMAP (irqs_allocated , UM_LAST_SIGNAL_IRQ ) ;
58
58
static bool irqs_suspended ;
@@ -257,15 +257,14 @@ static struct irq_entry *get_irq_entry_by_fd(int fd)
257
257
return NULL ;
258
258
}
259
259
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 )
261
261
{
262
262
if (!to_free )
263
263
return ;
264
264
265
265
if (remove )
266
266
os_del_epoll_fd (to_free -> fd );
267
267
list_del (& to_free -> list );
268
- kfree (to_free );
269
268
}
270
269
271
270
static bool update_irq_entry (struct irq_entry * entry )
@@ -286,27 +285,30 @@ static bool update_irq_entry(struct irq_entry *entry)
286
285
return false;
287
286
}
288
287
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 )
290
289
{
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 ;
293
294
}
294
295
295
296
static int activate_fd (int irq , int fd , enum um_irq_type type , void * dev_id ,
296
297
void (* timetravel_handler )(int , int , void * ,
297
298
struct time_travel_event * ))
298
299
{
299
- struct irq_entry * irq_entry ;
300
+ struct irq_entry * irq_entry , * to_free = NULL ;
300
301
int err , events = os_event_mask (type );
301
302
unsigned long flags ;
302
303
303
304
err = os_set_fd_async (fd );
304
305
if (err < 0 )
305
306
goto out ;
306
307
307
- spin_lock_irqsave (& irq_lock , flags );
308
+ raw_spin_lock_irqsave (& irq_lock , flags );
308
309
irq_entry = get_irq_entry_by_fd (fd );
309
310
if (irq_entry ) {
311
+ already :
310
312
/* cannot register the same FD twice with the same type */
311
313
if (WARN_ON (irq_entry -> reg [type ].events )) {
312
314
err = - EALREADY ;
@@ -316,11 +318,22 @@ static int activate_fd(int irq, int fd, enum um_irq_type type, void *dev_id,
316
318
/* temporarily disable to avoid IRQ-side locking */
317
319
os_del_epoll_fd (fd );
318
320
} 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 ;
323
329
}
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 ;
324
337
irq_entry -> fd = fd ;
325
338
list_add_tail (& irq_entry -> list , & active_fds );
326
339
maybe_sigio_broken (fd );
@@ -339,12 +352,11 @@ static int activate_fd(int irq, int fd, enum um_irq_type type, void *dev_id,
339
352
#endif
340
353
341
354
WARN_ON (!update_irq_entry (irq_entry ));
342
- spin_unlock_irqrestore (& irq_lock , flags );
343
-
344
- return 0 ;
355
+ err = 0 ;
345
356
out_unlock :
346
- spin_unlock_irqrestore (& irq_lock , flags );
357
+ raw_spin_unlock_irqrestore (& irq_lock , flags );
347
358
out :
359
+ kfree (to_free );
348
360
return err ;
349
361
}
350
362
@@ -358,19 +370,20 @@ void free_irq_by_fd(int fd)
358
370
struct irq_entry * to_free ;
359
371
unsigned long flags ;
360
372
361
- spin_lock_irqsave (& irq_lock , flags );
373
+ raw_spin_lock_irqsave (& irq_lock , flags );
362
374
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 );
365
378
}
366
379
EXPORT_SYMBOL (free_irq_by_fd );
367
380
368
381
static void free_irq_by_irq_and_dev (unsigned int irq , void * dev )
369
382
{
370
- struct irq_entry * entry ;
383
+ struct irq_entry * entry , * to_free = NULL ;
371
384
unsigned long flags ;
372
385
373
- spin_lock_irqsave (& irq_lock , flags );
386
+ raw_spin_lock_irqsave (& irq_lock , flags );
374
387
list_for_each_entry (entry , & active_fds , list ) {
375
388
enum um_irq_type i ;
376
389
@@ -386,12 +399,13 @@ static void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
386
399
387
400
os_del_epoll_fd (entry -> fd );
388
401
reg -> events = 0 ;
389
- update_or_free_irq_entry (entry );
402
+ to_free = update_or_remove_irq_entry (entry );
390
403
goto out ;
391
404
}
392
405
}
393
406
out :
394
- spin_unlock_irqrestore (& irq_lock , flags );
407
+ raw_spin_unlock_irqrestore (& irq_lock , flags );
408
+ kfree (to_free );
395
409
}
396
410
397
411
void deactivate_fd (int fd , int irqnum )
@@ -402,7 +416,7 @@ void deactivate_fd(int fd, int irqnum)
402
416
403
417
os_del_epoll_fd (fd );
404
418
405
- spin_lock_irqsave (& irq_lock , flags );
419
+ raw_spin_lock_irqsave (& irq_lock , flags );
406
420
entry = get_irq_entry_by_fd (fd );
407
421
if (!entry )
408
422
goto out ;
@@ -414,9 +428,10 @@ void deactivate_fd(int fd, int irqnum)
414
428
entry -> reg [i ].events = 0 ;
415
429
}
416
430
417
- update_or_free_irq_entry (entry );
431
+ entry = update_or_remove_irq_entry (entry );
418
432
out :
419
- spin_unlock_irqrestore (& irq_lock , flags );
433
+ raw_spin_unlock_irqrestore (& irq_lock , flags );
434
+ kfree (entry );
420
435
421
436
ignore_sigio_fd (fd );
422
437
}
@@ -546,7 +561,7 @@ void um_irqs_suspend(void)
546
561
547
562
irqs_suspended = true;
548
563
549
- spin_lock_irqsave (& irq_lock , flags );
564
+ raw_spin_lock_irqsave (& irq_lock , flags );
550
565
list_for_each_entry (entry , & active_fds , list ) {
551
566
enum um_irq_type t ;
552
567
bool clear = true;
@@ -579,7 +594,7 @@ void um_irqs_suspend(void)
579
594
!__ignore_sigio_fd (entry -> fd );
580
595
}
581
596
}
582
- spin_unlock_irqrestore (& irq_lock , flags );
597
+ raw_spin_unlock_irqrestore (& irq_lock , flags );
583
598
}
584
599
585
600
void um_irqs_resume (void )
@@ -588,7 +603,7 @@ void um_irqs_resume(void)
588
603
unsigned long flags ;
589
604
590
605
591
- spin_lock_irqsave (& irq_lock , flags );
606
+ raw_spin_lock_irqsave (& irq_lock , flags );
592
607
list_for_each_entry (entry , & active_fds , list ) {
593
608
if (entry -> suspended ) {
594
609
int err = os_set_fd_async (entry -> fd );
@@ -602,7 +617,7 @@ void um_irqs_resume(void)
602
617
}
603
618
}
604
619
}
605
- spin_unlock_irqrestore (& irq_lock , flags );
620
+ raw_spin_unlock_irqrestore (& irq_lock , flags );
606
621
607
622
irqs_suspended = false;
608
623
send_sigio_to_self ();
@@ -613,7 +628,7 @@ static int normal_irq_set_wake(struct irq_data *d, unsigned int on)
613
628
struct irq_entry * entry ;
614
629
unsigned long flags ;
615
630
616
- spin_lock_irqsave (& irq_lock , flags );
631
+ raw_spin_lock_irqsave (& irq_lock , flags );
617
632
list_for_each_entry (entry , & active_fds , list ) {
618
633
enum um_irq_type t ;
619
634
@@ -628,7 +643,7 @@ static int normal_irq_set_wake(struct irq_data *d, unsigned int on)
628
643
}
629
644
}
630
645
unlock :
631
- spin_unlock_irqrestore (& irq_lock , flags );
646
+ raw_spin_unlock_irqrestore (& irq_lock , flags );
632
647
return 0 ;
633
648
}
634
649
#else
0 commit comments