Skip to content

Commit

Permalink
HID: sony: Fix work queue issues
Browse files Browse the repository at this point in the history
Only initialize force feedback for devices that actually support it (Sixaxis and
Dualshock 4) to prevent calls to schedule_work() with an uninitialized work
queue.

Move the cancel_work_sync() call out of sony_destroy_ff() since the state worker
is used for the LEDs even when force-feedback is disabled.

Remove the sony_destroy_ff() function since it is no longer used.

Signed-off-by: Frank Praznik <frank.praznik@oh.rr.com>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
  • Loading branch information
Frank Praznik authored and Jiri Kosina committed Feb 24, 2014
1 parent ad142b9 commit c8de9db
Showing 1 changed file with 14 additions and 14 deletions.
28 changes: 14 additions & 14 deletions drivers/hid/hid-sony.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\
DUALSHOCK4_CONTROLLER)
#define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER)
#define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER)

#define MAX_LEDS 4

Expand Down Expand Up @@ -729,6 +730,7 @@ struct sony_sc {
__u8 right;
#endif

__u8 worker_initialized;
__u8 cable_state;
__u8 battery_charging;
__u8 battery_capacity;
Expand Down Expand Up @@ -1367,22 +1369,12 @@ static int sony_init_ff(struct hid_device *hdev)
return input_ff_create_memless(input_dev, NULL, sony_play_effect);
}

static void sony_destroy_ff(struct hid_device *hdev)
{
struct sony_sc *sc = hid_get_drvdata(hdev);

cancel_work_sync(&sc->state_worker);
}

#else
static int sony_init_ff(struct hid_device *hdev)
{
return 0;
}

static void sony_destroy_ff(struct hid_device *hdev)
{
}
#endif

static int sony_battery_get_property(struct power_supply *psy,
Expand Down Expand Up @@ -1535,9 +1527,11 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
hdev->hid_output_raw_report = sixaxis_usb_output_raw_report;
ret = sixaxis_set_operational_usb(hdev);
sc->worker_initialized = 1;
INIT_WORK(&sc->state_worker, sixaxis_state_worker);
} else if (sc->quirks & SIXAXIS_CONTROLLER_BT) {
ret = sixaxis_set_operational_bt(hdev);
sc->worker_initialized = 1;
INIT_WORK(&sc->state_worker, sixaxis_state_worker);
} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
Expand All @@ -1555,6 +1549,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (ret < 0)
goto err_stop;

sc->worker_initialized = 1;
INIT_WORK(&sc->state_worker, dualshock4_state_worker);
} else {
ret = 0;
Expand Down Expand Up @@ -1582,9 +1577,11 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
}
}

ret = sony_init_ff(hdev);
if (ret < 0)
goto err_close;
if (sc->quirks & SONY_FF_SUPPORT) {
ret = sony_init_ff(hdev);
if (ret < 0)
goto err_close;
}

return 0;
err_close:
Expand All @@ -1594,6 +1591,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
sony_leds_remove(hdev);
if (sc->quirks & SONY_BATTERY_SUPPORT)
sony_battery_remove(sc);
if (sc->worker_initialized)
cancel_work_sync(&sc->state_worker);
hid_hw_stop(hdev);
return ret;
}
Expand All @@ -1610,7 +1609,8 @@ static void sony_remove(struct hid_device *hdev)
sony_battery_remove(sc);
}

sony_destroy_ff(hdev);
if (sc->worker_initialized)
cancel_work_sync(&sc->state_worker);

hid_hw_stop(hdev);
}
Expand Down

0 comments on commit c8de9db

Please sign in to comment.