7171
7272#include <linux/bitfield.h>
7373#include <linux/bitops.h>
74- #include <linux/cleanup.h>
7574#include <linux/device.h>
7675#include <linux/hid.h>
7776#include <linux/module.h>
78- #include <linux/mutex.h>
7977#include <linux/power_supply.h>
8078#include <linux/usb.h>
8179#include <linux/workqueue.h>
@@ -120,6 +118,12 @@ enum {
120118 CORSAIR_VOID_BATTERY_CHARGING = 5 ,
121119};
122120
121+ enum {
122+ CORSAIR_VOID_ADD_BATTERY = 0 ,
123+ CORSAIR_VOID_REMOVE_BATTERY = 1 ,
124+ CORSAIR_VOID_UPDATE_BATTERY = 2 ,
125+ };
126+
123127static enum power_supply_property corsair_void_battery_props [] = {
124128 POWER_SUPPLY_PROP_STATUS ,
125129 POWER_SUPPLY_PROP_PRESENT ,
@@ -155,12 +159,12 @@ struct corsair_void_drvdata {
155159
156160 struct power_supply * battery ;
157161 struct power_supply_desc battery_desc ;
158- struct mutex battery_mutex ;
159162
160163 struct delayed_work delayed_status_work ;
161164 struct delayed_work delayed_firmware_work ;
162- struct work_struct battery_remove_work ;
163- struct work_struct battery_add_work ;
165+
166+ unsigned long battery_work_flags ;
167+ struct work_struct battery_work ;
164168};
165169
166170/*
@@ -260,11 +264,9 @@ static void corsair_void_process_receiver(struct corsair_void_drvdata *drvdata,
260264
261265 /* Inform power supply if battery values changed */
262266 if (memcmp (& orig_battery_data , battery_data , sizeof (* battery_data ))) {
263- scoped_guard (mutex , & drvdata -> battery_mutex ) {
264- if (drvdata -> battery ) {
265- power_supply_changed (drvdata -> battery );
266- }
267- }
267+ set_bit (CORSAIR_VOID_UPDATE_BATTERY ,
268+ & drvdata -> battery_work_flags );
269+ schedule_work (& drvdata -> battery_work );
268270 }
269271}
270272
@@ -536,29 +538,11 @@ static void corsair_void_firmware_work_handler(struct work_struct *work)
536538
537539}
538540
539- static void corsair_void_battery_remove_work_handler (struct work_struct * work )
540- {
541- struct corsair_void_drvdata * drvdata ;
542-
543- drvdata = container_of (work , struct corsair_void_drvdata ,
544- battery_remove_work );
545- scoped_guard (mutex , & drvdata -> battery_mutex ) {
546- if (drvdata -> battery ) {
547- power_supply_unregister (drvdata -> battery );
548- drvdata -> battery = NULL ;
549- }
550- }
551- }
552-
553- static void corsair_void_battery_add_work_handler (struct work_struct * work )
541+ static void corsair_void_add_battery (struct corsair_void_drvdata * drvdata )
554542{
555- struct corsair_void_drvdata * drvdata ;
556543 struct power_supply_config psy_cfg = {};
557544 struct power_supply * new_supply ;
558545
559- drvdata = container_of (work , struct corsair_void_drvdata ,
560- battery_add_work );
561- guard (mutex )(& drvdata -> battery_mutex );
562546 if (drvdata -> battery )
563547 return ;
564548
@@ -583,16 +567,42 @@ static void corsair_void_battery_add_work_handler(struct work_struct *work)
583567 drvdata -> battery = new_supply ;
584568}
585569
570+ static void corsair_void_battery_work_handler (struct work_struct * work )
571+ {
572+ struct corsair_void_drvdata * drvdata = container_of (work ,
573+ struct corsair_void_drvdata , battery_work );
574+
575+ bool add_battery = test_and_clear_bit (CORSAIR_VOID_ADD_BATTERY ,
576+ & drvdata -> battery_work_flags );
577+ bool remove_battery = test_and_clear_bit (CORSAIR_VOID_REMOVE_BATTERY ,
578+ & drvdata -> battery_work_flags );
579+ bool update_battery = test_and_clear_bit (CORSAIR_VOID_UPDATE_BATTERY ,
580+ & drvdata -> battery_work_flags );
581+
582+ if (add_battery && !remove_battery ) {
583+ corsair_void_add_battery (drvdata );
584+ } else if (remove_battery && !add_battery && drvdata -> battery ) {
585+ power_supply_unregister (drvdata -> battery );
586+ drvdata -> battery = NULL ;
587+ }
588+
589+ if (update_battery && drvdata -> battery )
590+ power_supply_changed (drvdata -> battery );
591+
592+ }
593+
586594static void corsair_void_headset_connected (struct corsair_void_drvdata * drvdata )
587595{
588- schedule_work (& drvdata -> battery_add_work );
596+ set_bit (CORSAIR_VOID_ADD_BATTERY , & drvdata -> battery_work_flags );
597+ schedule_work (& drvdata -> battery_work );
589598 schedule_delayed_work (& drvdata -> delayed_firmware_work ,
590599 msecs_to_jiffies (100 ));
591600}
592601
593602static void corsair_void_headset_disconnected (struct corsair_void_drvdata * drvdata )
594603{
595- schedule_work (& drvdata -> battery_remove_work );
604+ set_bit (CORSAIR_VOID_REMOVE_BATTERY , & drvdata -> battery_work_flags );
605+ schedule_work (& drvdata -> battery_work );
596606
597607 corsair_void_set_unknown_wireless_data (drvdata );
598608 corsair_void_set_unknown_batt (drvdata );
@@ -678,13 +688,7 @@ static int corsair_void_probe(struct hid_device *hid_dev,
678688 drvdata -> battery_desc .get_property = corsair_void_battery_get_property ;
679689
680690 drvdata -> battery = NULL ;
681- INIT_WORK (& drvdata -> battery_remove_work ,
682- corsair_void_battery_remove_work_handler );
683- INIT_WORK (& drvdata -> battery_add_work ,
684- corsair_void_battery_add_work_handler );
685- ret = devm_mutex_init (drvdata -> dev , & drvdata -> battery_mutex );
686- if (ret )
687- return ret ;
691+ INIT_WORK (& drvdata -> battery_work , corsair_void_battery_work_handler );
688692
689693 ret = sysfs_create_group (& hid_dev -> dev .kobj , & corsair_void_attr_group );
690694 if (ret )
@@ -721,8 +725,7 @@ static void corsair_void_remove(struct hid_device *hid_dev)
721725 struct corsair_void_drvdata * drvdata = hid_get_drvdata (hid_dev );
722726
723727 hid_hw_stop (hid_dev );
724- cancel_work_sync (& drvdata -> battery_remove_work );
725- cancel_work_sync (& drvdata -> battery_add_work );
728+ cancel_work_sync (& drvdata -> battery_work );
726729 if (drvdata -> battery )
727730 power_supply_unregister (drvdata -> battery );
728731
0 commit comments