@@ -98,6 +98,7 @@ struct asus_kbd_leds {
98
98
struct hid_device * hdev ;
99
99
struct work_struct work ;
100
100
unsigned int brightness ;
101
+ spinlock_t lock ;
101
102
bool removed ;
102
103
};
103
104
@@ -495,28 +496,42 @@ static void asus_kbd_backlight_set(struct led_classdev *led_cdev,
495
496
{
496
497
struct asus_kbd_leds * led = container_of (led_cdev , struct asus_kbd_leds ,
497
498
cdev );
499
+ unsigned long flags ;
500
+
501
+ spin_lock_irqsave (& led -> lock , flags );
498
502
led -> brightness = brightness ;
503
+ spin_unlock_irqrestore (& led -> lock , flags );
504
+
499
505
schedule_work (& led -> work );
500
506
}
501
507
502
508
static enum led_brightness asus_kbd_backlight_get (struct led_classdev * led_cdev )
503
509
{
504
510
struct asus_kbd_leds * led = container_of (led_cdev , struct asus_kbd_leds ,
505
511
cdev );
512
+ enum led_brightness brightness ;
513
+ unsigned long flags ;
506
514
507
- return led -> brightness ;
515
+ spin_lock_irqsave (& led -> lock , flags );
516
+ brightness = led -> brightness ;
517
+ spin_unlock_irqrestore (& led -> lock , flags );
518
+
519
+ return brightness ;
508
520
}
509
521
510
522
static void asus_kbd_backlight_work (struct work_struct * work )
511
523
{
512
524
struct asus_kbd_leds * led = container_of (work , struct asus_kbd_leds , work );
513
525
u8 buf [] = { FEATURE_KBD_REPORT_ID , 0xba , 0xc5 , 0xc4 , 0x00 };
514
526
int ret ;
527
+ unsigned long flags ;
515
528
516
529
if (led -> removed )
517
530
return ;
518
531
532
+ spin_lock_irqsave (& led -> lock , flags );
519
533
buf [4 ] = led -> brightness ;
534
+ spin_unlock_irqrestore (& led -> lock , flags );
520
535
521
536
ret = asus_kbd_set_report (led -> hdev , buf , sizeof (buf ));
522
537
if (ret < 0 )
@@ -584,6 +599,7 @@ static int asus_kbd_register_leds(struct hid_device *hdev)
584
599
drvdata -> kbd_backlight -> cdev .brightness_set = asus_kbd_backlight_set ;
585
600
drvdata -> kbd_backlight -> cdev .brightness_get = asus_kbd_backlight_get ;
586
601
INIT_WORK (& drvdata -> kbd_backlight -> work , asus_kbd_backlight_work );
602
+ spin_lock_init (& drvdata -> kbd_backlight -> lock );
587
603
588
604
ret = devm_led_classdev_register (& hdev -> dev , & drvdata -> kbd_backlight -> cdev );
589
605
if (ret < 0 ) {
@@ -1119,9 +1135,13 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
1119
1135
static void asus_remove (struct hid_device * hdev )
1120
1136
{
1121
1137
struct asus_drvdata * drvdata = hid_get_drvdata (hdev );
1138
+ unsigned long flags ;
1122
1139
1123
1140
if (drvdata -> kbd_backlight ) {
1141
+ spin_lock_irqsave (& drvdata -> kbd_backlight -> lock , flags );
1124
1142
drvdata -> kbd_backlight -> removed = true;
1143
+ spin_unlock_irqrestore (& drvdata -> kbd_backlight -> lock , flags );
1144
+
1125
1145
cancel_work_sync (& drvdata -> kbd_backlight -> work );
1126
1146
}
1127
1147
0 commit comments