--- x/drivers/hid/hid-steam.c +++ y/drivers/hid/hid-steam.c @@ -314,6 +314,7 @@ struct steam_device { u16 rumble_right; unsigned int sensor_timestamp_us; struct work_struct unregister_work; + struct work_struct unregister_work2; }; static int steam_recv_report(struct steam_device *steam, @@ -618,6 +619,8 @@ static void steam_input_close(struct inp unsigned long flags; bool set_lizard_mode; + if (dev->going_away) + return; if (!(steam->quirks & STEAM_QUIRK_DECK)) { spin_lock_irqsave(&steam->lock, flags); set_lizard_mode = !steam->client_opened && lizard_mode; @@ -1077,25 +1080,17 @@ static void steam_work_unregister_cb(str { struct steam_device *steam = container_of(work, struct steam_device, unregister_work); - unsigned long flags; - bool connected; - bool opened; - - spin_lock_irqsave(&steam->lock, flags); - opened = steam->client_opened; - connected = steam->connected; - spin_unlock_irqrestore(&steam->lock, flags); + steam_sensors_unregister(steam); + steam_input_unregister(steam); +} - if (connected) { - if (opened) { - steam_sensors_unregister(steam); - steam_input_unregister(steam); - } else { - steam_set_lizard_mode(steam, lizard_mode); - steam_input_register(steam); - steam_sensors_register(steam); - } - } +static void steam_work_unregister_cb2(struct work_struct *work) +{ + struct steam_device *steam = container_of(work, struct steam_device, + unregister_work2); + steam_set_lizard_mode(steam, lizard_mode); + steam_input_register(steam); + steam_sensors_register(steam); } static bool steam_is_valve_interface(struct hid_device *hdev) @@ -1160,7 +1155,7 @@ static void steam_client_ll_close(struct connected = steam->connected && !steam->client_opened; spin_unlock_irqrestore(&steam->lock, flags); - schedule_work(&steam->unregister_work); + schedule_work(&steam->unregister_work2); } static int steam_client_ll_raw_request(struct hid_device *hdev, @@ -1253,6 +1248,7 @@ static int steam_probe(struct hid_device INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb); steam->sensor_timestamp_us = 0; INIT_WORK(&steam->unregister_work, steam_work_unregister_cb); + INIT_WORK(&steam->unregister_work2, steam_work_unregister_cb2); /* * With the real steam controller interface, do not connect hidraw. @@ -1314,6 +1310,7 @@ err_cancel_work: cancel_delayed_work_sync(&steam->mode_switch); cancel_work_sync(&steam->rumble_work); cancel_work_sync(&steam->unregister_work); + cancel_work_sync(&steam->unregister_work2); return ret; } @@ -1330,7 +1327,6 @@ static void steam_remove(struct hid_devi cancel_delayed_work_sync(&steam->mode_switch); cancel_work_sync(&steam->work_connect); cancel_work_sync(&steam->rumble_work); - cancel_work_sync(&steam->unregister_work); hid_destroy_device(steam->client_hdev); steam->client_hdev = NULL; steam->client_opened = 0; @@ -1340,6 +1336,8 @@ static void steam_remove(struct hid_devi hid_hw_close(hdev); hid_hw_stop(hdev); steam_unregister(steam); + flush_work(&steam->unregister_work); + flush_work(&steam->unregister_work2); } static void steam_do_connect_event(struct steam_device *steam, bool connected)