Commit 0365fb6b authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid

Pull HID fixes from Jiri Kosina:

 - HID++ device support regression fixes (race condition during cleanup,
   device detection fix, opps fix) from Andrey Smirnov

 - disable PM on i2c-hid, as it's causing problems with a lot of
   devices; other OSes apparently don't implement/enable it either; from
   Kai-Heng Feng

 - error handling fix in intel-ish driver, from Zhang Lixu

 - syzbot fuzzer fix for HID core code from Alan Stern

 - a few other tiny fixups (printk message cleanup, new device ID)

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid:
  HID: i2c-hid: add Trekstor Primebook C11B to descriptor override
  HID: logitech-hidpp: do all FF cleanup in hidpp_ff_destroy()
  HID: logitech-hidpp: rework device validation
  HID: logitech-hidpp: split g920_get_config()
  HID: i2c-hid: Remove runtime power management
  HID: intel-ish-hid: fix wrong error handling in ishtp_cl_alloc_tx_ring()
  HID: google: add magnemite/masterball USB ids
  HID: Fix assumption that devices have inputs
  HID: prodikeys: make array keys static const, makes object smaller
  HID: fix error message in hid_open_report()
parents 9e5eefba 09f3dbe4
...@@ -63,13 +63,20 @@ static int axff_init(struct hid_device *hid) ...@@ -63,13 +63,20 @@ static int axff_init(struct hid_device *hid)
{ {
struct axff_device *axff; struct axff_device *axff;
struct hid_report *report; struct hid_report *report;
struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list); struct hid_input *hidinput;
struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list; struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct input_dev *dev = hidinput->input; struct input_dev *dev;
int field_count = 0; int field_count = 0;
int i, j; int i, j;
int error; int error;
if (list_empty(&hid->inputs)) {
hid_err(hid, "no inputs found\n");
return -ENODEV;
}
hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
dev = hidinput->input;
if (list_empty(report_list)) { if (list_empty(report_list)) {
hid_err(hid, "no output reports found\n"); hid_err(hid, "no output reports found\n");
return -ENODEV; return -ENODEV;
......
...@@ -1139,6 +1139,7 @@ int hid_open_report(struct hid_device *device) ...@@ -1139,6 +1139,7 @@ int hid_open_report(struct hid_device *device)
__u8 *start; __u8 *start;
__u8 *buf; __u8 *buf;
__u8 *end; __u8 *end;
__u8 *next;
int ret; int ret;
static int (*dispatch_type[])(struct hid_parser *parser, static int (*dispatch_type[])(struct hid_parser *parser,
struct hid_item *item) = { struct hid_item *item) = {
...@@ -1192,7 +1193,8 @@ int hid_open_report(struct hid_device *device) ...@@ -1192,7 +1193,8 @@ int hid_open_report(struct hid_device *device)
device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
ret = -EINVAL; ret = -EINVAL;
while ((start = fetch_item(start, end, &item)) != NULL) { while ((next = fetch_item(start, end, &item)) != NULL) {
start = next;
if (item.format != HID_ITEM_FORMAT_SHORT) { if (item.format != HID_ITEM_FORMAT_SHORT) {
hid_err(device, "unexpected long global item\n"); hid_err(device, "unexpected long global item\n");
...@@ -1230,7 +1232,8 @@ int hid_open_report(struct hid_device *device) ...@@ -1230,7 +1232,8 @@ int hid_open_report(struct hid_device *device)
} }
} }
hid_err(device, "item fetching failed at offset %d\n", (int)(end - start)); hid_err(device, "item fetching failed at offset %u/%u\n",
size - (unsigned int)(end - start), size);
err: err:
kfree(parser->collection_stack); kfree(parser->collection_stack);
alloc_err: alloc_err:
......
...@@ -75,13 +75,19 @@ static int drff_init(struct hid_device *hid) ...@@ -75,13 +75,19 @@ static int drff_init(struct hid_device *hid)
{ {
struct drff_device *drff; struct drff_device *drff;
struct hid_report *report; struct hid_report *report;
struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input *hidinput;
struct hid_input, list);
struct list_head *report_list = struct list_head *report_list =
&hid->report_enum[HID_OUTPUT_REPORT].report_list; &hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct input_dev *dev = hidinput->input; struct input_dev *dev;
int error; int error;
if (list_empty(&hid->inputs)) {
hid_err(hid, "no inputs found\n");
return -ENODEV;
}
hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
dev = hidinput->input;
if (list_empty(report_list)) { if (list_empty(report_list)) {
hid_err(hid, "no output reports found\n"); hid_err(hid, "no output reports found\n");
return -ENODEV; return -ENODEV;
......
...@@ -47,13 +47,19 @@ static int emsff_init(struct hid_device *hid) ...@@ -47,13 +47,19 @@ static int emsff_init(struct hid_device *hid)
{ {
struct emsff_device *emsff; struct emsff_device *emsff;
struct hid_report *report; struct hid_report *report;
struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input *hidinput;
struct hid_input, list);
struct list_head *report_list = struct list_head *report_list =
&hid->report_enum[HID_OUTPUT_REPORT].report_list; &hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct input_dev *dev = hidinput->input; struct input_dev *dev;
int error; int error;
if (list_empty(&hid->inputs)) {
hid_err(hid, "no inputs found\n");
return -ENODEV;
}
hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
dev = hidinput->input;
if (list_empty(report_list)) { if (list_empty(report_list)) {
hid_err(hid, "no output reports found\n"); hid_err(hid, "no output reports found\n");
return -ENODEV; return -ENODEV;
......
...@@ -64,14 +64,20 @@ static int gaff_init(struct hid_device *hid) ...@@ -64,14 +64,20 @@ static int gaff_init(struct hid_device *hid)
{ {
struct gaff_device *gaff; struct gaff_device *gaff;
struct hid_report *report; struct hid_report *report;
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input *hidinput;
struct hid_input, list);
struct list_head *report_list = struct list_head *report_list =
&hid->report_enum[HID_OUTPUT_REPORT].report_list; &hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct list_head *report_ptr = report_list; struct list_head *report_ptr = report_list;
struct input_dev *dev = hidinput->input; struct input_dev *dev;
int error; int error;
if (list_empty(&hid->inputs)) {
hid_err(hid, "no inputs found\n");
return -ENODEV;
}
hidinput = list_entry(hid->inputs.next, struct hid_input, list);
dev = hidinput->input;
if (list_empty(report_list)) { if (list_empty(report_list)) {
hid_err(hid, "no output reports found\n"); hid_err(hid, "no output reports found\n");
return -ENODEV; return -ENODEV;
......
...@@ -469,6 +469,10 @@ static int hammer_probe(struct hid_device *hdev, ...@@ -469,6 +469,10 @@ static int hammer_probe(struct hid_device *hdev,
static const struct hid_device_id hammer_devices[] = { static const struct hid_device_id hammer_devices[] = {
{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) }, USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) },
{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MAGNEMITE) },
{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MASTERBALL) },
{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STAFF) }, USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STAFF) },
{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
......
...@@ -124,13 +124,19 @@ static int holtekff_init(struct hid_device *hid) ...@@ -124,13 +124,19 @@ static int holtekff_init(struct hid_device *hid)
{ {
struct holtekff_device *holtekff; struct holtekff_device *holtekff;
struct hid_report *report; struct hid_report *report;
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input *hidinput;
struct hid_input, list);
struct list_head *report_list = struct list_head *report_list =
&hid->report_enum[HID_OUTPUT_REPORT].report_list; &hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct input_dev *dev = hidinput->input; struct input_dev *dev;
int error; int error;
if (list_empty(&hid->inputs)) {
hid_err(hid, "no inputs found\n");
return -ENODEV;
}
hidinput = list_entry(hid->inputs.next, struct hid_input, list);
dev = hidinput->input;
if (list_empty(report_list)) { if (list_empty(report_list)) {
hid_err(hid, "no output report found\n"); hid_err(hid, "no output report found\n");
return -ENODEV; return -ENODEV;
......
...@@ -476,6 +476,8 @@ ...@@ -476,6 +476,8 @@
#define USB_DEVICE_ID_GOOGLE_STAFF 0x502b #define USB_DEVICE_ID_GOOGLE_STAFF 0x502b
#define USB_DEVICE_ID_GOOGLE_WAND 0x502d #define USB_DEVICE_ID_GOOGLE_WAND 0x502d
#define USB_DEVICE_ID_GOOGLE_WHISKERS 0x5030 #define USB_DEVICE_ID_GOOGLE_WHISKERS 0x5030
#define USB_DEVICE_ID_GOOGLE_MASTERBALL 0x503c
#define USB_DEVICE_ID_GOOGLE_MAGNEMITE 0x503d
#define USB_VENDOR_ID_GOTOP 0x08f2 #define USB_VENDOR_ID_GOTOP 0x08f2
#define USB_DEVICE_ID_SUPER_Q2 0x007f #define USB_DEVICE_ID_SUPER_Q2 0x007f
......
...@@ -50,11 +50,17 @@ int lg2ff_init(struct hid_device *hid) ...@@ -50,11 +50,17 @@ int lg2ff_init(struct hid_device *hid)
{ {
struct lg2ff_device *lg2ff; struct lg2ff_device *lg2ff;
struct hid_report *report; struct hid_report *report;
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input *hidinput;
struct hid_input, list); struct input_dev *dev;
struct input_dev *dev = hidinput->input;
int error; int error;
if (list_empty(&hid->inputs)) {
hid_err(hid, "no inputs found\n");
return -ENODEV;
}
hidinput = list_entry(hid->inputs.next, struct hid_input, list);
dev = hidinput->input;
/* Check that the report looks ok */ /* Check that the report looks ok */
report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7); report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7);
if (!report) if (!report)
......
...@@ -117,12 +117,19 @@ static const signed short ff3_joystick_ac[] = { ...@@ -117,12 +117,19 @@ static const signed short ff3_joystick_ac[] = {
int lg3ff_init(struct hid_device *hid) int lg3ff_init(struct hid_device *hid)
{ {
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); struct hid_input *hidinput;
struct input_dev *dev = hidinput->input; struct input_dev *dev;
const signed short *ff_bits = ff3_joystick_ac; const signed short *ff_bits = ff3_joystick_ac;
int error; int error;
int i; int i;
if (list_empty(&hid->inputs)) {
hid_err(hid, "no inputs found\n");
return -ENODEV;
}
hidinput = list_entry(hid->inputs.next, struct hid_input, list);
dev = hidinput->input;
/* Check that the report looks ok */ /* Check that the report looks ok */
if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35)) if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35))
return -ENODEV; return -ENODEV;
......
...@@ -1253,8 +1253,8 @@ static int lg4ff_handle_multimode_wheel(struct hid_device *hid, u16 *real_produc ...@@ -1253,8 +1253,8 @@ static int lg4ff_handle_multimode_wheel(struct hid_device *hid, u16 *real_produc
int lg4ff_init(struct hid_device *hid) int lg4ff_init(struct hid_device *hid)
{ {
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); struct hid_input *hidinput;
struct input_dev *dev = hidinput->input; struct input_dev *dev;
struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct hid_report *report = list_entry(report_list->next, struct hid_report, list); struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor); const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor);
...@@ -1266,6 +1266,13 @@ int lg4ff_init(struct hid_device *hid) ...@@ -1266,6 +1266,13 @@ int lg4ff_init(struct hid_device *hid)
int mmode_ret, mmode_idx = -1; int mmode_ret, mmode_idx = -1;
u16 real_product_id; u16 real_product_id;
if (list_empty(&hid->inputs)) {
hid_err(hid, "no inputs found\n");
return -ENODEV;
}
hidinput = list_entry(hid->inputs.next, struct hid_input, list);
dev = hidinput->input;
/* Check that the report looks ok */ /* Check that the report looks ok */
if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
return -1; return -1;
......
...@@ -115,12 +115,19 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude) ...@@ -115,12 +115,19 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude)
int lgff_init(struct hid_device* hid) int lgff_init(struct hid_device* hid)
{ {
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); struct hid_input *hidinput;
struct input_dev *dev = hidinput->input; struct input_dev *dev;
const signed short *ff_bits = ff_joystick; const signed short *ff_bits = ff_joystick;
int error; int error;
int i; int i;
if (list_empty(&hid->inputs)) {
hid_err(hid, "no inputs found\n");
return -ENODEV;
}
hidinput = list_entry(hid->inputs.next, struct hid_input, list);
dev = hidinput->input;
/* Check that the report looks ok */ /* Check that the report looks ok */
if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
return -ENODEV; return -ENODEV;
......
This diff is collapsed.
...@@ -328,11 +328,17 @@ static int ms_play_effect(struct input_dev *dev, void *data, ...@@ -328,11 +328,17 @@ static int ms_play_effect(struct input_dev *dev, void *data,
static int ms_init_ff(struct hid_device *hdev) static int ms_init_ff(struct hid_device *hdev)
{ {
struct hid_input *hidinput = list_entry(hdev->inputs.next, struct hid_input *hidinput;
struct hid_input, list); struct input_dev *input_dev;
struct input_dev *input_dev = hidinput->input;
struct ms_data *ms = hid_get_drvdata(hdev); struct ms_data *ms = hid_get_drvdata(hdev);
if (list_empty(&hdev->inputs)) {
hid_err(hdev, "no inputs found\n");
return -ENODEV;
}
hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
input_dev = hidinput->input;
if (!(ms->quirks & MS_QUIRK_FF)) if (!(ms->quirks & MS_QUIRK_FF))
return 0; return 0;
......
...@@ -516,7 +516,7 @@ static void pcmidi_setup_extra_keys( ...@@ -516,7 +516,7 @@ static void pcmidi_setup_extra_keys(
MY PICTURES => KEY_WORDPROCESSOR MY PICTURES => KEY_WORDPROCESSOR
MY MUSIC=> KEY_SPREADSHEET MY MUSIC=> KEY_SPREADSHEET
*/ */
unsigned int keys[] = { static const unsigned int keys[] = {
KEY_FN, KEY_FN,
KEY_MESSENGER, KEY_CALENDAR, KEY_MESSENGER, KEY_CALENDAR,
KEY_ADDRESSBOOK, KEY_DOCUMENTS, KEY_ADDRESSBOOK, KEY_DOCUMENTS,
...@@ -532,7 +532,7 @@ static void pcmidi_setup_extra_keys( ...@@ -532,7 +532,7 @@ static void pcmidi_setup_extra_keys(
0 0
}; };
unsigned int *pkeys = &keys[0]; const unsigned int *pkeys = &keys[0];
unsigned short i; unsigned short i;
if (pm->ifnum != 1) /* only set up ONCE for interace 1 */ if (pm->ifnum != 1) /* only set up ONCE for interace 1 */
......
...@@ -2254,9 +2254,15 @@ static int sony_play_effect(struct input_dev *dev, void *data, ...@@ -2254,9 +2254,15 @@ static int sony_play_effect(struct input_dev *dev, void *data,
static int sony_init_ff(struct sony_sc *sc) static int sony_init_ff(struct sony_sc *sc)
{ {
struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, struct hid_input *hidinput;
struct hid_input, list); struct input_dev *input_dev;
struct input_dev *input_dev = hidinput->input;
if (list_empty(&sc->hdev->inputs)) {
hid_err(sc->hdev, "no inputs found\n");
return -ENODEV;
}
hidinput = list_entry(sc->hdev->inputs.next, struct hid_input, list);
input_dev = hidinput->input;
input_set_capability(input_dev, EV_FF, FF_RUMBLE); input_set_capability(input_dev, EV_FF, FF_RUMBLE);
return input_ff_create_memless(input_dev, NULL, sony_play_effect); return input_ff_create_memless(input_dev, NULL, sony_play_effect);
......
...@@ -124,12 +124,18 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits) ...@@ -124,12 +124,18 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
struct tmff_device *tmff; struct tmff_device *tmff;
struct hid_report *report; struct hid_report *report;
struct list_head *report_list; struct list_head *report_list;
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input *hidinput;
struct hid_input, list); struct input_dev *input_dev;
struct input_dev *input_dev = hidinput->input;
int error; int error;
int i; int i;
if (list_empty(&hid->inputs)) {
hid_err(hid, "no inputs found\n");
return -ENODEV;
}
hidinput = list_entry(hid->inputs.next, struct hid_input, list);
input_dev = hidinput->input;
tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL);
if (!tmff) if (!tmff)
return -ENOMEM; return -ENOMEM;
......
...@@ -54,11 +54,17 @@ static int zpff_init(struct hid_device *hid) ...@@ -54,11 +54,17 @@ static int zpff_init(struct hid_device *hid)
{ {
struct zpff_device *zpff; struct zpff_device *zpff;
struct hid_report *report; struct hid_report *report;
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input *hidinput;
struct hid_input, list); struct input_dev *dev;
struct input_dev *dev = hidinput->input;
int i, error; int i, error;
if (list_empty(&hid->inputs)) {
hid_err(hid, "no inputs found\n");
return -ENODEV;
}
hidinput = list_entry(hid->inputs.next, struct hid_input, list);
dev = hidinput->input;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1); report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1);
if (!report) if (!report)
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/err.h> #include <linux/err.h>
...@@ -48,8 +47,6 @@ ...@@ -48,8 +47,6 @@
/* quirks to control the device */ /* quirks to control the device */
#define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV BIT(0) #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV BIT(0)
#define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET BIT(1) #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET BIT(1)
#define I2C_HID_QUIRK_NO_RUNTIME_PM BIT(2)
#define I2C_HID_QUIRK_DELAY_AFTER_SLEEP BIT(3)
#define I2C_HID_QUIRK_BOGUS_IRQ BIT(4) #define I2C_HID_QUIRK_BOGUS_IRQ BIT(4)
/* flags */ /* flags */
...@@ -172,14 +169,7 @@ static const struct i2c_hid_quirks { ...@@ -172,14 +169,7 @@ static const struct i2c_hid_quirks {
{ USB_VENDOR_ID_WEIDA, HID_ANY_ID, { USB_VENDOR_ID_WEIDA, HID_ANY_ID,
I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV }, I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
{ I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288, { I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288,
I2C_HID_QUIRK_NO_IRQ_AFTER_RESET | I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
I2C_HID_QUIRK_NO_RUNTIME_PM },
{ I2C_VENDOR_ID_RAYDIUM, I2C_PRODUCT_ID_RAYDIUM_4B33,
I2C_HID_QUIRK_DELAY_AFTER_SLEEP },
{ USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_8001,
I2C_HID_QUIRK_NO_RUNTIME_PM },
{ I2C_VENDOR_ID_GOODIX, I2C_DEVICE_ID_GOODIX_01F0,
I2C_HID_QUIRK_NO_RUNTIME_PM },
{ USB_VENDOR_ID_ELAN, HID_ANY_ID, { USB_VENDOR_ID_ELAN, HID_ANY_ID,
I2C_HID_QUIRK_BOGUS_IRQ }, I2C_HID_QUIRK_BOGUS_IRQ },
{ 0, 0 } { 0, 0 }
...@@ -397,7 +387,6 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state) ...@@ -397,7 +387,6 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state)
{ {
struct i2c_hid *ihid = i2c_get_clientdata(client); struct i2c_hid *ihid = i2c_get_clientdata(client);
int ret; int ret;
unsigned long now, delay;
i2c_hid_dbg(ihid, "%s\n", __func__); i2c_hid_dbg(ihid, "%s\n", __func__);
...@@ -415,22 +404,9 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state) ...@@ -415,22 +404,9 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state)
goto set_pwr_exit; goto set_pwr_exit;
} }
if (ihid->quirks & I2C_HID_QUIRK_DELAY_AFTER_SLEEP &&
power_state == I2C_HID_PWR_ON) {
now = jiffies;
if (time_after(ihid->sleep_delay, now)) {
delay = jiffies_to_usecs(ihid->sleep_delay - now);
usleep_range(delay, delay + 1);
}
}
ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state, ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state,
0, NULL, 0, NULL, 0); 0, NULL, 0, NULL, 0);
if (ihid->quirks & I2C_HID_QUIRK_DELAY_AFTER_SLEEP &&
power_state == I2C_HID_PWR_SLEEP)
ihid->sleep_delay = jiffies + msecs_to_jiffies(20);
if (ret) if (ret)
dev_err(&client->dev, "failed to change power setting.\n"); dev_err(&client->dev, "failed to change power setting.\n");
...@@ -791,11 +767,6 @@ static int i2c_hid_open(struct hid_device *hid) ...@@ -791,11 +767,6 @@ static int i2c_hid_open(struct hid_device *hid)
{ {
struct i2c_client *client = hid->driver_data; struct i2c_client *client = hid->driver_data;
struct i2c_hid *ihid = i2c_get_clientdata(client); struct i2c_hid *ihid = i2c_get_clientdata(client);
int ret = 0;
ret = pm_runtime_get_sync(&client->dev);
if (ret < 0)
return ret;
set_bit(I2C_HID_STARTED, &ihid->flags); set_bit(I2C_HID_STARTED, &ihid->flags);
return 0; return 0;
...@@ -807,27 +778,6 @@ static void i2c_hid_close(struct hid_device *hid) ...@@ -807,27 +778,6 @@ static void i2c_hid_close(struct hid_device *hid)
struct i2c_hid *ihid = i2c_get_clientdata(client); struct i2c_hid *ihid = i2c_get_clientdata(client);
clear_bit(I2C_HID_STARTED, &ihid->flags); clear_bit(I2C_HID_STARTED, &ihid->flags);
/* Save some power */
pm_runtime_put(&client->dev);
}
static int i2c_hid_power(struct hid_device *hid, int lvl)
{
struct i2c_client *client = hid->driver_data;
struct i2c_hid *ihid = i2c_get_clientdata(client);
i2c_hid_dbg(ihid, "%s lvl:%d\n", __func__, lvl);
switch (lvl) {
case PM_HINT_FULLON:
pm_runtime_get_sync(&client->dev);
break;
case PM_HINT_NORMAL:
pm_runtime_put(&client->dev);
break;
}
return 0;
} }
struct hid_ll_driver i2c_hid_ll_driver = { struct hid_ll_driver i2c_hid_ll_driver = {
...@@ -836,7 +786,6 @@ struct hid_ll_driver i2c_hid_ll_driver = { ...@@ -836,7 +786,6 @@ struct hid_ll_driver i2c_hid_ll_driver = {
.stop = i2c_hid_stop, .stop = i2c_hid_stop,
.open = i2c_hid_open, .open = i2c_hid_open,
.close = i2c_hid_close, .close = i2c_hid_close,
.power = i2c_hid_power,
.output_report = i2c_hid_output_report, .output_report = i2c_hid_output_report,
.raw_request = i2c_hid_raw_request, .raw_request = i2c_hid_raw_request,
}; };
...@@ -1104,9 +1053,6 @@ static int i2c_hid_probe(struct i2c_client *client, ...@@ -1104,9 +1053,6 @@ static int i2c_hid_probe(struct i2c_client *client,
i2c_hid_acpi_fix_up_power(&client->dev); i2c_hid_acpi_fix_up_power(&client->dev);
pm_runtime_get_noresume(&client->dev);
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
device_enable_async_suspend(&client->dev); device_enable_async_suspend(&client->dev);
/* Make sure there is something at this address */ /* Make sure there is something at this address */
...@@ -1114,16 +1060,16 @@ static int i2c_hid_probe(struct i2c_client *client, ...@@ -1114,16 +1060,16 @@ static int i2c_hid_probe(struct i2c_client *client,
if (ret < 0) { if (ret < 0) {
dev_dbg(&client->dev, "nothing at this address: %d\n", ret); dev_dbg(&client->dev, "nothing at this address: %d\n", ret);
ret = -ENXIO; ret = -ENXIO;
goto err_pm; goto err_regulator;
} }
ret = i2c_hid_fetch_hid_descriptor(ihid); ret = i2c_hid_fetch_hid_descriptor(ihid);
if (ret < 0) if (ret < 0)
goto err_pm; goto err_regulator;
ret = i2c_hid_init_irq(client); ret = i2c_hid_init_irq(client);
if (ret < 0) if (ret < 0)
goto err_pm; goto err_regulator;
hid = hid_allocate_device(); hid = hid_allocate_device();
if (IS_ERR(hid)) { if (IS_ERR(hid)) {
...@@ -1154,9 +1100,6 @@ static int i2c_hid_probe(struct i2c_client *client, ...@@ -1154,9 +1100,6 @@ static int i2c_hid_probe(struct i2c_client *client,
goto err_mem_free; goto err_mem_free;
} }
if (!(ihid->quirks & I2C_HID_QUIRK_NO_RUNTIME_PM))
pm_runtime_put(&client->dev);
return 0; return 0;
err_mem_free: err_mem_free:
...@@ -1165,10 +1108,6 @@ static int i2c_hid_probe(struct i2c_client *client, ...@@ -1165,10 +1108,6 @@ static int i2c_hid_probe(struct i2c_client *client,
err_irq: err_irq:
free_irq(client->irq, ihid); free_irq(client->irq, ihid);
err_pm:
pm_runtime_put_noidle(&client->dev);
pm_runtime_disable(&client->dev);
err_regulator: err_regulator:
regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies), regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies),
ihid->pdata.supplies); ihid->pdata.supplies);
...@@ -1181,12 +1120,6 @@ static int i2c_hid_remove(struct i2c_client *client) ...@@ -1181,12 +1120,6 @@ static int i2c_hid_remove(struct i2c_client *client)
struct i2c_hid *ihid = i2c_get_clientdata(client); struct i2c_hid *ihid = i2c_get_clientdata(client);
struct hid_device *hid; struct hid_device *hid;
if (!(ihid->quirks & I2C_HID_QUIRK_NO_RUNTIME_PM))
pm_runtime_get_sync(&client->dev);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
pm_runtime_put_noidle(&client->dev);
hid = ihid->hid; hid = ihid->hid;
hid_destroy_device(hid); hid_destroy_device(hid);
...@@ -1219,25 +1152,15 @@ static int i2c_hid_suspend(struct device *dev) ...@@ -1219,25 +1152,15 @@ static int i2c_hid_suspend(struct device *dev)
int wake_status; int wake_status;
if (hid->driver && hid->driver->suspend) { if (hid->driver && hid->driver->suspend) {
/*
* Wake up the device so that IO issues in
* HID driver's suspend code can succeed.
*/
ret = pm_runtime_resume(dev);
if (ret < 0)
return ret;
ret = hid->driver->suspend(hid, PMSG_SUSPEND); ret = hid->driver->suspend(hid, PMSG_SUSPEND);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
if (!pm_runtime_suspended(dev)) {
/* Save some power */ /* Save some power */
i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
disable_irq(client->irq); disable_irq(client->irq);
}
if (device_may_wakeup(&client->dev)) { if (device_may_wakeup(&client->dev)) {
wake_status = enable_irq_wake(client->irq); wake_status = enable_irq_wake(client->irq);
...@@ -1279,11 +1202,6 @@ static int i2c_hid_resume(struct device *dev) ...@@ -1279,11 +1202,6 @@ static int i2c_hid_resume(struct device *dev)
wake_status); wake_status);
} }
/* We'll resume to full power */
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
enable_irq(client->irq); enable_irq(client->irq);
/* Instead of resetting device, simply powers the device on. This /* Instead of resetting device, simply powers the device on. This
...@@ -1304,30 +1222,8 @@ static int i2c_hid_resume(struct device *dev) ...@@ -1304,30 +1222,8 @@ static int i2c_hid_resume(struct device *dev)
} }
#endif #endif
#ifdef CONFIG_PM
static int i2c_hid_runtime_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
disable_irq(client->irq);
return 0;
}
static int i2c_hid_runtime_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
enable_irq(client->irq);
i2c_hid_set_power(client, I2C_HID_PWR_ON);
return 0;
}
#endif
static const struct dev_pm_ops i2c_hid_pm = { static const struct dev_pm_ops i2c_hid_pm = {
SET_SYSTEM_SLEEP_PM_OPS(i2c_hid_suspend, i2c_hid_resume) SET_SYSTEM_SLEEP_PM_OPS(i2c_hid_suspend, i2c_hid_resume)
SET_RUNTIME_PM_OPS(i2c_hid_runtime_suspend, i2c_hid_runtime_resume,
NULL)
}; };
static const struct i2c_device_id i2c_hid_id_table[] = { static const struct i2c_device_id i2c_hid_id_table[] = {
......
...@@ -322,6 +322,25 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = { ...@@ -322,6 +322,25 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
}, },
.driver_data = (void *)&sipodev_desc .driver_data = (void *)&sipodev_desc
}, },
{
/*
* There are at least 2 Primebook C11B versions, the older
* version has a product-name of "Primebook C11B", and a
* bios version / release / firmware revision of:
* V2.1.2 / 05/03/2018 / 18.2
* The new version has "PRIMEBOOK C11B" as product-name and a
* bios version / release / firmware revision of:
* CFALKSW05_BIOS_V1.1.2 / 11/19/2018 / 19.2
* Only the older version needs this quirk, note the newer
* version will not match as it has a different product-name.
*/
.ident = "Trekstor Primebook C11B",
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Primebook C11B"),
},
.driver_data = (void *)&sipodev_desc
},
{ {
.ident = "Direkt-Tek DTLAPY116-2", .ident = "Direkt-Tek DTLAPY116-2",
.matches = { .matches = {
......
...@@ -84,7 +84,7 @@ int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl) ...@@ -84,7 +84,7 @@ int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl)
return 0; return 0;
out: out:
dev_err(&cl->device->dev, "error in allocating Tx pool\n"); dev_err(&cl->device->dev, "error in allocating Tx pool\n");
ishtp_cl_free_rx_ring(cl); ishtp_cl_free_tx_ring(cl);
return -ENOMEM; return -ENOMEM;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment