@@ -124,7 +124,7 @@ struct steam_device {
124124 struct list_head list ;
125125 spinlock_t lock ;
126126 struct hid_device * hdev , * client_hdev ;
127- struct mutex mutex ;
127+ struct mutex report_mutex ;
128128 bool client_opened ;
129129 struct input_dev __rcu * input ;
130130 unsigned long quirks ;
@@ -267,21 +267,26 @@ static int steam_get_serial(struct steam_device *steam)
267267 * Send: 0xae 0x15 0x01
268268 * Recv: 0xae 0x15 0x01 serialnumber (10 chars)
269269 */
270- int ret ;
270+ int ret = 0 ;
271271 u8 cmd [] = {STEAM_CMD_GET_SERIAL , 0x15 , 0x01 };
272272 u8 reply [3 + STEAM_SERIAL_LEN + 1 ];
273273
274+ mutex_lock (& steam -> report_mutex );
274275 ret = steam_send_report (steam , cmd , sizeof (cmd ));
275276 if (ret < 0 )
276- return ret ;
277+ goto out ;
277278 ret = steam_recv_report (steam , reply , sizeof (reply ));
278279 if (ret < 0 )
279- return ret ;
280- if (reply [0 ] != 0xae || reply [1 ] != 0x15 || reply [2 ] != 0x01 )
281- return - EIO ;
280+ goto out ;
281+ if (reply [0 ] != 0xae || reply [1 ] != 0x15 || reply [2 ] != 0x01 ) {
282+ ret = - EIO ;
283+ goto out ;
284+ }
282285 reply [3 + STEAM_SERIAL_LEN ] = 0 ;
283286 strscpy (steam -> serial_no , reply + 3 , sizeof (steam -> serial_no ));
284- return 0 ;
287+ out :
288+ mutex_unlock (& steam -> report_mutex );
289+ return ret ;
285290}
286291
287292/*
@@ -291,13 +296,18 @@ static int steam_get_serial(struct steam_device *steam)
291296 */
292297static inline int steam_request_conn_status (struct steam_device * steam )
293298{
294- return steam_send_report_byte (steam , STEAM_CMD_REQUEST_COMM_STATUS );
299+ int ret ;
300+ mutex_lock (& steam -> report_mutex );
301+ ret = steam_send_report_byte (steam , STEAM_CMD_REQUEST_COMM_STATUS );
302+ mutex_unlock (& steam -> report_mutex );
303+ return ret ;
295304}
296305
297306static inline int steam_haptic_rumble (struct steam_device * steam ,
298307 u16 intensity , u16 left_speed , u16 right_speed ,
299308 u8 left_gain , u8 right_gain )
300309{
310+ int ret ;
301311 u8 report [11 ] = {STEAM_CMD_HAPTIC_RUMBLE , 9 };
302312
303313 report [3 ] = intensity & 0xFF ;
@@ -309,7 +319,10 @@ static inline int steam_haptic_rumble(struct steam_device *steam,
309319 report [9 ] = left_gain ;
310320 report [10 ] = right_gain ;
311321
312- return steam_send_report (steam , report , sizeof (report ));
322+ mutex_lock (& steam -> report_mutex );
323+ ret = steam_send_report (steam , report , sizeof (report ));
324+ mutex_unlock (& steam -> report_mutex );
325+ return ret ;
313326}
314327
315328static void steam_haptic_rumble_cb (struct work_struct * work )
@@ -336,11 +349,14 @@ static int steam_play_effect(struct input_dev *dev, void *data,
336349static void steam_set_lizard_mode (struct steam_device * steam , bool enable )
337350{
338351 if (enable ) {
352+ mutex_lock (& steam -> report_mutex );
339353 /* enable esc, enter, cursors */
340354 steam_send_report_byte (steam , STEAM_CMD_DEFAULT_MAPPINGS );
341355 /* enable mouse */
342356 steam_send_report_byte (steam , STEAM_CMD_DEFAULT_MOUSE );
357+ mutex_unlock (& steam -> report_mutex );
343358 } else {
359+ mutex_lock (& steam -> report_mutex );
344360 /* disable esc, enter, cursor */
345361 steam_send_report_byte (steam , STEAM_CMD_CLEAR_MAPPINGS );
346362
@@ -352,34 +368,43 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable)
352368 STEAM_REG_RPAD_CLICK_PRESSURE , 0xFFFF , /* disable clicky pad */
353369 STEAM_REG_WATCHDOG_ENABLE , 0 , /* disable watchdog that tests if Steam is active */
354370 0 );
371+ mutex_unlock (& steam -> report_mutex );
355372 } else {
356373 steam_write_registers (steam ,
357374 STEAM_REG_LPAD_MODE , 0x07 , /* disable mouse */
358375 STEAM_REG_RPAD_MODE , 0x07 , /* disable mouse */
359376 0 );
377+ mutex_unlock (& steam -> report_mutex );
360378 }
361379 }
362380}
363381
364382static int steam_input_open (struct input_dev * dev )
365383{
366384 struct steam_device * steam = input_get_drvdata (dev );
385+ unsigned long flags ;
386+ bool set_lizard_mode ;
367387
368- mutex_lock (& steam -> mutex );
369- if (!steam -> client_opened && lizard_mode )
388+ spin_lock_irqsave (& steam -> lock , flags );
389+ set_lizard_mode = !steam -> client_opened && lizard_mode ;
390+ spin_unlock_irqrestore (& steam -> lock , flags );
391+ if (set_lizard_mode )
370392 steam_set_lizard_mode (steam , false);
371- mutex_unlock ( & steam -> mutex );
393+
372394 return 0 ;
373395}
374396
375397static void steam_input_close (struct input_dev * dev )
376398{
377399 struct steam_device * steam = input_get_drvdata (dev );
400+ unsigned long flags ;
401+ bool set_lizard_mode ;
378402
379- mutex_lock (& steam -> mutex );
380- if (!steam -> client_opened && lizard_mode )
403+ spin_lock_irqsave (& steam -> lock , flags );
404+ set_lizard_mode = !steam -> client_opened && lizard_mode ;
405+ spin_unlock_irqrestore (& steam -> lock , flags );
406+ if (set_lizard_mode )
381407 steam_set_lizard_mode (steam , true);
382- mutex_unlock (& steam -> mutex );
383408}
384409
385410static enum power_supply_property steam_battery_props [] = {
@@ -624,6 +649,7 @@ static int steam_register(struct steam_device *steam)
624649{
625650 int ret ;
626651 bool client_opened ;
652+ unsigned long flags ;
627653
628654 /*
629655 * This function can be called several times in a row with the
@@ -636,11 +662,9 @@ static int steam_register(struct steam_device *steam)
636662 * Unlikely, but getting the serial could fail, and it is not so
637663 * important, so make up a serial number and go on.
638664 */
639- mutex_lock (& steam -> mutex );
640665 if (steam_get_serial (steam ) < 0 )
641666 strscpy (steam -> serial_no , "XXXXXXXXXX" ,
642667 sizeof (steam -> serial_no ));
643- mutex_unlock (& steam -> mutex );
644668
645669 hid_info (steam -> hdev , "Steam Controller '%s' connected" ,
646670 steam -> serial_no );
@@ -655,15 +679,13 @@ static int steam_register(struct steam_device *steam)
655679 mutex_unlock (& steam_devices_lock );
656680 }
657681
658- mutex_lock (& steam -> mutex );
682+ spin_lock_irqsave (& steam -> lock , flags );
659683 client_opened = steam -> client_opened ;
660- if (!client_opened )
684+ spin_unlock_irqrestore (& steam -> lock , flags );
685+ if (!client_opened ) {
661686 steam_set_lizard_mode (steam , lizard_mode );
662- mutex_unlock (& steam -> mutex );
663-
664- if (!client_opened )
665687 ret = steam_input_register (steam );
666- else
688+ } else
667689 ret = 0 ;
668690
669691 return ret ;
@@ -746,10 +768,11 @@ static void steam_client_ll_stop(struct hid_device *hdev)
746768static int steam_client_ll_open (struct hid_device * hdev )
747769{
748770 struct steam_device * steam = hdev -> driver_data ;
771+ unsigned long flags ;
749772
750- mutex_lock (& steam -> mutex );
773+ spin_lock_irqsave (& steam -> lock , flags );
751774 steam -> client_opened = true;
752- mutex_unlock (& steam -> mutex );
775+ spin_unlock_irqrestore (& steam -> lock , flags );
753776
754777 steam_input_unregister (steam );
755778
@@ -764,17 +787,14 @@ static void steam_client_ll_close(struct hid_device *hdev)
764787 bool connected ;
765788
766789 spin_lock_irqsave (& steam -> lock , flags );
767- connected = steam -> connected ;
790+ steam -> client_opened = false;
791+ connected = steam -> connected && !steam -> client_opened ;
768792 spin_unlock_irqrestore (& steam -> lock , flags );
769793
770- mutex_lock (& steam -> mutex );
771- steam -> client_opened = false;
772- if (connected )
794+ if (connected ) {
773795 steam_set_lizard_mode (steam , lizard_mode );
774- mutex_unlock (& steam -> mutex );
775-
776- if (connected )
777796 steam_input_register (steam );
797+ }
778798}
779799
780800static int steam_client_ll_raw_request (struct hid_device * hdev ,
@@ -860,19 +880,12 @@ static int steam_probe(struct hid_device *hdev,
860880 steam -> hdev = hdev ;
861881 hid_set_drvdata (hdev , steam );
862882 spin_lock_init (& steam -> lock );
863- mutex_init (& steam -> mutex );
883+ mutex_init (& steam -> report_mutex );
864884 steam -> quirks = id -> driver_data ;
865885 INIT_WORK (& steam -> work_connect , steam_work_connect_cb );
866886 INIT_LIST_HEAD (& steam -> list );
867887 INIT_WORK (& steam -> rumble_work , steam_haptic_rumble_cb );
868888
869- steam -> client_hdev = steam_create_client_hid (hdev );
870- if (IS_ERR (steam -> client_hdev )) {
871- ret = PTR_ERR (steam -> client_hdev );
872- goto client_hdev_fail ;
873- }
874- steam -> client_hdev -> driver_data = steam ;
875-
876889 /*
877890 * With the real steam controller interface, do not connect hidraw.
878891 * Instead, create the client_hid and connect that.
@@ -881,10 +894,6 @@ static int steam_probe(struct hid_device *hdev,
881894 if (ret )
882895 goto hid_hw_start_fail ;
883896
884- ret = hid_add_device (steam -> client_hdev );
885- if (ret )
886- goto client_hdev_add_fail ;
887-
888897 ret = hid_hw_open (hdev );
889898 if (ret ) {
890899 hid_err (hdev ,
@@ -910,15 +919,26 @@ static int steam_probe(struct hid_device *hdev,
910919 }
911920 }
912921
922+ steam -> client_hdev = steam_create_client_hid (hdev );
923+ if (IS_ERR (steam -> client_hdev )) {
924+ ret = PTR_ERR (steam -> client_hdev );
925+ goto client_hdev_fail ;
926+ }
927+ steam -> client_hdev -> driver_data = steam ;
928+
929+ ret = hid_add_device (steam -> client_hdev );
930+ if (ret )
931+ goto client_hdev_add_fail ;
932+
913933 return 0 ;
914934
915- input_register_fail :
916- hid_hw_open_fail :
917935client_hdev_add_fail :
918936 hid_hw_stop (hdev );
919- hid_hw_start_fail :
920- hid_destroy_device (steam -> client_hdev );
921937client_hdev_fail :
938+ hid_destroy_device (steam -> client_hdev );
939+ input_register_fail :
940+ hid_hw_open_fail :
941+ hid_hw_start_fail :
922942 cancel_work_sync (& steam -> work_connect );
923943 cancel_work_sync (& steam -> rumble_work );
924944steam_alloc_fail :
@@ -936,12 +956,10 @@ static void steam_remove(struct hid_device *hdev)
936956 return ;
937957 }
938958
959+ cancel_work_sync (& steam -> work_connect );
939960 hid_destroy_device (steam -> client_hdev );
940- mutex_lock (& steam -> mutex );
941961 steam -> client_hdev = NULL ;
942962 steam -> client_opened = false;
943- mutex_unlock (& steam -> mutex );
944- cancel_work_sync (& steam -> work_connect );
945963 if (steam -> quirks & STEAM_QUIRK_WIRELESS ) {
946964 hid_info (hdev , "Steam wireless receiver disconnected" );
947965 }
@@ -1408,10 +1426,8 @@ static int steam_param_set_lizard_mode(const char *val,
14081426
14091427 mutex_lock (& steam_devices_lock );
14101428 list_for_each_entry (steam , & steam_devices , list ) {
1411- mutex_lock (& steam -> mutex );
14121429 if (!steam -> client_opened )
14131430 steam_set_lizard_mode (steam , lizard_mode );
1414- mutex_unlock (& steam -> mutex );
14151431 }
14161432 mutex_unlock (& steam_devices_lock );
14171433 return 0 ;
0 commit comments