From 3865f5c94cb90d16810b7e751fa79034321ea836 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 23 Mar 2022 22:39:07 +0200 Subject: fixed possible kernel oops when unplugging device --- hid-tmff2.c | 9 ++++++--- hid-tmff2.h | 4 ++-- hid-tmt248.c | 16 +++++++++------- hid-tmt300rs.c | 12 +++++++----- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/hid-tmff2.c b/hid-tmff2.c index 4aa6141..d632b09 100644 --- a/hid-tmff2.c +++ b/hid-tmff2.c @@ -408,7 +408,7 @@ static void tmff2_close(struct input_dev *dev) return; if (tmff2->close) { - tmff2->close(tmff2->data); + tmff2->close(tmff2->data, tmff2->hdev != 0); return; } @@ -524,6 +524,7 @@ static int tmff2_wheel_init(struct tmff2_device_entry *tmff2) return 0; + input_ff_destroy(tmff2->input_dev); err: return ret; } @@ -611,7 +612,6 @@ static void tmff2_remove(struct hid_device *hdev) if (!tmff2) return; - cancel_delayed_work_sync(&tmff2->work); dev = &tmff2->hdev->dev; @@ -627,8 +627,11 @@ static void tmff2_remove(struct hid_device *hdev) if (tmff2->params & PARAM_ALT_MODE) device_remove_file(dev, &dev_attr_alt_mode); - tmff2->wheel_destroy(tmff2->data); + /* indicate that the underlying usb device should not be assumed to be + * accessible */ + tmff2->hdev = 0; hid_hw_stop(hdev); + tmff2->wheel_destroy(tmff2->data); kfree(tmff2->states); kfree(tmff2); diff --git a/hid-tmff2.h b/hid-tmff2.h index b396d78..4058cf7 100644 --- a/hid-tmff2.h +++ b/hid-tmff2.h @@ -79,7 +79,7 @@ struct tmff2_device_entry { /* optional callbacks */ int (*open)(void *data); - int (*close)(void *data); + int (*close)(void *data, int dev_accessible); int (*set_gain)(void *data, uint16_t gain); int (*set_range)(void *data, uint16_t range); int (*switch_mode)(void *data, uint16_t mode); @@ -123,7 +123,7 @@ int t300rs_update_effect(void *, struct tmff2_effect_state *); int t300rs_stop_effect(void *, struct tmff2_effect_state *); int t300rs_open(void *); -int t300rs_close(void *); +int t300rs_close(void *, int); int t300rs_set_gain(void *, uint16_t); int t300rs_set_range(void *, uint16_t); int t300rs_set_autocenter(void *, uint16_t); diff --git a/hid-tmt248.c b/hid-tmt248.c index f3d4700..839f670 100644 --- a/hid-tmt248.c +++ b/hid-tmt248.c @@ -254,19 +254,21 @@ static int t248_open(void *data) return t248->open(t248->input_dev); } -static int t248_close(void *data) +static int t248_close(void *data, int dev_accessible) { struct t300rs_device_entry *t248 = data; if (!t248) return -ENODEV; - t248->send_buffer[0] = 0x01; - t248->send_buffer[1] = 0x05; - t300rs_send_int(t248); + if (dev_accessible) { + t248->send_buffer[0] = 0x01; + t248->send_buffer[1] = 0x05; + t300rs_send_int(t248); - t248->send_buffer[0] = 0x01; - t248->send_buffer[1] = 0x00; - t300rs_send_int(t248); + t248->send_buffer[0] = 0x01; + t248->send_buffer[1] = 0x00; + t300rs_send_int(t248); + } t248->close(t248->input_dev); return 0; diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 167262c..c2a6c64 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1303,7 +1303,7 @@ int t300rs_open(void *data) return t300rs->open(t300rs->input_dev); } -int t300rs_close(void *data) +int t300rs_close(void *data, int dev_accessible) { struct t300rs_device_entry *t300rs = data; struct t300rs_packet_close { @@ -1314,11 +1314,13 @@ int t300rs_close(void *data) if (!t300rs) return -ENODEV; - close_packet = (struct t300rs_packet_close *)t300rs->send_buffer; - close_packet->header.cmd = 0x01; + if (dev_accessible) { + close_packet = (struct t300rs_packet_close *)t300rs->send_buffer; + close_packet->header.cmd = 0x01; - if ((ret = t300rs_send_int(t300rs))) - hid_warn(t300rs->hdev, "failed sending close command\n"); + if ((ret = t300rs_send_int(t300rs))) + hid_warn(t300rs->hdev, "failed sending close command\n"); + } t300rs->close(t300rs->input_dev); return ret; -- cgit v1.3